ios 如何使用 Magical Record 创建和更新对象并在不使用 contextForCurrentThread 的情况下保存它们

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19251246/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:12:39  来源:igfitidea点击:

How do I use Magical Record to create & update objects and save them without using contextForCurrentThread

ioscore-datarubymotionmagicalrecord

提问by Paul Sturgess

I just read the author of MagicalRecord's blog post on Why contextForCurrentThread Doesn't work in MagicalRecord.

我刚刚阅读了 MagicalRecord 博客文章的作者,关于为什么 contextForCurrentThread 在 MagicalRecord 中不起作用

contextForCurrentThreadis deprecated and saveWithBlockshould be used instead because it creates a safe new NSManagedObjectContextfor the relevant thread.

contextForCurrentThread已弃用,saveWithBlock应改为使用,因为它NSManagedObjectContext为相关线程创建了一个安全的新线程。

I've been using contextForCurrentThreadextensively in my app so far. However, I'm having trouble figuring out how to use saveWithBlockinstead as my fetching and saving are not necessarily happening sequentially.

contextForCurrentThread到目前为止,我一直在我的应用程序中广泛使用。但是,我无法弄清楚如何使用,saveWithBlock因为我的获取和保存不一定按顺序发生。

Currently I'm doing things like:

目前我正在做这样的事情:

localContext = NSManagedObjectContext.MR_contextForCurrentThread
person = Person.MR_createInContext(localContext)
person.name = "John Smith"

The user may then browse around the app, different controllers, views etc. are displayed. Other objects may be created using a similar method to the code above.

然后用户可以浏览应用程序,显示不同的控制器、视图等。可以使用与上述代码类似的方法创建其他对象。

Then at some arbitrary point in the future, when the user decides to save, I run this method:

然后在将来的某个任意时刻,当用户决定保存时,我运行此方法:

localContext = NSManagedObjectContext.MR_contextForCurrentThread
localContext.MR_saveToPersistentStoreWithCompletion(
  lambda { |success, error|
    # ...
  }
)

What is the recommended way to create & update objects and then save them without using contextForCurrentThread?

创建和更新对象然后在不使用的情况下保存它们的推荐方法是什么contextForCurrentThread

采纳答案by casademora

So, I use objective C as opposed to RubyMotion, but you should be able todo things like this:

因此,我使用目标 C 而不是 RubyMotion,但您应该能够执行以下操作:

MagicalRecord.saveWithBlock(
   lambda { |localContext|
       person = Person.MR_createInContext(localContext)
       #update person stuff here
   }
)

EDIT

编辑

If you want to save the context later, you just need to hold on to it:

如果你想稍后保存上下文,你只需要坚持下去:

// Somewhere in your ViewController, etc
NSManagedObjectContext *context = [NSManagedObjectContext MR_confinementContext];


// Somewhere else
Person *p = [Person MR_createInContext:context];

// And in yet another method
[context MR_saveToPersistentStoreAndWait];

The main idea here is that you just need to hold on to the context and perform your operations on it when you're ready. If you want a background save to occur, you an use the following method:

这里的主要思想是,您只需要保持上下文并在准备好时对其执行操作。如果要进行后台保存,可以使用以下方法:

[context MR_saveToPersistentStoreCompletion:^(BOOL success, NSError *error){
   //called on the main thread when save is complete
}];

回答by lbsweek

here is a tutorial for new api: http://ablfx.com/blog/article/2here is the refence: http://cocoadocs.org/docsets/MagicalRecord/2.1/

这是新 api 的教程:http://ablfx.com/blog/article/2 这里是参考:http://cocoadocs.org/docsets/MagicalRecord/2.1/

  1. init

    [MagicalRecord setupCoreDataStackWithStoreNamed:@"MyDatabase.sqlite"];

  2. dealloc

    [MagicalRecord cleanUp];

  3. insert

    Person *alex = [Person MR_createEntity]; alex.name = @"Alex"; alex.age = @23;

  4. select

    /Retrieve all for aNSManagedObject subclass NSArray *people = [Person MR_findAll];

    //Retrieve first record Person *aPerson = [Person MR_findFirst];

    //Retrieve records conditionally & sort NSArray *people = [Person MR_findByAttribute:@"name" withValue:@"alex" andOrderBy:@"age" ascending:YES];

  5. update

    //Updating a retrieved entity is as easy as manipulating it's properties aPerson.age = @56;

  6. delete

    //Remove all records [Person MR_truncateAll];

    //Delete single record, after retrieving it [alex MR_deleteEntity];

  7. save

    //For any entities to actually be saved / updated / deleted on disk call following method [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

    //Again check the MagicalRecord repo for more save options

  1. 在里面

    [MagicalRecord setupCoreDataStackWithStoreNamed:@"MyDatabase.sqlite"];

  2. 解除分配

    [MagicalRecord cleanUp];

  3. 插入

    Person *alex = [Person MR_createEntity]; alex.name = @"Alex"; alex.age = @23;

  4. 选择

    / 检索所有的 NSManagedObject 子类 NSArray *people = [Person MR_findAll];

    //获取第一条记录 Person *aPerson = [Person MR_findFirst];

    //有条件地检索记录并排序 NSArray *people = [Person MR_findByAttribute:@"name" withValue:@"alex" andOrderBy:@"age" ascending:YES];

  5. 更新

    //更新检索到的实体就像操作它的属性一样简单 aPerson.age = @56;

  6. 删除

    //删除所有记录 [Person MR_truncateAll];

    //删除单条记录,取回后 [alex MR_deleteEntity];

  7. 节省

    //对于要在磁盘上实际保存/更新/删除的任何实体调用以下方法 [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

    //再次检查 MagicalRecord 存储库以获得更多保存选项

回答by Arek Holko

I might be mistaken here, but I think that Magical Record isn't prepared for this use case.Here's how I'd do what you want in pure Core Data:

我可能在这里弄错了,但我认为 Magical Record 没有为这个用例做好准备。这是我在纯核心数据中做你想做的事情:

  1. Create an independent or nested context and keep somewhere (AppDelegate, singleton object, etc.) a reference to it
  2. Do the insertions, reads, updates and deletions with performBlock:and performBlockAndWait:
  3. Save the context with:

    [context performBlock:^{
        ZAssert([context save:&error], @"Save failed: %@\n%@", [error localizedDescription], [error userInfo]);
    }];
    
  1. 创建一个独立的或嵌套的上下文并在某处(AppDelegate、单例对象等)保留对它的引用
  2. 执行插入,读取,更新和删除与performBlock:performBlockAndWait:
  3. 使用以下命令保存上下文:

    [context performBlock:^{
        ZAssert([context save:&error], @"Save failed: %@\n%@", [error localizedDescription], [error userInfo]);
    }];
    

This seems to be the standard approach to these kind of problems. It's nicely described online, e.g. Common Background Practices - Core Data in the Background.

这似乎是解决此类问题的标准方法。它在网上很好地描述,例如Common Background Practices - Core Data in the Background