【问题标题】:awakeFromInsert called twice with nested contextsawakeFromInsert 使用嵌套上下文调用了两次
【发布时间】:2013-11-10 19:00:20
【问题描述】:

本项目使用 Mogenerator 和 Magical Record。我已经找到了一个错误,即awakeFromInsert 被调用了两次。我假设我的每个上下文都有一次。这是一个问题,因为我需要像这样在这个 NSManagedObject 上监听 NSNotifications:

- (void)awakeFromInsert
{
    // Listen for a return from background mode
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enteringForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}

但是 awakeFromInsert get 被调用了两次,这很烦人。我想在第一次创建 NSManagedObject 时调用一次方法。

搜索this solution seems to make a lot of sense后。但是,当使用 Mogenerator 和 MagicalRecord 时,我看不到如何将类别添加到 NSManagedObject 上。没有一些复杂的覆盖。

在 MagicalRecord 中MR_createEntity 调用

if ([self respondsToSelector:@selector(insertInManagedObjectContext:)]) 
    {
        id entity = [self performSelector:@selector(insertInManagedObjectContext:) withObject:context];
        return entity;
    }

这个问题有更简洁的解决方案吗?

【问题讨论】:

  • Mogenerator 为每个实体创建两个类,一个“机器”类和一个“人类”类。您可以根据需要向“人类”类添加方法,而无需类别。
  • 谢谢。是的,我已经这样做了。我想这里的问题是我需要 MagicalRecord 来调用我的新方法,而不是如上所示的 insertInManagedObjectContext。
  • 我还不明白“awakeFromFetch 调用了两次”问题和insertInManagedObjectContext:(这可能是我的错)之间的关系。 - 但是你不能在“人类”实体类中覆盖insertInManagedObjectContext:吗?
  • 对不起马丁,我的错误代码示例应该都显示 awakeFromInsert。由 insertInManagedObjectContext: 调用,然后对于 MR 保存的每个上下文。到目前为止,AFAIK。
  • 似乎用 Mogenerator 覆盖 insertInManagedObjectContext: 效果不太好 - stackoverflow.com/questions/16430005/…

标签: objective-c core-data mogenerator magicalrecord-2.1


【解决方案1】:

好吧,这感觉很hacky,但似乎工作。我在人类可读的 NSManagedObject 类上创建了以下类方法:

+ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ {

    JWBoard *newobject = [super insertInManagedObjectContext:moc_];
    [JWBoard awakeFromCreate:newobject];
    return newobject;
}

+ (void)awakeFromCreate:(JWBoard *)board
{
    // do setup stuff & add observers
}

接受更好的解决方案!

【讨论】:

  • 感谢这段代码——只要你也使用 MOGenerator 的insertInManagedObjectContext 就可以很好地工作——我确实必须搜索我的项目并在我使用 entityDescriptionForName 的所有地方进行分析,以确保我没有做插入非 MOGenerator 方式。
【解决方案2】:

接受更好的解决方案!

我希望!苹果调用 awakeFromInsert 或至少提供一个在“parentProcessSaveRequest”上下文中为真的标志已经足够容易了。如果您查看对awakeFromInsert 的非首次调用的调用堆栈,堆栈始终包含parentProcessSaveRequest

这里有一些糟糕的代码证明了这一点:

- (void) awakeFromInsert 
{
    [super awakeFromInsert];

    NSArray* stackArray = [NSThread callStackSymbols];
    for (NSString* method in stackArray)
    {
        if ([method rangeOfString:@"_parentProcessSaveRequest"].location != NSNotFound)
        {
            NSLog(@"Parent insert %@",self.objectID);
            return;
        }        
    }
    NSLog(@"First insert %@",self.objectID);
    // Initialize here

}

而且日志输出——objectId 保持不变:

2014-05-19 20:53:52.964 myApp[1891:a01f] First insert 0x6000000326c0 <x-coredata:///MyEntity/t496E9B17-E170-4A7C-B7D4-7D8B92433E1C2>
2014-05-19 20:53:53.531 myApp[1891:303] Parent insert 0xdca8000eb <x-coredata://7274869F-4BF3-4B8A-9270-A64E54476AAD/MyEntity/p14122>
2014-05-19 20:53:53.537 myApp[1891:303] Parent insert 0xdca8000eb <x-coredata://7274869F-4BF3-4B8A-9270-A64E54476AAD/MyEntity/p14122>

似乎可以保存到我拥有的任何嵌套上下文中,尽管它很丑。

不幸的是,我想不出任何合理的方法来确定是否在 parentProcessSaveRequest 的上下文中调用了 awakeFromInsert。加油,苹果!在这里给我们一面旗帜。

【讨论】:

    【解决方案3】:

    这是最简单的一个: 当 parentContext 为 null 时,意味着当保存此上下文时,您可以执行自定义逻辑,例如递增表号

    - (void)awakeFromInsert
     {
    
         if (!self.managedObjectContext.parentContext) {
             //setting tableNumber
    
             [self willChangeValueForKey:@"number"];
             [self setPrimitiveNumber:tableNumber];
             [self didChangeValueForKey:@"number"];
        }
    
     }
    

    【讨论】:

      猜你喜欢
      • 2013-11-20
      • 1970-01-01
      • 2017-06-25
      • 2013-01-21
      • 2012-09-08
      • 2016-04-27
      • 2019-02-27
      • 1970-01-01
      • 2019-12-04
      相关资源
      最近更新 更多