在我的应用程序中,我正在从两个核心数据存储中删除(或尝试删除)所有记录,然后再添加新的记录。它们是 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 之间没有关系。它们是独立的、独立的实体。
奇怪的是,代码似乎永远不会进入@catch,因为控制台Exception triggered: ...
在崩溃之前不会接收任何消息。
不时抛出错误。该应用在 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];
这是main
SLSyncOperation 的方法(继承自 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。它每次都会打印出该线程的名称。所以这似乎不是一个多线程问题。特别是因为应用程序在每次达到该点时都会时不时地崩溃。