Fetch on Core Data 可以在模拟器上运行,但不能在设备上运行

Posted

技术标签:

【中文标题】Fetch on Core Data 可以在模拟器上运行,但不能在设备上运行【英文标题】:Fetch on Core Data works in simulator but not on device 【发布时间】:2013-01-20 12:18:50 【问题描述】:

我有一个应用程序,我在其中展示 VC1 来选择游戏,并展示 VC2 来提交所选游戏的播放。当用户从 VC2 切换回 VC1 时,我想保留他们正在玩的游戏的游戏数据。由于它是 ios 6.0,我使用 UIManagedDocument 来访问 Core Data 以存储和检索游戏数据。我完全被我所面临的问题难住了,在花费了无数个小时之后,我正在与这个论坛上的智者联系。

当我在模拟器中运行下面的代码时,一切正常,数据被存储,如果用户选择与之前玩的游戏相同的游戏,我也能够检索并显示它。不幸的是,在设备上,我可以看到数据存储在 segue 上——我放了一个断点并使用 iExplorer 查看了 persistentStore——但是当我回到 VC2 选择存储的游戏时,persistentStore 似乎被覆盖或清除了的所有数据。在调试器中,我注意到“UIManagedDocument”的_persistentStoreCoordinator 对象的_persistentStores NSArray 属性在设备上完成检索时始终显示0。

非常感谢任何帮助!!!

- (void) addOrGetDataToGamesDatabase:(CNPUIManagedDocument *)document withFlag:(BOOL)getFlag     
    if (getFlag) 
    NSLog(@"INSIDE addDataToGamesDatabase to get data");
    
    else
    NSLog(@"INSIDE addDataToGamesDatabase to set data");

    dispatch_queue_t update = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);
    dispatch_sync(update, ^
    [document.managedObjectContext performBlockAndWait:^
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Game"];
        request.predicate = [NSPredicate predicateWithFormat:@"game = %@", self.selectedGameID];
        NSError *error = nil;
        NSLog(@"Persistent Store Name = %@", [[document class] persistentStoreName]);
        NSArray *matches = [document.managedObjectContext executeFetchRequest:request error:&error];       
        NSLog(@"Fetch Error if any: %@ %@", error.debugDescription, [error userInfo]);


        if (!matches || matches.count >1) 
        NSLog(@"There is a problem with creating the game data");
        

        //This is where it fails on the device as the match.count is always 0 as the fetch retrieves nothing
        else if ([matches count] == 0) 
        if (!getFlag) 
        // Code to initialize the game data in store
        
        
        else if ([matches count] == 1) 
        // Another fetch - nested
        if (!oTeammatches || [oTeammatches count] >1) 
            NSLog(@"There is a problem with creating the offense team data");
        
        else if ([oTeammatches count] == 0) 
            if (!getFlag) 
              //Code to initialize the team data in store
           
        
        else if ([oTeammatches count] == 1) 
            OTeam *newOTeam = [oTeammatches lastObject];
            if (getFlag) 
                //Retrieves data
                //Shown by log lines beginning with "Getting"
            
            else 
                //Sets/Saves data
                //Shown by log lines beginning with "Setting"
            
         

        
    ];
    if (!getFlag) 
        [document updateChangeCount:UIDocumentChangeDone];
    
    );


- (IBAction)pressBackButton:(UIButton *)sender 
    [self addOrGetDataToGamesDatabase:self.gamesDatabase withFlag:NO];
    if ((self.gamesDatabase.documentState & UIDocumentStateEditingDisabled) != UIDocumentStateEditingDisabled) 
    [self.gamesDatabase saveToURL:self.gamesDatabase.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) 
        if (success) 
           NSLog(@"DB save file path: %@", self.gamesDatabase.fileURL);
           NSLog(@"Saved!!!");
        
        else
        NSLog(@"Unable to save");
    ];
    
  [self performSegueWithIdentifier:@"BackToPickGame" sender:self];


