2013-03-08 68 views
1

我創建用下面的代碼的對象:的NSManagedObjectContext保存出現失去對象

+(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; 
} 

並沒有錯誤,但之後保存我再也瑟該對象的任何記錄。

運行在此功能的調試器我看到它有1個對象unprocessedInserts後保存在上下文中的所有內部設置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; 
} 

編輯:我問的是錯誤的問題。儲蓄是工作獲取不是。仍然無法弄清楚我的抓取有什麼問題。

+0

也是我能想到的一切似乎正常Checkin * ret =(Checkin *)[NSEntityDescription insertNewObjectForEntityForName:@「Checkin」inManagedObjectContext:context];返回一個好的對象;上下文不是零,等不知道還有什麼其他檢查 – mike 2013-03-08 02:39:50

回答

1

你檢查過它是否真的被持續到sqlite?

你的應用程序應該在~Library/Application Support/iPhone Simulator/6.1/Applications。您必須找到哪個應用程序文件夾是您的(它們都由UUIDS命名),然後在Documents文件夾中查找sql​​ite文件。在你的代碼中,那將是foursquareaugmentation.sqlite

在該目錄中打開一個終端窗口並啓動sqlite3 foursquareaugmentation.sqlite開始查詢數據庫。

您應該找到一個名爲ZCHECKIN的表(如果您有一個名爲Checkin的託管對象類),並且每次保存上下文時,它都應該添加到該表中。

因此,在每次保存後運行select * from zcheckin;應該會向您顯示一行添加到該表中。

如果沒有發生這種情況,save操作中出現問題。如果它在數據庫表中,則代碼中的某些內容會丟失對象的引用,將其設置爲nil或其他類似內容。

希望有所幫助。

+0

Thx的開始!我做到了,在表中找到1條,但是至少應該有20條。所以它必須一次工作,然後失敗或什麼。 但在代碼中,我從來沒有看到任何,即使是這個1,實際上有 – mike 2013-03-08 03:31:35

+0

啊等一下!我在我的實際電話上做了20個,是的,當我保存時它已經進入了數據庫,那麼一定是fletch出了問題呢?該提取仍返回0行。 – mike 2013-03-08 03:41:57

+0

嗯,你有沒有嘗試過使用調試器來檢查NSArray從你的獲取回來?您可以使用調試器的左側窗格展開數組的內容並查看其中有多少個對象......或右鍵單擊並打印內容。 我可能只是爲了簡化問題而剪掉iCloud代碼,然後嘗試在模擬器上敲入幾行到核心數據並從那裏檢索它們。 – 2013-03-09 05:01:37

0

在我看來,你應該在createfetch中創建兩個上下文。這將使核心數據感到困惑,並且不會從管理對象中獲取最新的對象,儘管在insert new object successfully之後。

所以我建議你應該在兩種方法之間傳遞上下文。至少,它適用於我。

相關問題