私のアプリケーションでは、新しいレコードを適切な場所に追加する前に、2 つのコア データ ストアからすべてのレコードを削除しています (または削除しようとしています)。これらは、アドレス帳のレコードに関連するデータを含む 2 つの単純なストアです (VIContacts には連絡先 ID と vcard ハッシュ (整数) が含まれ、VIGroup にはグループ ID とグループ名が含まれます)。
ストアからすべての連絡先を削除するには、次のコードをメソッドで使用します-clear:
。
NSArray *allOldRowsInVIContacts = [[mainContext fetchObjectsForEntityName:[VIContact name]
includePropertyValues:NO
withPredicate:nil] copy];
for (NSManagedObject *obj in allOldRowsInVIContacts) {
@try {
[mainContext deleteObject:obj];
}
@catch (NSException *exception) {
NSLog(@"Exception Triggered: %@", exception.reason);
[NSException raise:exception.reason format:@"thrown on vicontacts."];
}
}
[allOldRowsInVIContacts release];
if (![mainContext save:error]) {
return NO;
}
NSArray *allOldRowsInVIGroups = [[mainContext fetchObjectsForEntityName:[VIGroup name]
includePropertyValues:NO
withPredicate:nil] copy];
NSLog(@"all rows in VIGroups count: %d", [allOldRowsInVIGroups count]);
for (NSManagedObject *obj in allOldRowsInVIGroups) {
@try {
[mainContext deleteObject:obj];
}
@catch (NSException *exception) {
NSLog(@"Exception Triggered: %@", exception.reason);
[NSException raise:exception.reason format:@"thrown on vigroups."];
}
}
[allOldRowsInVIGroups release];
NSLog(@"at the end of -clear: Going to save context.");
/* SAVE */
if (![mainContext save:error]) {
return NO;
}
アプリは常に VIGroup 領域でクラッシュするようです。
クラッシュログは次のとおりです。
Crashed Thread: 5 Dispatch queue: com.apple.root.default-priority
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
...
Thread 5 Crashed:: Dispatch queue: com.apple.root.default-priority
0 com.apple.CoreFoundation 0x00007fff82532574 __CFBasicHashRehash + 1412
1 com.apple.CoreFoundation 0x00007fff8252b41b __CFBasicHashAddValue + 75
2 com.apple.CoreFoundation 0x00007fff82531f78 CFBasicHashAddValue + 3176
3 com.apple.CoreFoundation 0x00007fff82547899 CFSetAddValue + 121
4 com.apple.CoreData 0x00007fff8520e3dc -[NSManagedObjectContext deleteObject:] + 220
5 com.andrei.AddressBookApp 0x000000010004da9a -[AddressBookFrameworkSyncHelper clear:] + 490
6 com.andrei.AddressBookApp 0x000000010004c8f9 +[AddressBookFrameworkSyncHelper saveSnapshot:] + 105
7 com.andrei.AddressBookApp 0x000000010002d417 -[SLSyncOperation main] + 2631
8 com.apple.Foundation 0x00007fff8b68dbb6 -[__NSOperationInternal start] + 684
他の情報
Instruments を使用してゾンビを探しましたが、何も表示されません。アプリケーションにいくつかのリークがありますが、Core Data に関連するものはありません。
VIGroup と VIContact の間に関係はありません。それらは独立した独立したエンティティです。
Exception triggered: ...
奇妙なことに、コンソールはクラッシュする前にメッセージを取得しないため、コードは @catch に入らないようです。
エラーは時々スローされます。アプリは Lion の方が安定しているようですが、Mountain Lion と Snow Leopard では頻繁にクラッシュします。
ありがとう。どんな助けでも大歓迎です。
いくつかのコードで更新
作成された MOC:
「NSOperation」(「SLSyncOperation」) を作成し、「NSOperationQueue」に追加します。それSLSyncOperation
はに追加されますNSOperationQueue
:
[backgroundQueue setMaxConcurrentOperationCount:1];
// has a custom initializer
currentOperation = [[SLSyncOperation alloc] initWithPersistentStoreCoordinator:persistentStoreCoordinator
andDelegate:delegate
forceRemoteSync:forceSync];
[backgroundQueue addOperation:currentOperation];
これは SLSyncOperation のmain
メソッドです (NSOperation から継承):
- (void)main {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
syncProgressTracker = [SLSyncProgressTracker sharedProgressTracker];
syncProgressTracker.currentStatus = SLSyncStatusIdle;
// ... some other setup and sending notifications ...
/* Set up. */
managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
managedObjectContext = [[NSManagedObjectContext alloc] init];
// persistentStoreCoordinator is passed from the app delegate
[managedObjectContext setPersistentStoreCoordinator:persistentStoreCoordinator];
// ... continues with other logic (syncing to a server), and the end of the method is: ...
/* Tear down. */
[managedObjectContext release];
managedObjectModel = nil;
[pool drain];
}
使用されている MOC:
内から呼び出されるメソッドから呼び出されるシングルトン クラスで MOC を使用していSLSyncOperation
ます。この場合、すべてが同じスレッドで起こっていると思います...? これを確認するために、いくつかのテスト メソッドを追加します。
シングルトン クラスで初期化されている MOC:
+ (AddressBookFrameworkSyncHelper *)sharedHelper {
if (!_sharedAddressBookHelper) {
_sharedAddressBookHelper = [[AddressBookFrameworkSyncHelper alloc] init];
}
return _sharedAddressBookHelper;
}
- (id)init {
if (self = [super init]) {
mainContext = [(AddressBookAppAppDelegate *)[[NSApplication sharedApplication] delegate] managedObjectContext];
addressBookRef = [ABAddressBook sharedAddressBook];
// disable undo manager - uses less memory
[mainContext setUndoManager:nil];
}
return self;
}
この後、MOC ( mainContext
) を使用して保存し、それを使用する他のメソッドに渡します。
//saving
[sharedABF.mainContext save:error];
// passing it to a Core Data method
VIContact *contactToAdd = [VIContact newOrExistingContactWithID:contactID
inContext:sharedABF.mainContext
error:error];
// that method looks like this
+ (VIContact *)newOrExistingContactWithID:(NSString *)contactID inContext:(NSManagedObjectContext *)context error:(NSError **)error {
VIContact *theContact = [[context fetchObjectsForEntityName:[VIContact name]
includePropertyValues:YES
withPredicate:
@"personID == %@", contactID] lastObject];
if (theContact) {
return [theContact retain];
} else {
// no contact found with that ID, return a new one
VIContact *newContact = [[VIContact alloc] initAndInsertInContext:context];
newContact.personID = contactID;
return newContact;
}
}
// and then fetch all rows in a Core Data entity and remove them
NSArray *allOldRowsInVIContacts = [mainContext fetchObjectsForEntityName:[VIContact name]
includePropertyValues:NO
withPredicate:nil];
for (NSManagedObject *obj in allOldRowsInVIContacts) {
[mainContext deleteObject:obj];
}
if (![mainContext save:error]) {
return NO;
}
fetchObjectsForEntityName
メソッドはここから取得されます。
あなたが言及したメソッドを使用して、メソッドが異なるスレッドからアクセスされるかどうかを確認します。これが役に立ち、私が MOC をどのように使用しているかについての詳細情報を提供してくれることを願っています。
詳しくは
mainContext が作成されるスレッドの名前をSLSyncOperationThread.Name set.
. アプリがクラッシュするポイントの前に、スレッドの名前を出力する NSLog を配置しました。毎回このスレッドの名前を出力します。したがって、マルチスレッドの問題ではないようです。特に、アプリがその時点に達するたびに時々クラッシュするためです。