2

OSX アプリケーションを作成しており、サービスと呼ばれる CoreData エンティティからエンティティをロードしようとしています。デフォルトの Xcode テンプレートを使用していますが、エンティティが正常に保存されます。ただし、それらを取得すると、このエラーがスローされます。

+entityForName: nil は、エンティティ名「サービス」を検索する有効な NSManagedObjectContext パラメータではありません

エラーをスローするコードは次のとおりです。この関数はawakeFromNibで呼び出されます

-( NSMutableArray * )getServices {

    //NSManagedObjectContext *context = [(SAAppDelegate *)[[NSApplication sharedApplication] delegate] managedObjectContext];

    SAAppDelegate *delegate = (SAAppDelegate*)[[NSApplication sharedApplication] delegate];
    NSManagedObjectContext *context = [delegate managedObjectContext];

    NSLog(@"After managedObjectContext: %@",  context);
    NSEntityDescription *entity = [ NSEntityDescription entityForName:@"Service" inManagedObjectContext: context ];

    NSSortDescriptor *sortDescriptor = [ [ NSSortDescriptor alloc] initWithKey: @"service_name" ascending: YES ];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    [request setEntity:entity];
    [request setSortDescriptors:[ NSArray arrayWithObject: sortDescriptor]];

    [context processPendingChanges];

    NSError *error;
    return [ NSMutableArray arrayWithArray: [ context executeFetchRequest:request error:&error ] ];


}

参考までに、AppDelegate.m ファイルからの managedObjectContext を次に示します。

    //
//  SAAppDelegate.m
//  ServerAngel
//
//  Created by Adam Bulmer on 29/10/2013.
//  Copyright (c) 2013 Adam Bulmer. All rights reserved.
//

#import "SAAppDelegate.h"

@implementation SAAppDelegate

@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize managedObjectContext = _managedObjectContext;

@class SAServerListWindowController;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application

}

// Returns the directory the application uses to store the Core Data store file. This code uses a directory named "com.adambulmer.ServerAngel" in the user's Application Support directory.
- (NSURL *)applicationFilesDirectory
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *appSupportURL = [[fileManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject];
    return [appSupportURL URLByAppendingPathComponent:@"com.adambulmer.ServerAngel"];
}

// Creates if necessary and returns the managed object model for the application.
- (NSManagedObjectModel *)managedObjectModel
{

    if (  _managedObjectModel == nil ) {

        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"ServerAngel" withExtension:@"momd"];
        _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    }

    return _managedObjectModel;

}

// Returns the persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. (The directory for the store is created, if necessary.)
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{

    if ( _persistentStoreCoordinator == nil ) {

        NSManagedObjectModel *mom = [ self managedObjectModel ];

        NSFileManager *fileManager = [ NSFileManager defaultManager ];
        NSURL *applicationFilesDirectory = [ self applicationFilesDirectory ];
        NSError *error = nil;

        NSDictionary *properties = [ applicationFilesDirectory resourceValuesForKeys:@[ NSURLIsDirectoryKey ] error:&error ];

        if ( ! properties ) {

            BOOL ok = NO;

            if ( [ error code ] == NSFileReadNoSuchFileError ) {

                ok = [ fileManager createDirectoryAtPath:[ applicationFilesDirectory path ] withIntermediateDirectories:YES attributes:nil error:&error ];

            }

            if ( ! ok ) {

                [ [  NSApplication sharedApplication ] presentError:error ];

                NSLog( @"1 - test" );
                return nil;

            }

        } else {

            if ( ! [ properties[ NSURLIsDirectoryKey ] boolValue ] ) {

                // Customize and localize this error.
                NSString *failureDescription = [NSString stringWithFormat:@"Expected a folder to store application data, found a file (%@).", [applicationFilesDirectory path]];

                NSMutableDictionary *dict = [NSMutableDictionary dictionary];
                [dict setValue:failureDescription forKey:NSLocalizedDescriptionKey];

                error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:101 userInfo:dict];

                [ [ NSApplication sharedApplication ] presentError:error ];

                NSLog( @"2 - test" );
                return nil;
            }

        }

        NSURL *url = [applicationFilesDirectory URLByAppendingPathComponent:@"ServerAngel.storedata"];
        NSPersistentStoreCoordinator *coordinator = [ [ NSPersistentStoreCoordinator alloc ] initWithManagedObjectModel:mom ];

        if ( ! [ coordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error ] ) {

            [ [ NSApplication sharedApplication] presentError:error ];
            return nil;

        }

        NSLog(@"AppDelegate coordinator: %@",  coordinator);
        _persistentStoreCoordinator = coordinator;

    }

    return _persistentStoreCoordinator;

}

// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 
- (NSManagedObjectContext *)managedObjectContext
{

    if ( _managedObjectContext == nil ) {

        _managedObjectContext = [ [ NSManagedObjectContext alloc ] init ];

        NSPersistentStoreCoordinator *coordinator = [ self persistentStoreCoordinator ];

        if ( coordinator != nil ) {

            [ _managedObjectContext setPersistentStoreCoordinator: coordinator ];

        }

        NSLog(@"AppDelegate coordinator: %@",  coordinator);

    }

    NSLog(@"AppDelegate managedObjectContext: %@",  _managedObjectContext);


    return _managedObjectContext;

}

// Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application.
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window
{
    return [[self managedObjectContext] undoManager];
}

// Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user.
- (IBAction)saveAction:(id)sender
{
    NSError *error = nil;

    if (![[self managedObjectContext] commitEditing]) {
        NSLog(@"%@:%@ unable to commit editing before saving", [self class], NSStringFromSelector(_cmd));
    }

    if (![[self managedObjectContext] save:&error]) {
        [[NSApplication sharedApplication] presentError:error];
    }
}

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
    // Save changes in the application's managed object context before the application terminates.

    if (!_managedObjectContext) {
        return NSTerminateNow;
    }

    if (![[self managedObjectContext] commitEditing]) {
        NSLog(@"%@:%@ unable to commit editing to terminate", [self class], NSStringFromSelector(_cmd));
        return NSTerminateCancel;
    }

    if (![[self managedObjectContext] hasChanges]) {
        return NSTerminateNow;
    }

    NSError *error = nil;
    if (![[self managedObjectContext] save:&error]) {

        // Customize this code block to include application-specific recovery steps.              
        BOOL result = [sender presentError:error];
        if (result) {
            return NSTerminateCancel;
        }

        NSString *question = NSLocalizedString(@"Could not save changes while quitting. Quit anyway?", @"Quit without saves error question message");
        NSString *info = NSLocalizedString(@"Quitting now will lose any changes you have made since the last successful save", @"Quit without saves error question info");
        NSString *quitButton = NSLocalizedString(@"Quit anyway", @"Quit anyway button title");
        NSString *cancelButton = NSLocalizedString(@"Cancel", @"Cancel button title");
        NSAlert *alert = [[NSAlert alloc] init];
        [alert setMessageText:question];
        [alert setInformativeText:info];
        [alert addButtonWithTitle:quitButton];
        [alert addButtonWithTitle:cancelButton];

        NSInteger answer = [alert runModal];

        if (answer == NSAlertAlternateReturn) {
            return NSTerminateCancel;
        }
    }

    return NSTerminateNow;
}

@end

エラーログ

    2013-11-14 22:01:38.267 ServerAngel[1012:303] Network check
2013-11-14 22:01:48.161 ServerAngel[1012:303] network avi
2013-11-14 22:01:48.162 ServerAngel[1012:303] After managedObjectContext: (null)
2013-11-14 22:01:48.162 ServerAngel[1012:303] +entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Service'
2013-11-14 22:01:48.163 ServerAngel[1012:303] (
    0   CoreFoundation                      0x00007fff877c941c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff85c31e75 objc_exception_throw + 43
    2   CoreData                            0x00007fff8d202729 +[NSEntityDescription entityForName:inManagedObjectContext:] + 217
    3   ServerAngel                         0x0000000100002d9d -[SAServerListWindowController getServices] + 205
    4   ServerAngel                         0x0000000100003294 -[SAServerListWindowController checkServices] + 148
    5   Foundation                          0x00007fff894d1094 __NSFireTimer + 96
    6   CoreFoundation                      0x00007fff87730724 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    7   CoreFoundation                      0x00007fff8773025f __CFRunLoopDoTimer + 1151
    8   CoreFoundation                      0x00007fff877a176a __CFRunLoopDoTimers + 298
    9   CoreFoundation                      0x00007fff876ebaa5 __CFRunLoopRun + 1525
    10  CoreFoundation                      0x00007fff876eb275 CFRunLoopRunSpecific + 309
    11  HIToolbox                           0x00007fff8e4b3f0d RunCurrentEventLoopInMode + 226
    12  HIToolbox                           0x00007fff8e4b3cb7 ReceiveNextEventCommon + 479
    13  HIToolbox                           0x00007fff8e4b3abc _BlockUntilNextEventMatchingListInModeWithFilter + 65
    14  AppKit                              0x00007fff8ef1828e _DPSNextEvent + 1434
    15  AppKit                              0x00007fff8ef178db -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
    16  AppKit                              0x00007fff8ef0b9cc -[NSApplication run] + 553
    17  AppKit                              0x00007fff8eef6803 NSApplicationMain + 940
    18  ServerAngel                         0x00000001000049a2 main + 34
    19  libdyld.dylib                       0x00007fff88cbf5fd start + 1
)
2013-11-14 22:01:48.255 ServerAngel[1012:303] Network check
4

2 に答える 2

2

managedObjectContextすべてのケースでインスタンス化されているわけではありません。アクセサーを単純化し、このアクセサーで MOC が決して nil にならないようにすることができます。

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext == nil) 
    {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
    }
    return _managedObjectContext;
}

persistantStoreCoordinator同様の方法でアクセサーを変更して、遅延インスタンス化も確実にする必要がある場合があります。

于 2013-11-14T20:40:58.610 に答える
2

管理対象オブジェクト コンテキストのアクセサ メソッドが呼び出されていません。遅延読み込みメソッドからのログも表示されていません。

私の推測では、アプリケーション デリゲートが正しく接続されていません。デバッガーを使用すると、おそらく次の行が表示されます。

SAAppDelegate *delegate = (SAAppDelegate*)[[NSApplication sharedApplication] delegate];

戻ってきnilます。

OS X アプリケーションにはデフォルトでデリゲートがありません。通常はオブジェクトをメインの xib ファイルに追加し、それをデリゲート クラスとして識別し、それをアプリケーション オブジェクトのデリゲート アウトレットに接続することによって、特別に設定する必要があります。

それが接続されている場合(そして、デフォルトのテンプレートを使用したと言っているので、すぐに使用できるすべてのものに付属しています)、問題は間違ったawakeFromNibメソッドからこれを呼び出しているか、適切に設定されていない他のnibファイルを追加しました。

于 2013-11-16T20:53:50.767 に答える