1

次のコードでオブジェクトを作成しています。

 +(Checkin *) newCheckinWithId:(NSString*) checkinID forVenueId:(NSString *)venueId
{
    NSManagedObjectContext * context = [[AppDelegate sharedInstance] managedObjectContext];
    Checkin *ret = (Checkin *)[NSEntityDescription insertNewObjectForEntityForName:@"Checkin" inManagedObjectContext:context];
    ret.checkinID = checkinID;
    ret.forVenueID = venueId;
    ret.date = [NSDate date];
    NSError * error;
    if(![context save:&error]) {
        NSLog(@"Error saving!!!!!: %@", error.userInfo);
    }
    return ret;
}

エラーはありませんが、保存後、そのオブジェクトのレコードを再度取得することはありません。

この関数でデバッガーを実行すると、unprocessedInsertsに1つのオブジェクトがあり、コンテキスト内のすべての内部セットに0個のオブジェクトが保存されていることがわかります(それが期待されるかどうかはわかりません)。

これが私のストア+管理対象オブジェクトコンテキストを作成するために使用するコードです(私はすべてに1つのコンテキストを使用します)それは基本的にすべて私が見つけたスタックオーバーフローポストからのものです

- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil)
    {
        return _managedObjectModel;
    }
    //NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"];
    //__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    //NSArray *testArray = [[NSBundle mainBundle] URLsForResourcesWithExtension:@"momd"subdirectory:nil];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];

    if( !path ) path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"mom"];

    NSURL *modelURL = [NSURL fileURLWithPath:path];

    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    //__managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];

    return _managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if((_persistentStoreCoordinator != nil)) {
        return _persistentStoreCoordinator;
    }

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
    NSPersistentStoreCoordinator *psc = _persistentStoreCoordinator;

    // Set up iCloud in another thread:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // ** Note: if you adapt this code for your own use, you MUST change this variable:
        NSString *iCloudEnabledAppID = @"[MY APP ID]";

        // ** Note: if you adapt this code for your own use, you should change this variable:
        NSString *dataFileName = @"foursquareaugmentation.sqlite";

        // ** Note: For basic usage you shouldn't need to change anything else

        NSString *iCloudDataDirectoryName = @"Data.nosync";
        NSString *iCloudLogsDirectoryName = @"Logs";
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
        NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];

        if (iCloud) {

            NSLog(@"iCloud is working");

            NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];

            NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
            NSLog(@"dataFileName = %@", dataFileName);
            NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
            NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);
            NSLog(@"iCloud = %@", iCloud);
            NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);

            if([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
                NSError *fileSystemError;
                [fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]
                       withIntermediateDirectories:YES
                                        attributes:nil
                                             error:&fileSystemError];
                if(fileSystemError != nil) {
                    NSLog(@"Error creating database directory %@", fileSystemError);
                }
            }

            NSString *iCloudData = [[[iCloud path]
                                     stringByAppendingPathComponent:iCloudDataDirectoryName]
                                    stringByAppendingPathComponent:dataFileName];

            NSLog(@"iCloudData = %@", iCloudData);

            NSMutableDictionary *options = [NSMutableDictionary dictionary];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
            [options setObject:iCloudEnabledAppID            forKey:NSPersistentStoreUbiquitousContentNameKey];
            [options setObject:iCloudLogsPath                forKey:NSPersistentStoreUbiquitousContentURLKey];

            [psc lock];
            NSError *error;

            [psc addPersistentStoreWithType:NSSQLiteStoreType
                              configuration:nil
                                        URL:[NSURL fileURLWithPath:iCloudData]
                                    options:options
                                      error:&error];

            if( error )
            {
                NSLog(@"Error adding persistent store %@, %@", error, [error userInfo]);

                // comment in this line while debugging if get "Can't find model for source store" error in addPersistentStoreWithType.
                // it means the sqlite database doesn't match the new model and needs to be created from scratch.
                // this happens if you change the xcdatamodel instead of creating a new one under Xcode->Editor->Add Model Version...
                // CoreData can only automatically migrate if there is a new model version (it can't migrate if the model simply changes, because it can't see the difference between the two models).
                // be sure to back up the database if needed, because all data will be lost.
                //[fileManager removeItemAtPath:iCloudData error:&error];

                /*// this is another way to verify the hashes for the database's model to make sure they match one of the entries in the momd directory's VersionInfo.plist
                 NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:[NSURL fileURLWithPath:iCloudData] error:&error];

                 if( !sourceMetadata )
                 NSLog(@"sourceMetadata is nil");
                 else
                 NSLog(@"sourceMetadata is %@", sourceMetadata);*/
            }

            [psc unlock];
        }
        else {
            NSLog(@"iCloud is NOT working - using a local store");
            NSMutableDictionary *options = [NSMutableDictionary dictionary];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

            [psc lock];
            NSError *error;

            [psc addPersistentStoreWithType:NSSQLiteStoreType
                              configuration:nil
                                        URL:localStore
                                    options:options
                                      error:nil];

            if( error )
                NSLog(@"Error adding persistent store %@, %@", error, [error userInfo]);
            [psc unlock];
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:@"SomethingChanged" object:self userInfo:nil];
        });
    });

    return _persistentStoreCoordinator;   
}

