我有一个由fetchedResultsController / UIManagedDocument支持的tableViewController,它使用通过JSON消息从服务器获取的数据。它以斯坦福2011年iPhone编程讲座中使用的TVC为蓝本。程序从服务器加载,更新并完美刷新tableView。但是当我尝试编辑单元格中的信息时,我的结果非常奇怪。
我在类PlugDetailTVC中编辑对象,该类向DataFetcher类发送消息以发送适当的JSON消息。然后通过重新加载整个数据库 getAllPlugsInDocument。一切正常。发送正确的JSON并收到正确的响应。服务器数据库正确更新。在运行getAllPlugsInDocument之后,tableView显示正确的更新信息。然后10-15秒后,程序抛出一个没有错误消息的异常!
UPDate:我对我的代码进行了一次更改,这是对saveToURL.document.fileURL的更改
[self.document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success) {
if (success) {
NSLog(@"PlugFetcher Document saved");
} else {
NSLog(@"PlugFetcher Document was unable to save");
}
BUT!我把代码交给其他人运行(xcode 4.2 / iPhone 5.1模拟器与黑客运行iOS 5.1)它完美运行!我然后在我的手机上运行它 - 带iOS 5.1的4S再次完美运行。回到xCode 4.3.1上的iPhone 5.1模拟器 - 同样的旧崩溃,即使在重置内容和设置等之后 现在我比以前更加神秘了。
相关代码:
PlugsTableViewController
-(void)setupFetchedResultsController{
NSManagedObjectContext *context=self.mainDatabase.managedObjectContext;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Plug"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]];
self.fetchedResultsController= [[NSFetchedResultsController alloc]initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
}
-(void)fetchPlugDataIntoDocument:(UIManagedDocument *)document{
NSLog(@"fetchPlugDataIntoDocument");
PlugFetcher *plugFetcher=[PlugFetcher getInstance];
[plugFetcher getAllTimeZones:document];
[plugFetcher getAllPlugsInDocument:document];
}
//Open or create document,call setupFetchedResultsController
-(void)useDocument{
if (![[NSFileManager defaultManager]fileExistsAtPath:[self.mainDatabase.fileURL path]]) {
NSLog(@"######## Document Does not exist #########");
[self.mainDatabase saveToURL:self.mainDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
}];
}else if (self.mainDatabase.documentState==UIDocumentStateClosed){
NSLog(@"######## Document closed #########");
[self.mainDatabase openWithCompletionHandler:^(BOOL success) {
[self setupFetchedResultsController];
}];
}else if (self.mainDatabase.documentState==UIDocumentStateNormal){
NSLog(@"######## Document Normal #########");
[self setupFetchedResultsController];
}
[self fetchPlugDataIntoDocument:self.mainDatabase];
}
-(void)setmainDatabase:(UIManagedDocument *)mainDatabase{
if (_mainDatabase!=mainDatabase) {
_mainDatabase=mainDatabase;
[self useDocument];
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.mainDatabase) {
NSLog(@"######## !self.mainDatabase #########");
NSURL *url=[[[NSFileManager defaultManager]URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]lastObject];
url=[url URLByAppendingPathComponent:@"main Database"];
self.mainDatabase=[[UIManagedDocument alloc]initWithFileURL:url];
PlugFetcher *plugFetcher=[PlugFetcher getInstance];
plugFetcher.context=self.mainDatabase.managedObjectContext;
plugFetcher.document=self.mainDatabase;
}
}
PlugFetcher.m
- (void)getAllPlugsInDocument:(UIManagedDocument*)document{
NSManagedObjectContext *context=[document managedObjectContext];
dispatch_queue_t fetchQ=dispatch_queue_create("Data Fetcher", NULL);
dispatch_async(fetchQ, ^{
NSDictionary *serverDictionary=[self.serverCommManager getServerPlugList];
if([[serverDictionary objectForKey:@"success"] isEqualToString:@"true"]){
NSArray *serverPlugArray=[serverDictionary objectForKey:@"response"];
[document.managedObjectContext performBlock:^{ // perform in the NSMOC's safe thread (main thread)
NSEntityDescription *plugEntity = [NSEntityDescription entityForName:@"Plug" inManagedObjectContext:context];
[self deleteAllObjectsInEntity:plugEntity forPlug:nil inContext:context];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"TimeZone"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"utcOffset"
ascending:YES]];
NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterNoStyle];
for (NSDictionary *plugFromServer in serverPlugArray){
Plug *newLocalPlug=[NSEntityDescription insertNewObjectForEntityForName:@"Plug" inManagedObjectContext:context];
newLocalPlug.plugID = [plugFromServer valueForKey:@"id"];
newLocalPlug.name = [plugFromServer valueForKey:@"name"];
newLocalPlug.location = [plugFromServer valueForKey:@"loc"];
newLocalPlug.notes = [plugFromServer valueForKey:@"notes"];
newLocalPlug.state=[plugFromServer valueForKey:@"state"];
}
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
}];
}else{
NSLog(@"PLUGFETCHER getAllPlugs:json response=fail");
}
});
}
-(void)updatePlug:(Plug*)plug{
NSString *json = [JSONQuery queryUpdateDevice:plug.plugID
name:plug.name
location:plug.location
notes:plug.notes
dummy:plug.dummy
state:plug.state
timezone:[NSString stringWithFormat:@"%@", plug.timeZone.utcOffset]];
[self.serverCommManager send:json];
}
PlugDetailTVC:
if ([[segue identifier] isEqualToString:@"savePlugDetail"]){
//forces saving of info in field be edited when button is pushed
[self.view.window endEditing: YES];
[self.currentTextField endEditing:YES];
NSLog(@"PlugDetailTVC prepareForSeque plug:%@",self.plug.plugID);
PlugFetcher *plugFetcher= [PlugFetcher getInstance];
[plugFetcher updatePlug:self.plug];
}