无需更改屏幕即可更新 Core Data

Posted

技术标签:

【中文标题】无需更改屏幕即可更新 Core Data【英文标题】:Update Core Data without having to change screen 【发布时间】:2017-06-14 18:53:34 【问题描述】:

在我更新我的核心数据存储后 - 通过删除然后添加数据 - 在不同的线程中,我需要更改屏幕,然后返回数据以更新它。有没有办法在不改变应用程序屏幕的情况下更新核心数据?

重置数据库的代码:

- (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)

                );
        );

ui改变时运行的代码:

- (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];

我认为它与 loadStudents() 函数有关,但是当我使用 NSNotificationCenter 从其他类运行它时,它仍然不起作用。

加载学生代码:

- (void)loadStudents
    NSError *error = nil;
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Caf_student_cards"];
    NSArray *arr = [[self.manager managedObjectContext] executeFetchRequest:fetchRequest error:&error];
    for(int i = 0; i < [arr count]; i++)
        if([[[arr objectAtIndex:i] valueForKey:@"user_id"] isEqualToString:@"201509061"])
            NSLog(@"%@",[arr objectAtIndex:i]);
        
    
    if(!error)
        self.caf_student_cards = [NSMutableArray arrayWithArray:arr];
        self.keys = [[[arr.firstObject entity] attributesByName] allKeys];
    
    else
        NSLog(@"%s %s %s","\n\n\n",[[error localizedDescription] UTF8String],"\n\n\n");
        dispatch_async(dispatch_get_main_queue(), ^
            // Show alert to tell user to reload this page
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"Error: %@", [error localizedDescription]] message:@"Check connection and relog back into cafeteria." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
            [alert show];
        );
    

【问题讨论】:

更新CoreData和改变UI有什么关系?? 我不确定,但它只会在我更改 ui 屏幕时更新 这怎么可能,伙计?核心数据更新与 UI 更新无关。请发布一些代码来澄清你的情况 ***.com/questions/44546194/… 与此相关 - 修复了错误但需要更改 ui 才能正常工作 Core Data 没有什么需要更新 UI 才能工作。如果您发现了某种联系,则需要发布有关您正在做什么确切以及更新 UI 时会发生什么的信息。 【参考方案1】:

这段代码存在多个问题。

与您的问题最直接相关的一个问题是您正在更新持久存储,而不是更新您的 UI。它不会自动发生。如果您有新数据,则需要告诉您的 UI 进行更新。如何做到这一点取决于您拥有什么样的 UI。如果它是一个表格视图,它可能就像告诉表格视图重新加载其数据一样简单。如果您有一个用于保存 UI 数据的数组,您也需要对其进行更新(看起来这可能是您的代码中的 caf_student_cards,但无法确定。

其他问题——这些是您需要立即解决的主要问题:

    您在执行 Core Data 多线程时出错。在这里使用dispatch_async 无效。您需要在托管对象上下文中使用 performBlockperformBlockAndWait,或者在持久容器上使用 performBackgroundTask。 您正在删除主持久存储文件,但没有删除日志文件。这几乎可以保证防止旧数据被删除或简单地导致数据损坏。你正在做的不是一个有用的技术。删除持久存储文件很少是一个好主意。如果您想删除现有数据,请将其从 Core Data 中删除,可能通过将您的上下文告诉 delete 对象或使用 NSBatchDeleteRequest

可能还有其他人。这段代码很乱。如果您花一点时间查看 Apple 的 Core Data Programming Guide,您会帮自己一个大忙。

还有你keep 几乎问same 问题repeatedly。你有一些很好的建议,但你似乎没有接受任何建议。如果您想了解更多信息,请阅读您之前发布此问题时人们已经给出的其他答案。

【讨论】:

谢谢,但在重新加载阵列方面。我调用了执行此操作的函数,但它仍然不起作用。当我输入某个键时,它说它不存在,除非我改变屏幕。 然后你应该问一个描述你如何更新你的 UI 的问题。即使它是您遇到的问题的核心,您仍然没有描述它,也没有包含任何解释它的示例代码。例如,您在这个问题中的代码会加载一个数组,但根本不会触及您的 UI。 我找到了错误发生的原因。所以基本上我的核心数据变成了“数据:”,除非我改变屏幕。 核心数据故障不是错误情况。我已经建议阅读 Apple 关于 Core Data 如何工作的文档。请帮自己一个忙,看看。你在这里让自己很难受。

以上是关于无需更改屏幕即可更新 Core Data的主要内容,如果未能解决你的问题,请参考以下文章

Prisma 无需等待即可创建/更新

node.js + mysql + ejs 数据插入后无需重新加载页面即可更新屏幕信息

Core Data 更改时更新 Swiftui 视图

告知 iCloud 何时没有更多待处理的 Core Data 更新更改

Core Data 不会将属性更新保留到数据库

Core Data + iCloud,更改通知插入和删除关系中的对象但不更新关系中现有实体的属性