【发布时间】:2017-11-16 16:33:17
【问题描述】:
我正在尝试在我的 ios 应用程序的后台更新核心数据,我首先删除核心数据,然后将其添加回来。但是,我需要一定的 segue 才能运行某些功能,但是当我尝试在后台执行所有操作时,这些功能永远不会运行,除非我更改页面并返回它。
所以我尝试通过手动调用 viewWillAppear() 来修复此错误,但我收到以下错误。
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x17191c00 of class CardScanView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x16d99c30> (
<NSKeyValueObservance 0x16dcdf20: Observer: 0x17191c00, Key path: verifyingCard, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x16d5db30>
发生错误的类中的方法:
- (void) resetDatabase {
count++;
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
ConDAO *con = [[ConDAO alloc] init];
DatabaseManager *manager = [DatabaseManager sharedManager];
NSError * error;
NSURL * storeURL = [[[manager managedObjectContext] persistentStoreCoordinator] URLForPersistentStore:[[[[manager managedObjectContext] persistentStoreCoordinator] persistentStores] lastObject]];
[[manager managedObjectContext] reset];//to drop pending changes
if ([[[manager managedObjectContext] persistentStoreCoordinator] removePersistentStore:[[[[manager managedObjectContext] persistentStoreCoordinator] persistentStores] lastObject] error:&error])
{
// remove the file containing the data
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
//recreate the store like in the appDelegate method
[[[manager managedObjectContext] persistentStoreCoordinator] addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];//recreates the persistent store
}
NSLog(@"*****************************");
NSLog(@"updating");
NSLog(@"count: %d", count);
NSLog(@"*****************************");
[self populateDatabase:0 con:con];
NSTimer *timer = [NSTimer timerWithTimeInterval:60.0
target:self
selector:@selector(resetDatabase)
userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
dispatch_async(dispatch_get_main_queue(), ^(void){
CardScanView *card = [[CardScanView alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:card
selector:@selector(viewWillAppear:)
name:@"updated" object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"updated" object:nil];
});
});
}
viewWillAppear 和 viewDidDissapear 在其他类中:
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// Setup KVO for verifyingcard
[self addObserver:self forKeyPath:@"verifyingCard" options:NSKeyValueObservingOptionNew context:nil];
if([BluetoothTech isEqualToString:@"BLE"]){
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{CBCentralManagerOptionShowPowerAlertKey: @YES}];
}
else if([BluetoothTech isEqualToString:@"HID"]){
[self.bluetoothScanTextView becomeFirstResponder];
}
[self loadStudents];
}
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
// Disconnect the bluetooth peripheral device if it exists
if(self.discoveredPeripheral != nil){
[self.centralManager cancelPeripheralConnection:self.discoveredPeripheral];
}
// Remove KVO for verifyingCard
[self removeObserver:self forKeyPath:@"verifyingCard"];
}
是什么导致了错误,还有比手动调用 viewDidLoad 更好的方法来解决这个问题吗?谢谢
【问题讨论】:
-
每 60 秒您就完全重新初始化数据库?这是一种反模式。
-
那我该如何更新呢?
-
基于推送通知的增量更新是理想的选择。应避免轮询。删除所有数据并从头开始重新创建整个数据库是最坏的情况;你正在做大量的工作——消耗大量的电池寿命——只是为了重新创建你已经拥有的东西(假设数据库的内容不是每 60 秒完全改变一次)。
标签: ios objective-c xcode multithreading core-data