3

iOSアプリでiCloudを有効にしましたが、アプリを最初に起動したときに、アプリのいずれかのビューを押すと、アプリが約5秒間フリーズします。このチュートリアルに従って、アプリでiCloudを有効にし、コアデータを使用してデータを同期しました。iCloud同期を追加する前は、この問題は発生していませんでした。これは最初の起動時にのみ発生し、アプリの他の起動では発生しません。iCloudの同期は発生します。問題はアプリのフリーズです。

これが私のアプリデリゲートの同期を管理するコードです。

- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    /*if (persistentStoreCoordinator == nil) {
        NSURL *storeURL = [NSURL fileURLWithPath:[self dataStorePath]];

        persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];

        NSError *error;
        if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
            NSLog(@"Error adding persistent store %@, %@", error, [error userInfo]);
            abort();
        }
    }
    return persistentStoreCoordinator;*/

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    if ((persistentStoreCoordinator != nil)) {
        return persistentStoreCoordinator;
    }

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSPersistentStoreCoordinator *psc = persistentStoreCoordinator;

    // Set up iCloud in another thread:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // ** Note: if you adapt this code for your own use, you MUST change this variable:
        NSString *iCloudEnabledAppID = @"48S27G4A2S.com.maxned.iDownloadBlog";

        // ** Note: if you adapt this code for your own use, you should change this variable:
        NSString *dataFileName = @"DataStore.sqlite";

        // ** Note: For basic usage you shouldn't need to change anything else

        NSString *iCloudDataDirectoryName = @"Data.nosync";
        NSString *iCloudLogsDirectoryName = @"Logs";
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
        NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];

        if (iCloud)
        {
            //NSLog(@"iCloud is working");

            NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];

            /*NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
            NSLog(@"dataFileName = %@", dataFileName);
            NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
            NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);
            NSLog(@"iCloud = %@", iCloud);
            NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);*/

            if ([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
                NSError *fileSystemError;
                [fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]
                       withIntermediateDirectories:YES
                                        attributes:nil
                                             error:&fileSystemError];

                if (fileSystemError != nil) {
                    NSLog(@"Error creating database directory %@", fileSystemError);
                }
            }

            NSString *iCloudData = [[[iCloud path]
                                     stringByAppendingPathComponent:iCloudDataDirectoryName]
                                    stringByAppendingPathComponent:dataFileName];

            //NSLog(@"iCloudData = %@", iCloudData);

            NSMutableDictionary *options = [NSMutableDictionary dictionary];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
            [options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey];
            [options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey];

            [psc lock];

            [psc addPersistentStoreWithType:NSSQLiteStoreType
                configuration:nil
                URL:[NSURL fileURLWithPath:iCloudData]
                options:options
                error:nil];

            [psc unlock];

        } else {

            NSLog(@"iCloud is NOT working - using a local store");
            NSMutableDictionary *options = [NSMutableDictionary dictionary];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

            [psc lock];

            [psc addPersistentStoreWithType:NSSQLiteStoreType
                configuration:nil
                URL:localStore
                options:options
                error:nil];

            [psc unlock];

        }

        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:@"SomethingChanged" object:self userInfo:nil];
        });
    });

    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    return persistentStoreCoordinator;
}

/*- (NSManagedObjectContext *)managedObjectContext
{
    if (managedObjectContext == nil) {
        NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator;
        if (coordinator != nil) {
            managedObjectContext = [[NSManagedObjectContext alloc] init];
            [managedObjectContext setPersistentStoreCoordinator:coordinator];
        }
    }
    return managedObjectContext;
}*/

- (NSManagedObjectContext *)managedObjectContext
{
    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil) {
        NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

        [moc performBlockAndWait:^{
            [moc setPersistentStoreCoordinator: coordinator];
            [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mergeChangesFrom_iCloud:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:coordinator];
        }];
        managedObjectContext = moc;
    }

    return managedObjectContext;
}

- (void)mergeChangesFrom_iCloud:(NSNotification *)notification
{
    //NSLog(@"Merging in changes from iCloud...");

    NSManagedObjectContext* moc = [self managedObjectContext];

    [moc performBlock:^{

        [moc mergeChangesFromContextDidSaveNotification:notification];

        NSNotification* refreshNotification = [NSNotification notificationWithName:@"SomethingChanged"
            object:self
            userInfo:[notification userInfo]];

        [[NSNotificationCenter defaultCenter] postNotification:refreshNotification];
    }];
}
4

3 に答える 3

3

この問題を修正するために、コードを変更して別のスレッドに配置しました。

dispatch_queue_t mainQueue = dispatch_get_main_queue();
        dispatch_async(mainQueue, ^{

            NSFileManager *fileManager = [NSFileManager defaultManager];
            NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
            NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];

            if (iCloud)
            {
                //NSLog(@"iCloud is working");

                NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];

                /*NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
                 NSLog(@"dataFileName = %@", dataFileName);
                 NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
                 NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);
                 NSLog(@"iCloud = %@", iCloud);
                 NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);*/

                if ([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
                    NSError *fileSystemError;
                    [fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]
                           withIntermediateDirectories:YES
                                            attributes:nil
                                                 error:&fileSystemError];

                    if (fileSystemError != nil) {
                        NSLog(@"Error creating database directory %@", fileSystemError);
                    }
                }

                NSString *iCloudData = [[[iCloud path]
                                         stringByAppendingPathComponent:iCloudDataDirectoryName]
                                        stringByAppendingPathComponent:dataFileName];

                //NSLog(@"iCloudData = %@", iCloudData);

                NSMutableDictionary *options = [NSMutableDictionary dictionary];
                [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
                [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
                [options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey];
                [options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey];

                [psc lock];

                [psc addPersistentStoreWithType:NSSQLiteStoreType
                                  configuration:nil
                                            URL:[NSURL fileURLWithPath:iCloudData]
                                        options:options
                                          error:nil];

                [psc unlock];

            } else {

                NSLog(@"iCloud is NOT working - using a local store");
                NSMutableDictionary *options = [NSMutableDictionary dictionary];
                [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
                [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

                [psc lock];

                [psc addPersistentStoreWithType:NSSQLiteStoreType
                                  configuration:nil
                                            URL:localStore
                                        options:options
                                          error:nil];

                [psc unlock];
            }
        });
于 2012-10-16T23:04:15.927 に答える
0

このコードがメインスレッドで実行されている場合は、それが問題である可能性があります。

このコードは最初の(または任意の)起動時にどこから呼び出されますか?

于 2012-10-16T21:01:33.350 に答える
0

自分で検索を行うと、これは実際に予想される動作のように見えます。他の人がプライバシー設定を変更するときにアプリがSIGKILLによって殺されたと言っているように、ここで:https ://devforums.apple.com/message/715855

文書化は不十分ですが、設計どおりに機能しています。「権限が変更されると、iOSはアプリを終了し、以前の権限を前提として操作できないようにします。たとえば、ユーザーが連絡先の権限を付与したとします。その後、アプリをバックグラウンドで実行して変更します。それ。あなたは今は許可がないのに許可があるという考えの下で操作するでしょう。それでiOSはただアプリを終了します。」

「しかし、クラッシュすることはありません。強制的に再起動するだけです。SIGKILLメッセージは表示されますが、クラッシュログは表示されません。」

于 2015-04-06T15:42:36.627 に答える