代码之家  ›  专栏  ›  技术社区  ›  sehugg

iPhone应用程序发布时间和核心数据迁移

  •  11
  • sehugg  · 技术社区  · 16 年前

    我有一个核心数据应用程序,我计划用一个新的模式来更新它。轻量级迁移似乎可行,但所需时间与数据库中的数据量成比例。这发生在 didFinishLaunchingWithOptions

    我想避免 <app> failed to launch in time 问题,所以我假设我不能将迁移保持在 方法。

    我假设最好的方法是在后台线程中执行迁移。我还假设需要将主ViewController的加载推迟到加载完成,以避免使用 managedObjectContext

    这有意义吗?是否有这种初始化的示例代码(可能在苹果的示例项目中)?

    5 回复  |  直到 16 年前
        1
  •  14
  •   Community Mohan Dere    9 年前

    你不能把迁移放在 NSOperation -applicationDidFinishLaunching: 方法而不触及核心数据堆栈。如果你能很快完成这个方法(和运行循环周期),那么你的应用程序就不会被终止,你可以花用户所能忍受的时间来完成你的迁移。

    请看我的答案: How to switch from Core Data automatic lightweight migration to manual?

    2010年5月19日更新

    澄清我的立场。做任何事都有可能。但是,在后台线程上执行迁移是一个非常复杂的过程 坏主意 . 很难保证堆栈 从未 在迁移过程中接触到其他线程特有的复杂问题。

    它是 可能的 但这涉及到一个完全没有必要的高度风险。主线程可以而且应该用于迁移主核心数据堆栈。很容易建立一个模式对话框,让用户知道正在进行迁移,然后在主线程上执行迁移。

    • 如果需要,可以轻松地退出迁移。
    • 在用户退出应用程序的情况下分块执行迁移。
    • 向用户提供可靠的反馈,说明迁移的进展以及何时完成。

    更新日期:2015年12月15日

    现在迁移的答案是在后台队列(通过 dispatch_async 的 NSPersistentStoreCoordinator addStore...

    这也意味着您需要确保您的UI能够处理持久层在未知时间段内为空/不可用的情况。如何做到这一点取决于您的应用程序。

    例如,您可以有一个临时UI,在持久层进行迁移时显示跳舞的猫。用户体验由您决定。

    但是,你知道 不是 希望让用户在迁移过程中创建数据。这将使以后的合并变得困难(如果有的话)。

        2
  •  7
  •   Community Mohan Dere    9 年前

    对不起,马库斯,我不得不恭敬地表示不同意。你呢

    我的migration运行在后台线程上。在速度较慢的设备上可能需要10秒以上,因此我在后台线程上启动它,并使用特定的模态视图控制器来显示进度。

    方法是将正常的加载顺序分为两个阶段。

    第1阶段)

    第2阶段) 执行启动时通常发生的所有需要托管对象的操作。这一阶段是第1阶段(不需要迁移)的直接延续。

    为了成功地执行长时间迁移,我使用了一个模态视图控制器来向用户显示迁移进度的反馈。然后我在后台线程中开始迁移,而模态视图控制器使用KVO来更新它的进度条。

    在迁移结束时,它关闭整个核心数据“堆栈”,对主线程的回调将取消模式并继续到第2阶段)。

    open question 一种让自动轻量级迁移像手动迁移一样显示其进展的方法。

        3
  •  2
  •   chris    13 年前

    下面是一个类似于ohhorob描述的方法的概要。不同的是,我只是显示一个动画“升级…”HUD,而不是一个信息更丰富的进度条。

    -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        [self.window makeKeyAndVisible];
    
        if ([MyManagedObject doesRequireMigration]) { // -doesRequireMigration is a method in my RHManagedObject Core Data framework
            [SVProgressHUD showWithStatus:NSLocalizedString(@"Upgrading...", nil) maskType:SVProgressHUDMaskTypeGradient];
    
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    
                // do your migration here
    
                dispatch_async(dispatch_get_main_queue(), ^{
                    [SVProgressHUD showSuccessWithStatus:NSLocalizedString(@"Success!",nil)];
                    [self postApplication:application didFinishLaunchingWithOptions:launchOptions];
                });
            });
    
        } else {
            [self postApplication:application didFinishLaunchingWithOptions:launchOptions];
        }
    
        return YES;
    }
    
    -(void)postApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        self.window.rootViewController = ....
    
        // anything else you want to run at launch
    }
    

        4
  •  0
  •   Alex Reynolds    16 年前

    您可以将核心数据更新放入 NSOperation didFinishLaunching... 通过重写操作的 -main

    this tutorial page 对所涉及的事情有个大概的了解。使用 KVO 因为手术的原因 isFinished

        5
  •  0
  •   Brian Semiglia    13 年前

    我找到了一个很简单的方法。把你所有的电话都写进application:didFinishLaunching with 与主线程异步的调度。这将立即返回并让您在主线程上执行升级。但是,您可能应该设置窗口,使其在迁移时不会显示空白屏幕。

    - (void)application:didFinishLaunching {
         dispatch_async(main_queue) {
              // migration
         }
         self.window = ...
         return YES;
    }