私はコアデータで抱えている問題を理解しようと頭を悩ませています。エラーの意味を理解しており、以前に発生したことがあります(そして修正しました)が、なぜ今発生しているのか理解できません。
私のアプリの構造は次のとおりです。
MPModel->MPPlaceおよびMPModel->MPProject
ここで、MPModelはNSManagedObjectのサブクラスであり、MPPlaceとMPProjectはMPModelのサブクラスです。
データモデルは、MPPlaceとMPProjectの間に関係があり、MPPlaceにはMPPlaceがあります(多くのMPProjectとMPProjectが属します)。
アプリが読み込まれると、完全に機能する多数の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への2回目の呼び出しまで完全に実行されます。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に設定されている場合、これ以上値を設定する必要がないため、これは問題ないはずですが、それでも壊れており、理由がわかりません。
誰か助けてくれませんかありがとう