2012-04-20 7 views
4

私は以下のコードをコアデータシングルトンに使用しています。以下は私のコードです。私はコアデータundoManagerがクラッシュする

NSUndoManager *undoManager = [[NSUndoManager alloc] init]; 
[_managedObjectContext setUndoManager:undoManager]; 

を追加する場合(NachoManのblogからベース。ただし、コードが彼の要旨である。

// DataManager.h 
#import <Foundation/Foundation.h> 
#import <CoreData/CoreData.h> 

extern NSString * const DataManagerDidSaveNotification; 
extern NSString * const DataManagerDidSaveFailedNotification; 

@interface DataManager : NSObject { 
} 

@property (nonatomic, readonly, retain) NSManagedObjectModel *objectModel; 
@property (nonatomic, readonly, retain) NSManagedObjectContext *mainObjectContext; 
@property (nonatomic, readonly, retain) NSPersistentStoreCoordinator *persistentStoreCoordinator; 
@property (nonatomic, readonly, retain) NSManagedObjectContext *managedObjectContext; 

+ (DataManager*)sharedInstance; 
- (BOOL)save; 
- (BOOL)clearEntity:(NSString *)entityDescription; 
- (NSManagedObjectContext*)managedObjectContext; 

@end 

// DataManager.m 
#import "DataManager.h" 

NSString * const DataManagerDidSaveNotification = @"DataManagerDidSaveNotification"; 
NSString * const DataManagerDidSaveFailedNotification = @"DataManagerDidSaveFailedNotification"; 

@interface DataManager() 

- (NSString*)sharedDocumentsPath; 

@end 

@implementation DataManager 

@synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 
@synthesize mainObjectContext = _mainObjectContext; 
@synthesize objectModel = _objectModel; 
@synthesize managedObjectContext = _managedObjectContext; 

NSString * const kDataManagerBundleName = nil;//@"AP"; 
NSString * const kDataManagerModelName = @"APData"; 
NSString * const kDataManagerSQLiteName = @"APData.sqlite"; 

+ (DataManager*)sharedInstance { 
    static dispatch_once_t pred; 
    static DataManager *sharedInstance = nil; 

    dispatch_once(&pred, ^{ sharedInstance = [[self alloc] init]; }); 
    return sharedInstance; 
} 

- (void)dealloc { 
    [self save]; 
} 

- (NSManagedObjectModel*)objectModel { 
    if (_objectModel) 
     return _objectModel; 

    NSBundle *bundle = [NSBundle mainBundle]; 
    if (kDataManagerBundleName) { 
     NSString *bundlePath = [[NSBundle mainBundle] pathForResource:kDataManagerBundleName ofType:@"bundle"]; 
     bundle = [NSBundle bundleWithPath:bundlePath]; 
    } 
    NSString *modelPath = [bundle pathForResource:kDataManagerModelName ofType:@"momd"]; 
    NSLog(@"Path: %@",modelPath); 
    _objectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:modelPath]]; 

    return _objectModel; 
} 

- (NSPersistentStoreCoordinator*)persistentStoreCoordinator { 
    if (_persistentStoreCoordinator) { 
     NSLog(@"PersistentStore Exists %@",_persistentStoreCoordinator); 
     return _persistentStoreCoordinator; 
    } 
    NSLog(@"Persistent Stored DOESN'T EXIST"); 

    // Get the paths to the SQLite file 
    NSString *storePath = [[self sharedDocumentsPath] stringByAppendingPathComponent:kDataManagerSQLiteName]; 
    NSURL *storeURL = [NSURL fileURLWithPath:storePath]; 

    // Define the Core Data version migration options 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
       [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
       [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
       nil]; 

    // Attempt to load the persistent store 
    NSError *error = nil; 
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.objectModel]; 
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
           configuration:nil 
           URL:storeURL 
           options:options 
            error:&error]) { 
     NSLog(@"Fatal error while creating persistent store: %@", error); 
     abort(); 
    } 
    NSLog(@"store: %@",_persistentStoreCoordinator); 
    return _persistentStoreCoordinator; 
} 