/*
 Returns the managed object context for the application.
 If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
 */
- (NSManagedObjectContext *) managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setPersistentStoreCoordinator: coordinator];
    }
    return _managedObjectContext;
}

私はしばらくの間これに取り組んできましたが、試してみることがないので、ヘルプやデバッグ手順をいただければ幸いです。(また、icloudやローカルでは動作しません)

たぶん私は間違ってフェッチしているので、オブジェクトを取得できません。これが私のフェッチです:

+(NSArray *) checkinsForVenue:(NSString *) venueID
{
    NSManagedObjectContext * context = [[AppDelegate sharedInstance] managedObjectContext];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Checkin" inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = entity;

    //NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(forVenueID = %@)", venueID];
    //request.predicate = predicate;

    NSError *error;
    NSArray * ret = [context executeFetchRequest:request error:&error];
    if(ret == nil) {
        NSLog(@"%@", error.description);
    }
    return ret;
}

編集:私は間違った質問をしていました。保存は機能していますフェッチは機能していません。それでも私のフェッチの何が問題なのか理解できません。

4

2 に答える 2

1

実際に sqlite に永続化されているかどうかを確認しましたか?

アプリは にあるはずです~Library/Application Support/iPhone Simulator/6.1/Applications。どのアプリ フォルダーが自分のものであるか (それらはすべて UUIDS によって名前が付けられています) を見つけ、そのDocumentsフォルダーで sqlite ファイルを探す必要があります。あなたのコードでは、それはfoursquareaugmentation.sqlite.

そのディレクトリでターミナル ウィンドウを開き、sqlite3 foursquareaugmentation.sqlite起動してデータベースのクエリを開始します。

という名前のテーブルを見つける必要がありZCHECKIN( という名前の管理対象オブジェクト クラスがある場合Checkin)、コンテキストを保存するたびに、そのテーブルに追加されます。

そのため、各保存後に実行select * from zcheckin;すると、そのテーブルに追加された行がもう 1 つ表示されます。

そうでない場合は、save操作に問題があります。それがデータベース テーブルにある場合は、コード内でオブジェクトへの参照が失われている、nilどこかに設定されている、またはそのようなものです。

それが役立つことを願っています。

于 2013-03-08T03:11:06.660 に答える
0

私の意見では、 と の両方で 2 つのコンテキストを作成する必要がcreateありfetchます。これにより、Core Data が混乱し、管理対象オブジェクトから最新のオブジェクトがフェッチされなくなりますinsert new object successfully

したがって、2 つのメソッド間でコンテキストを渡す必要があることをお勧めします。少なくとも、それは私にとってはうまくいきます。

于 2014-09-04T06:50:37.687 に答える