- (void)viewDidLoad

    [super viewDidLoad];
  //Some Initialization code

    if (!self.gamesDatabase) 
      NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
      url = [url URLByAppendingPathComponent:@"GameDB"];
      self.gamesDatabase = [[CNPUIManagedDocument alloc] initWithFileURL:url];
      NSLog(@"DB File URL generated: %@", url);
      NSLog(@"self.gameDatabase initialized");
    

   [self addOrGetDataToGamesDatabase:self.gamesDatabase withFlag:YES];
   NSLog(@"Calling game with ID %@ , self.selectedGameID);

一些关于持久化存储的日志信息

设备 先进入VC2 document->_persistentStoreCoordinator 的打印说明: document->_persistentStoreCoordinator->persistentStores 的打印描述: _NSArrayM 0x1fd28ce0>(

)

在退出 VC2 时首先在 VC2 中设置 document->_persistentStoreCoordinator 的打印说明: document->_persistentStoreCoordinator->persistentStores 的打印描述: _NSArrayM 0x1fd28ce0>( (网址:file://localhost/var/mobile/Applications/4DD2D219-5AC1-406F-8020-260B01E46E0C/Documents/GameDB/StoreContent/persistentStore) )

第二次进入VC2 document->_persistentStoreCoordinator 的打印说明: document->_persistentStoreCoordinator->persistentStores 的打印描述: _NSArrayM 0x211d4660>(

)

模拟器 先进入VC2 document->_persistentStoreCoordinator 的打印说明: document->_persistentStoreCoordinator->persistentStores 的打印描述: _NSArrayM 0x84e4b60>( (网址:file://localhost/Users/Rujul/Library/Application%20Support/iPhone%20Simulator/6.0/Applications/B187169B-8D32-4BB1-AB41-33DB76637D9C/Documents/GameDB/StoreContent/persistentStore) )

退出 VC2 时的第一个设置 document->_persistentStoreCoordinator 的打印说明: document->_persistentStoreCoordinator->persistentStores 的打印描述: _NSArrayM 0x84e4b60>( (网址:file://localhost/Users/Rujul/Library/Application%20Support/iPhone%20Simulator/6.0/Applications/B187169B-8D32-4BB1-AB41-33DB76637D9C/Documents/GameDB/StoreContent/persistentStore) )

第二次进入VC2 document->_persistentStoreCoordinator 的打印说明: document->_persistentStoreCoordinator->persistentStores 的打印描述: _NSArrayM 0xf777910>( (网址:file://localhost/Users/Rujul/Library/Application%20Support/iPhone%20Simulator/6.0/Applications/B187169B-8D32-4BB1-AB41-33DB76637D9C/Documents/GameDB/StoreContent/persistentStore) )

【问题讨论】:

【参考方案1】:

检查代码中的所有覆盖(如上面的UIDocumentSaveForOverwriting)。记录前后的准确值。我相信你会通过这种方式找到罪魁祸首。

另外,检查您在每个prepareForSegue: 中所做的事情。

顺便说一句,我建议也许将令人困惑的 addOrGetDataToGamesDatabase 业务重构为两种易于理解的方法。

【讨论】:

感谢您的回复。不确定您希望我在覆盖后检查哪些值。当我在退出 VC2 时设置值时,我检查了设备上的 persistentStore,我看到它被填充了。我添加了一些关于persistentStore 状态的信息。如果您可以查看并发表评论,将不胜感激。

以上是关于Fetch on Core Data 可以在模拟器上运行,但不能在设备上运行的主要内容,如果未能解决你的问题,请参考以下文章

如果Core Data count / fetch请求中的实体名称错误,如何避免崩溃?

Core Data Fetch 在插入实体时保存关系(同时)

Core Data Fetch 没有返回它应该返回的对象

iOS Core Data Fetch Request,如何使用

Swift Core Data Fetch 按日期和时间存储为字符串并排序

iOS NSArray, NSSet 与 Core Data Query (Fetch Request)