- (NSManagedObjectContext*)mainObjectContext { 
    if (_mainObjectContext) 
     return _mainObjectContext; 

    // Create the main context only on the main thread 
    if (![NSThread isMainThread]) { 
     [self performSelectorOnMainThread:@selector(mainObjectContext) 
         withObject:nil 
        waitUntilDone:YES]; 
     return _mainObjectContext; 
    } 

    _mainObjectContext = [[NSManagedObjectContext alloc] init]; 
    [_mainObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 

    return _mainObjectContext; 
} 

- (BOOL)save { 
    if (![self.mainObjectContext hasChanges]) 
     return YES; 

    NSError *error = nil; 
    if (![self.mainObjectContext save:&error]) { 
     NSLog(@"Error while saving: %@\n%@", [error localizedDescription], [error userInfo]); 
     [[NSNotificationCenter defaultCenter] postNotificationName:DataManagerDidSaveFailedNotification 
            object:error]; 
     return NO; 
    } 

    [[NSNotificationCenter defaultCenter] postNotificationName:DataManagerDidSaveNotification object:nil]; 
    return YES; 
} 

- (BOOL)clearEntity:(NSString *)entityDescription 
{ 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityDescription inManagedObjectContext:_managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    NSError *error; 
    NSArray *items = [_managedObjectContext executeFetchRequest:fetchRequest error:&error]; 

    for (NSManagedObject *managedObject in items) { 
     [_managedObjectContext deleteObject:managedObject]; 
     NSLog(@"%@ object deleted",entityDescription); 
    } 
    if (![_managedObjectContext save:&error]) { 
     NSLog(@"Error deleting %@ - error:%@",entityDescription,error); 

     return NO; 
    } 
    return YES; 
} 

- (NSString*)sharedDocumentsPath { 
    static NSString *SharedDocumentsPath = nil; 
    if (SharedDocumentsPath) 
     return SharedDocumentsPath; 

    // Compose a path to the <Library>/Database directory 
    NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    SharedDocumentsPath = [libraryPath stringByAppendingPathComponent:@"Database"]; 

    // Ensure the database directory exists 
    NSFileManager *manager = [NSFileManager defaultManager]; 
    BOOL isDirectory; 
    if (![manager fileExistsAtPath:SharedDocumentsPath isDirectory:&isDirectory] || !isDirectory) { 
     NSError *error = nil; 
     NSDictionary *attr = [NSDictionary dictionaryWithObject:NSFileProtectionComplete 
           forKey:NSFileProtectionKey]; 
     [manager createDirectoryAtPath:SharedDocumentsPath 
      withIntermediateDirectories:YES 
        attributes:attr 
        error:&error]; 
     if (error) 
      NSLog(@"Error creating directory path: %@", [error localizedDescription]); 
    } 

    return SharedDocumentsPath; 
} 

- (NSManagedObjectContext*)managedObjectContext { 
    if (_managedObjectContext) { 
     return _managedObjectContext; 
    } 
    _managedObjectContext = [[NSManagedObjectContext alloc] init]; 
    NSUndoManager *undoManager = [[NSUndoManager alloc] init]; 
    [_managedObjectContext setUndoManager:undoManager]; 
    [_managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 
    [_mainObjectContext setRetainsRegisteredObjects:YES]; 

    return _managedObjectContext; 
} 

@end 

しかし、managedObjectContextにそれがクラッシュします。ログは

を示し

Crittercismを

SIGBUS
メイン(main.m:16)

0 CoreData 0x0033d940 -[NSManagedObject(_NSInternalMethods) _newSnapshotForUndo__] + 352 
1 CoreData 0x00318fb1 -[NSManagedObjectContext(_NSInternalChangeProcessing) _registerUndoForOperation:withObjects:withExtraArguments:] + 193 
2 CoreData 0x0031922f -[NSManagedObjectContext(_NSInternalChangeProcessing) _registerUndoForInsertedObjects:] + 63 
3 CoreData 0x003148f8 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 1384 
4 CoreData 0x00314389 -[NSManagedObjectContext processPendingChanges] + 41 
5 CoreData 0x002e8bd8 _performRunLoopAction + 216 
6 CoreFoundation 0x0177d99e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30 
7 CoreFoundation 0x01714640 __CFRunLoopDoObservers + 384 
8 CoreFoundation 0x016e04c6 __CFRunLoopRun + 1174 
9 CoreFoundation 0x016dfd84 CFRunLoopRunSpecific + 212 
10 CoreFoundation 0x016dfc9b CFRunLoopRunInMode + 123 
11 GraphicsServices 0x023617d8 GSEventRunModal + 190 
12 GraphicsServices 0x0236188a GSEventRun + 103 
13 UIKit 0x007e2626 UIApplicationMain + 1163 
14 My-App 0x284d main (main.m:16) 
15 My-App 0x27b5 start + 53 

SOの投稿の多くが使用していると、なぜこの2行でクラッシュするのですか?私はこれらの2行を取り出すとクラッシュすることはありません。私は、元に戻すマネージャーを使用することができません。

答えて

0

すべてのキャッシュをクリアしてから数日待ってからもう一度やり直します。それはクラッシュしなかった。キャッシュに何か詰まっているはずです。

0

コードが部分的に複数のスレッド用に準備されているようです。私はMOCが不適切にアクセスされていると思います。

また、_mainObjectContextのretainsRegisteredObjectsプロパティをmanagedObjectContextメソッド内から変更しているのはなぜですか?

私はあなたがしたいとは思わない。

+0

これは、複数スレッドのオープンソースのコアデータマネージャです。私はundoManagerを使う機能を追加するだけです。私のOPに明記されているように、undoManagerなしでうまく動作します。 – Bot

1

保存時にメインコンテキストを通知するなど、コアデータを使ったスレッド処理を処理する良い方法をお探しの場合は、MagicalRecordが素晴らしいライブラリです。スレッドヘルプに加えて、簡単な1行のフェッチ、簡単なコンテキストアクセスなどを提供します。

関連する問題