NSInternalInconsistencyException 递归弄脏混乱

Posted

技术标签:

【中文标题】NSInternalInconsistencyException 递归弄脏混乱【英文标题】:NSInternalInconsistencyException recursive dirtying confusion 【发布时间】:2012-12-01 00:27:18 【问题描述】:

我正在努力找出我在使用核心数据时遇到的问题。我了解错误的含义,并且我之前遇到过(并已修复),但我不知道为什么现在会遇到。

我的应用具有以下结构:

MPModel -> MPPlace 和 MPModel -> MPProject

其中 MPModel 是 NSManagedObject 的子类,MPPlace 和 MPProject 是 MPModel 的子类。

数据模型在MPPlace和MPProject之间有关系,其中MPPlace有-许多MPProject,MPProject属于-MPPlace。

当应用加载时,它会获取许多运行良好的 MPPlace 对象。当用户选择一个地点然后选择项目选项时,应用程序会尝试检索项目列表。然而,这是应用程序失败的地方,并出现以下错误

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:
'Failed to process pending changes before save.  The context is still dirty after 100 
attempts.  Typically this recursive dirtying is caused by a bad validation method, 
willSave, or notification handler.'

每个 MPModel 都包含许多自定义方法,包括 saveAllLocally (如果对象数组不存在的话,它只是将对象数组保存到持久性存储中),以及 loadNestedResources (从服务器获取与当前对象相关的新对象)。我发现 loadNestedResources 方法发生了故障,但我不知道为什么。

loadNestedResources 方法如下所示:

- (void) loadNestedResourcesOfType:(Class)type atURL:(NSString *)resURL withBlock:(MPFindObjectsBlock)block

    if (![type isSubclassOfClass:[MPModel class]]) 
        block(nil, nil);
     else 
             NSString *url = [NSString stringWithFormat:@"%@%@/%@%@", kMP_BASE_API_URL, [self.class baseURL], self.objID, [type baseURL]];
        MPRequest *request = [[MPRequest alloc] initWithURL:url];

        // Attempt to see if we already have this relation
           NSString *relation = [[MPUtils stripClassName:type].lowercaseString stringByAppendingString:@"s"];
        NSSet *relatedObjects = [self valueForKey:relation];

        if (relatedObjects && relatedObjects.count > 0) 
            // We have some objects so lets exclude these from our request
            NSMutableArray *uuids = [NSMutableArray arrayWithCapacity:0];
            for (MPModel *obj in relatedObjects) 
                [uuids addObject:obj.uuid];
            

            [request setParam:[uuids componentsJoinedByString:@";"] forKey:@"exclude_uuids"];
        

        [MPUser signRequest:request];
        [request setRequestMethod:@"POST"];
        [request submit:^(MPResponse *resp, NSError *error) 
            if (error) 
                if (relatedObjects.count > 0) 
                    block([relatedObjects allObjects], nil);
                 else 
                    block(nil, error);
                
             else 
                // Combine all of our objects
                NSMutableArray *allObjects = [[type createListWithResponse:resp] mutableCopy];
                if (allObjects.count > 0) 
                    [allObjects addObjectsFromArray:[relatedObjects allObjects]];

                    // Make sure they're now all saved in the persistence store
                    NSArray *savedObjects = [MPModel saveAllLocally:allObjects forEntityName:NSStringFromClass(type)];
                    for (NSObject *obj in savedObjects) 
                        [obj setValue:self forKey:[MPUtils stripClassName:self.class].lowercaseString];
                    

                    // Set them as our related objects for this relationship
                    [self setValue:[NSSet setWithArray:savedObjects] forKey:relation];

                    [MPModel saveAllLocally:savedObjects forEntityName:NSStringFromClass(type)];
                    block(allObjects, nil);
                 else 
                    block([relatedObjects allObjects], nil);
                
            

        ];
    

在第二次调用 saveAllLocally 之前,这些方法运行完美,这是我得到错误的地方。 MPModel 类还使用 willSave 方法,该方法具有以下内容:

- (void) willSave

    NSDate *now = [NSDate date];

    if (!self.updated_at) 
        self.updated_at = now;
    

    if (!self.created_at) 
        self.created_at = now;
    

    if (!self.uuid) 
        self.uuid = [self createUUID];
    

    if (!self.last_sync) 
        self.last_sync = now;
    

    if ([self isUpdated] && self.changedValues.count > 0) 

        if (!self.attribute_updated_at) 
            NSDictionary *attributes = [self.entity attributesByName];
            NSMutableDictionary *dates = [NSMutableDictionary dictionaryWithCapacity:0];
            for (NSString *attr in attributes.allKeys) 
                [dates setObject:now forKey:attr];
            

            [self setAttributeUpdatedDates:dates];
        

        if (_updatedAtSet) 
            _updatedAtSet = NO;
         else 
            if ([self.changedValues.allKeys containsObject:@"last_sync"]) 
                self.updated_at = [self.changedValues objectForKey:@"last_sync"];
             else 
                self.updated_at = [NSDate date];
            

                         _updatedAtSet = YES;
                 NSDictionary *changed = [self changedValues];
            NSMutableDictionary *dates = [[self attributeUpdatedDates] mutableCopy];

            for (NSString *key in changed.allKeys) 
                [dates setObject:now forKey:key];
            

            [self setAttributeUpdatedDates:dates];
        

    

据我所知,这应该没问题,因为如果 _updatedAtSet 变量设置为 true,它不应该再设置任何值,但是它仍然在中断,我不知道为什么!

请有人帮助我 谢谢

【问题讨论】:

【参考方案1】:

已经解决了。

我只是将_updatedAtSet = NO; 移到了 didSave 方法中,而不是它所在的位置,现在它工作正常。还是谢谢

【讨论】:

以上是关于NSInternalInconsistencyException 递归弄脏混乱的主要内容,如果未能解决你的问题,请参考以下文章

无法在包中加载 Nib - 错误的 nibname 错误