最近、RubyMotion 向けのラッパー gem じゃなくて、 Objective-C のライブラリを使ったほうがいいのでは、って思うようになってきた。 CoreData なら MotionData や MotionDataWrapper じゃなくて MagicalRecord。
そこで RubyMotion で MagicalRecord が使えるか試してみる。
まず CocoaPods で MagicalRecord を追加する。 motion-cocoapods を使っているから、Rakefile に
Motion::Project::App.setup do |app| app.name = 'MagicalRecordSample' # CocoaPods で MagicalRecord をインストール app.pods do pod 'MagicalRecord' end end
を記述して
bundle exec rake pod:install
を実行。
次に Xcode で Empty プロジェクトを作成する。
プロジェクトに Data Modelファイルを追加。ファイルの保存先は resources 直下で、 ファイル名は Model のままにしておく。
エンティティを定義したら Xcode での作業は終了。
MagicalRecord を使って RubyMotion のサンプルを書いてみる。
# coding: utf-8 class Task < NSManagedObject end class TasksViewController < UITableViewController def viewDidLoad super self.navigationItem.title = "Tasks" self.navigationItem.rightBarButtonItem = UIBarButtonItem.alloc.initWithBarButtonSystemItem( UIBarButtonSystemItemAdd, target: self, action: "add_task" ) self.navigationItem.leftBarButtonItem = self.editButtonItem end def tasks @tasks ||= Task.MR_findAll end def add_task task = Task.MR_createEntity task.title = "test" task.createdAt = NSDate.date NSManagedObjectContext.MR_defaultContext.MR_saveToPersistentStoreAndWait @tasks = nil self.tableView.reloadData end def tableView(tableView, numberOfRowsInSection:section) self.tasks.size end def tableView(tableView, cellForRowAtIndexPath:indexPath) task = self.tasks[indexPath.row] cell = tableView.dequeueReusableCellWithIdentifier("Cell") if cell == nil cell = UITableViewCell.alloc.initWithStyle( UITableViewCellStyleDefault, reuseIdentifier:"Cell" ) end cell.textLabel.text = task.title cell end def tableView(tableView, commitEditingStyle:editingStyle, forRowAtIndexPath:indexPath) if editingStyle == UITableViewCellEditingStyleDelete task = self.tasks[indexPath.row] delete_task(task) tableView.deleteRowsAtIndexPaths( [indexPath], withRowAnimation:UITableViewRowAnimationFade ) end end def delete_task(task) task.MR_deleteEntity NSManagedObjectContext.MR_defaultContext.MR_saveToPersistentStoreAndWait @tasks = nil end end class AppDelegate def application(application, didFinishLaunchingWithOptions:launchOptions) MagicalRecord.setupCoreDataStackWithStoreNamed("Sample.sqlite") @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) @window.rootViewController = UINavigationController.alloc.initWithRootViewController( TasksViewController.alloc.init ) @window.makeKeyAndVisible true end def applicationWillTerminate(application) MagicalRecord.cleanUp end end
MagicalRecord のメソッドを呼び出すだけで CoreData の初期化ができるから、コードがすっきりした。 MotionDataWrapper を使ったときと大差ない。
RubyMotion で CoreData ばっかり扱ってきた気がするけど、それも今回が最後になるかな。