Crash lors de l'ajout de persistance (activé iCloud) au délégué d'application

Je vais commencer la mise à jour pour aider ceux qui cherchent à l'utiliser comme référence pour leur propre code personnel.

Nouvelle mise à jour

  • Je suis assez sûr que j'ai trouvé un moyen pour resynchroniser les dispositifs de retour ensemble une fois qu'ils ont arrêté de se parler les uns les autres. Je vais mettre à jour mon
    réponse ci-dessous avec tous les détails. J'ai vraiment l'espoir que vous trouverez tous les
    cela utile. Il a pris près de 2 mois d'essai et d'erreur de la figure
    celui-ci dehors. Merci donc de référence et de le partager avec d'autres personnes qui sont
    ayant des problèmes à obtenir des périphériques une fois de plus parler les uns aux
    d'autres grâce à iCloud. Il m'a pris une éternité pour comprendre tout cela, donc je
    je suis plus qu'heureux de les enregistrer comme beaucoup d'autres développeurs possible de
    avoir à créer leur propre fortune de bugs.

Un autre plus pour vous aider à configurer correctement

  • J'ai trouvé que, après la mise à jour d'une application qui a iCloud données associées
    avec le compte peut provoquer un plantage lors de l'ouverture, parce que l'iCloud
    les données vont tenter de fusionner immédiatement dans l'appareil (où l'
    l'appareil n'a pas encore créé sa persistance). J'ai maintenant ajouté
    @property (nonatomic, readwrite) BOOL unlocked; à AppDelegate.h
    et @synthesize unlocked; à AppDelegate.m. J'ai ensuite changé mon -
    (NSPersistentStoreCoordinator *)persistentStoreCoordinator
    méthode
    bien que mon - (void)mergeChangesFrom_iCloud méthode, qui
    seront affichées ci-dessous (dans le milieu de la persistance de l'installation de magasin et de
    au bas de l'iCloud méthode de fusion). En fait, je suis contant
    l'app pour empêcher iCloud à partir de la fusion de données jusqu'à ce que l'application a mis en place
    sa persistance. Autrement, vous verrez l'application crash en raison de
    illisible défauts.

Ici est de savoir comment je configure mon persistentStoreCoordinator:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
//here is where you declare the persistent store is not prepared;
self.unlocked = NO;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Maintain_My_Car.sqlite"];
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];   
NSPersistentStoreCoordinator *psc = __persistentStoreCoordinator; 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *options = nil;
NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:nil];
NSString *coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:@"data"];
if (coreDataCloudContent.length != 0) {
//iCloud enabled;
cloudURL = [NSURL fileURLWithPath:coreDataCloudContent];
options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, @"<bundleIdentifier>.store", NSPersistentStoreUbiquitousContentNameKey, cloudURL, NSPersistentStoreUbiquitousContentURLKey, nil];
} else {
//iCloud not enabled;
options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
}
NSError *error = nil;
[psc lock];
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"bad things %@ %@", error, [error userInfo]);
abort();
}
[psc unlock];
//the store is now prepared and ready for iCloud to import data;
self.unlocked = YES;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"iCloud persistent store added");
[[NSNotificationCenter defaultCenter] postNotificationName:@"RefetchAllDatabaseData" object:self userInfo:nil];
});
});
return __persistentStoreCoordinator;
}

<myAppKey> et <bundleIdentifier> sont des valeurs réelles, bien sûr. Je suis juste de masquage pour le partage de ce code.

Je sais que certaines personnes sont toujours à avoir des problèmes avec cela et peut-être à l'aide de cette question à titre de référence sur la façon de créer leur propre compatibles iCloud de Base des applications de Données, de sorte que je veux mettre à jour ce à chaque fois que je modifie mon code personnel, veiller à ce que tous vous pouvez utiliser le code qui fonctionne pour moi. Dans cette mise à jour, j'ai changé la première cloudURL de [fileManager URLForUbiquityContainerIdentifier:@"<TeamIdentifier>.<bundleIdentifier>"] à [fileManager URLForUbiquityContainerIdentifier:nil], s'assurer que le conteneur des informations sont recueillies auprès de droits de fichier.

D'autres méthodes
_notificationArray est définie comme suit:
@property (nonatomice, strong) NSMutableArray *notificationArray;
@synthesize notificationArray = _notificationArray;

- (void)mergeChangesFrom_iCloud:(NSNotification *)notification {
if (self.unlocked) {
NSManagedObjectContext *moc = [self managedObjectContext];
if (self.notificationArray.count != 0) {
for (NSNotification *note in _notificationArray) {
[moc performBlock:^{
[self mergeiCloudChanges:note forContext:moc];
}];
}
[_notificationArray removeAllObjects];
[moc performBlock:^{
[self mergeiCloudChanges:notification forContext:moc];
}];
} else {
[moc performBlock:^{
[self mergeiCloudChanges:notification forContext:moc];
}];
}
} else {
if (_notificationArray == nil) {
_notificationArray = [[NSMutableArray alloc] init];
}
[_notificationArray addObject:notification];
}
}
- (void)resetStore {
[self saveContext];
__persistentStoreCoordinator = nil;
__managedObjectContext = nil;
//reset the managedObjectContext for your program as you would in application:didFinishLaunchingWithOptions:
myMainView.managedObjectContext = [self managedObjectContext];
//the example above will rebuild the MOC and PSC for you with the new parameters in mind;
}

Puis il y a le mergeiCloudChanges:forContext: méthode:

- (void)mergeiCloudChanges:(NSNotification *)note forContext:(NSManagedObjectContext *)moc {
//below are a few logs you can run to see what is being done and when;
NSLog(@"insert %@", [[note userInfo] valueForKey:@"inserted"]);
NSLog(@"delete %@", [[note userInfo] valueForKey:@"deleted"]);
NSLog(@"update %@", [[note userInfo] valueForKey:@"updated"]);
[moc mergeChangesFromContextDidSaveNotification:note];
NSNotification *refreshNotification = [NSNotification notificationWithName:@"RefreshAllViews" object:self userInfo:[note userInfo]];
[[NSNotificationCenter defaultCenter] postNotification:refreshNotification];
//do any additional work here;
}

Problème Initial

  • À l'aide d'iCloud sur iOS 5.0.1, je suis parfois d'avoir des erreurs relatives
    pour le stockage permanent. Je vais continuer la mise à jour de ce avec
    de nouvelles informations que je trouve par le biais de l'expérimentation, mais jusqu'à présent, l'
    solution que j'ai fournie est la seule façon que je peux obtenir l'application de travail
    de nouveau correctement (malheureusement jlstrecker la solution ne fonctionne pas pour
    moi) une fois que je commence à voir l'erreur, qui est la suivante:

    -NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:erreur::
    CoreData: l'Ubiquité: Erreur en essayant de lire l'omniprésence de la racine de l'url:
    file://localhost/private/var/mobile/Library/Mobile%20Documents/./de données/.
    Erreur: Erreur de Domaine=LibrarianErrorDomain Code=1 "L'opération
    ne pouvait pas être complété. (LibrarianErrorDomain erreur de 1 - Impossible de
    lancer téléchargement de l'élément.)" UserInfo=0x176000
    {NSURL=file://localhost/private/var/mobile/Library/Mobile%20Documents/./données/,
    NSDescription=pas en mesure d'initier téléchargement de l'élément.}

    Pour la vie de moi, je ne peux pas comprendre pourquoi je le vois tous les
    soudain ou comment le faire arrêter. J'ai supprimé l'application à partir de deux
    les appareils, de la suppression de l'iCloud de données qui a été la synchronisation entre précédente
    eux, et supprimé les données à partir de sauvegardes concernant les applications. J'ai
    redémarrage de Xcode, redémarré deux appareils, nettoyé le projet Xcode,
    pourtant, rien n'a arrêté l'erreur d'apparaître. Je n'ai jamais vu
    cette erreur avant et n'ont aucune chance de trouver quelque chose en ligne sur
    comment faire pour le bloquer.

    L'application se bloque ici:

    if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
    NSLog(@"bad things %@ %@", error, [error userInfo]);
    abort();
    }

    Le journal n'est jamais atteint, ni l'abandonner. Je viens de voir l'erreur ci-dessus
    et l'application elle-même ne répond pas. Si quelqu'un peut m'aider
    dans la bonne direction, je serais très reconnaissante.

Précédent pour les questions

  • Cela semble se poursuivre même après la mise à jour de la bêta à la
    la sortie publique de la 5.0.1. La dernière fois, il m'est arrivé était après
    changer mon contexte de la gestion des données du modèle. Compte tenu que je n'ai pas
    publié le app encore, je n'ai pas la peine de la fusion d'une nouvelle version de la
    de modèle. J'ai juste supprimé et réinstallé l'appli sur mes appareils, mais
    puis elle a refusé de coopérer avec les données stockées dans iCloud
    conteneur, par qui je veux dire que j'ai reçu un message d'erreur que le magasin
    impossible de télécharger les éléments. J'imagine que cela est dû à un conflit de données
    les types de modèles, ce qui est logique. Il semble donc que vous avez juste besoin de
    se débarrasser des données au sein de l'iCloud conteneur sans se débarrasser
    du conteneur. La suppression de l'iCloud de données semble tout tuer
    hors, en substance, la désactivation du conteneur et l'ID de l'Application. Étant donné qu'il semblait
    plus simple, j'ai essayé de créer un nouveau conteneur, tel que suggéré par jlstrecker,
    mais malheureusement, cela n'aide pas du tout. Donc, encore une fois, j'ai eu à
    aller à travers les étapes que j'ai indiqué dans ma réponse, qui a fait tout le
    truc. Mais vu comment il est ennuyeux d'avoir à créer une nouvelle Application
    Id et mettre à jour les profils de configuration à chaque fois, j'ai pensé qu'il valait mieux
    mise à jour de ce que j'ai appris à potentiellement réduire la cause et obtenir
    pour une solution plus rapide.

    En passant par iCloud > Stockage & Backup > Gérer le Stockage, puis
    la suppression de l'app semble être la meilleure solution pour vider le
    les données, mais cela semble corrompu le conteneur, conduisant à la
    l'erreur ci-dessus. Et après avoir réussi à faire cela, n'importe comment beaucoup de
    fois j'ai supprimer l'application et de la réinstaller à l'appareil (pour faire
    apparaît comme c'est la première fois apparaissant sur l'appareil et, espérons-le
    recréer le conteneur), je ne peux jamais obtenir l'application à afficher dans la
    Documents & de la liste de Données à nouveau. C'est un peu inquiétant si cela signifie
    que toute personne qui supprime les données de leurs iCloud comme cela signifie que
    iCloud ne fonctionne pas pour l'application de nouveau. Je ne suis qu'à l'aide d'un
    développement de profil sur l'appli, donc peut-être l'aide d'un
    profil de distribution peut faire une différence, mais je vais avoir à
    test avant de dire quoi que ce soit pour certains.

J'espère que ces nouvelles mises à jour d'aider toute personne qui peut avoir des problèmes de mise en place de leur magasin. Il a très bien fonctionné pour moi jusqu'à présent. Je ne manquerai pas de mettre à jour plus si je trouve mieux de bugs ou tout simplement tout ce qui rend le processus plus sans heurt.

  • Je peux aussi reproduire cette erreur par la suppression de mon application données dans "Gérer le Stockage" comme vous êtes. Une des solutions semble être la modification de la NSPersistentStoreUbiquitousContenturlkey - je vais donc par exemple de changer le suffixe de "/data" à "/data2" et il va commencer à travailler à nouveau. Ce n'est pas la solution, bien sûr.
  • vesl, il me semble comme un bug dans iCloud. Signalé — rdar://10440734.
  • Je suis avec vous, @jlstrecker. Il semble que l'iCloud conteneur de supprimer les données de l'application avec les données nécessaires pour s'initialiser. Je suis heureux de voir que vous avez signalé le problème. Dois-je le faire ou bien est-on assez?
  • Quelqu'un a posté un bug à Apple? N'est-ce pas le bon endroit pour cela?
  • Aussi, il me semble être en mesure de "réinitialiser" le dossier par la compensation de l'iCloud conteneur: [fileManager removeItemAtURL:cloudUrl erreur:&erreur] peut-être que c'est une bonne "master reset" option lorsque iCloud ne sont pas synchronisés. Cependant, il semble comme existant dans la base de données n'a pas de synchronisation lorsque vous faites cela - seulement de nouvelles choses?
  • vous avez également signalé ce bug à Apple, avez-vous? Ou seulement Ouvrir un Radar?
  • qui sonne comme il pourrait être une bonne solution, en ajoutant un peu de méthode, plus tard, à force de le contexte actuel à ajouter à la iCloud magasin persistant (ce qui serait fastidieux si vous avez une grande base de données). Je vais être signalé ce bug à Apple maintenant, alors ce ne sera pas nécessaire dans le futur
  • Je suis en cours d'exécution dans la même situation. Supprimer iCloud, l'app store via iCloud->Stockage & Sauvegarde ... de préférence cesse de données (nouvelles affaires) de synchronisation et par la suite de la suppression de la réinstallation de l'application conduit à la pendaison sur addPersistentStoreWithType:... l'invocation.
  • Mon rapport de bug à Apple a été fermé comme un doublon.
  • c'est bizarre. Espérons que cela signifie qu'ils sont à la recherche sur la question, mais je n'ai toujours pas entendu quoi que ce soit de retour sur le rapport que j'ai soumis. J'espère entendre quelque chose rapidement pour que je puisse mettre à jour tout le monde sur la façon de le résoudre, ou au moins d'attendre un correctif dans la prochaine mise à jour d'iOS
  • Je suis toujours avoir les mêmes problèmes avec la nouvelle version bêta, comme tout le monde sur les forums des développeurs. Le consensus général est que les Données de Base de la synchronisation n'est toujours pas résolu. Peut-être dans la prochaine version bêta?
  • qui est impair. Il semblait fonctionner pour moi très bien. Retrait de mon stockage iCloud (via le panneau de configuration) et de redémarrer l'application conduit à un nouveau dossier de stockage iCloud (avec toutes les données encore présentes). Mais il n'y avait pas des accidents ou se bloque. Ce qui se passe exactement avec le vôtre? Je serais heureux de jouer avec elle. Plus les gens en les regardant, le mieux.
  • J'ai migré ma Base de Données de la pile à miroir l'une dans la Base de Données de Recette pour la synchronisation iCloud - assez basique. J'ai ensuite mis à jour mon appareil à la dernière version bêta, supprimé l'application, supprimer iCloud de données de l'application, réinstallé, et il ne se synchronisent pas, sauf si je change l'omniprésence nom de dossier, puis uniquement les nouvelles données. Mêmes questions qu'avant, et les gens sur la Base de Données de Recettes développeur fil de discussion du forum sont également signalé les problèmes existent toujours.
  • Je vais aller regarder ça. Il ne semble pas être un problème pour moi si je passe par le même processus, mais je suis le plus susceptibles de la configuration de mon stockage différemment. Donc je vais prendre un coup d'oeil à la Base de Données de Recettes, pour voir ce qu'il existe des différences entre leur code et le mien. Je vais être sûr de mettre à jour ma réponse une fois/si je trouve quelque chose d'utile.
  • vesl - je pense que je l'ai eu à travailler! Une chose qui semble être sous-est discuté de la façon d'utiliser migratePersistentStore de la migration d'un magasin existant à iCloud (et retour au local à nouveau). J'ai trouvé que vous avez besoin pour passer un emplacement physique de votre "nouveau" iCloud base de données dans toURL - ne passe pas l'emplacement du journal des transactions, et il doit être différent de la boutique de l'emplacement actuel. Toujours en attente sur une nouvelle app de référence d'Apple, mais en attendant, nous sommes au moins quelque part. Merci à tous de tangage dans la!
  • Je pense que je peux honnêtement dire que vous êtes mon héros. J'ai lutté plus d'essayer d'obtenir que cela fonctionne pour les deux dernières semaines, en vain. En fait je viens de posté une nouvelle question d'essayer de comprendre ce que je vois, mais vous venez peut-être résolu. Toute idée de ce que le code serait de passer à la boutique?
  • pourriez vous m'expliquer comment vous avez réussi à le faire fonctionner en code s'il vous plaît? pass a physical location for your "new" iCloud database in toURL quoi toURL?
  • regardez mes autres réponses. Il a un exemple de code. Mais ce n'est vraiment pas prêt pour la production. Apple doit fournir des applications de référence pour établir les meilleures pratiques en la matière.
  • oh, génial! Mauvais vous demander dans sa réponse, puis..
  • Merci so so so so so so so so so so so so so so so SOoOOOoooooo beaucoup!!!!!!!!!!!!!! vous m'avez sauvé!!
  • Je ne sais pas comment merci. quel est votre app? 🙂
  • encore une chose, je veux juste savoir est de savoir comment la force de l'app pour actualiser si iCloud a été mis à jour? (par exemple, lorsque l'utilisateur vers d'application de veille-mode)
  • Je suis content d'avoir pu vous aider avec ceci. Comme pour forcer l'application pour vérifier les mises à jour iCloud, il doit vérifier par lui-même dans un délai de quelques secondes à quelques minutes, tout au plus. Si vous voulez vraiment la force de le vérifier, cependant, vous pouvez toujours recharger votre magasin persistant coordonnateur (comme dans mon resetStore méthode ci-dessus). C'est plus une force brute façon d'aller à ce sujet, donc je vais être sûr de mettre à jour ce que je trouve plus élégante des façons d'effectuer des tâches telles que
  • Oui, je pensais aussi même manière. Merci beaucoup. Je suis tellement heureux avec cela. merci pour le partage de votre travail acharné de deux mois. Que dieu vous bénisse.
  • mon plaisir. Et comme je l'ai dit avant, je vais continuer à mettre à jour ce que je figure sur de nouvelles façons de rendre le code plus efficace. Prendre soin dans l'intervalle. Aussi, je viens de réaliser que j'ai oublié de répondre à votre question à propos de l'application. Il est appelé à Maintenir Ma Voiture. Ce n'est pas la plus jolie app là-bas, mais il a certainement fait le tour si vous avez besoin de garder une trace de la réparation des véhicules et la comme
  • Bonjour, long time no voir 🙂 j'ai une autre question cruciale.. j'ai fait face à la même situation avec vous qu'il ne synchronise pas parce que quelque chose est faux. Le problème est présent. comme vous le savez, Tous les de base de données qui ont stocké doit être restaurée, même lorsque vous supprimez de votre application et de la réinstaller. et je vois qu'Il fonctionne bien. mais depuis que le problème est apparu, j'ai supprimer mon appli et de la réinstaller mon application, et rien n'est restauré! C'est tout simplement vide de données. C'est vraiment critique en question... parce que C'est très lié à la sécurité et reponsiblity applications... voyez-vous ce qui se passe ici? Merci
  • pensez-vous est-il de toute façon de l'éviter ou de restaurer les données que je ne peux pas restaurer après l'application de la réinstallation?
  • pensez-vous que ça aide si je ne resetiCloudSync:OUI, autant que je le peux? --;;
  • les informations à partir d'iCloud devrait immédiatement commencer à télécharger une fois qu'une application est réinstallé, à condition que le stockage iCloud fichier n'est pas supprimé (ce qui ne sera pas le faire lorsque vous supprimez l'application et vous auriez à le faire manuellement). Ce que je suggère, serait de rechercher l'application iCloud conteneur. Bien que peu probable, il est possible que l'application tente de créer un nouveau dossier avant de se rendre compte qu'il a déjà un lien dans.
  • Merci beaucoup de votre réponse! la chose que vous venez de dire "Bien que peu probable, il est possible que l'application tente de créer un nouveau dossier avant de se rendre compte qu'il a déjà un à un lien." . Est-il vraiment possible??!! Est-il une solution quand c'est arrivé?
  • et de la fonction que vous avez posté " (void)resetiCloudSync:(BOOL)isSource ". Peut-il donner une de les aider à résoudre mon cas?
  • Je suis tombé dans ce puits, avec une application qui est dans le magasin. Fonctionnait bien, tout d'un coup, tenter d'ouvrir le cloud PS se contente, pas de journal, n'est jamais à la sortie de l'appel. Je ne vois pas comment quelque chose mais en tournant iCloud dérouleront à ce point. La seule autre pensée était peut-être essayer de mettre une minuterie et d'attendre l'appel pour ouvrir le PS, et après un certain temps, de mettre fin que le fil et ensuite appeler nuke et ouvrir et créer un nouveau magasin.. ?
  • Je me risquerais à dire que c'est probablement la meilleure solution pour le moment. Réglez une minuterie de sorte que si le magasin persistant se bloque pour un montant x de temps, vous pouvez mettre en place un local non iCloud magasin (de sorte que l'utilisateur peut continuer à leur utilisation), tout en essayant de se reconnecter sur un thread d'arrière-plan. Si elle atteint donc beaucoup d'essais avec pas de chance, donner à l'utilisateur une option pour réinitialiser complètement le magasin à partir de zéro. À ce stade, vous pouvez utiliser le resetiCloudSync:(BOOL)isSource méthode que j'ai écrit ci-dessous ou quelque chose de similaire à pousser toutes les notifications de nouveau dans l'iCloud magasin persistant
  • bonjour Vesl, comment votre "mergeiCloudChanges" méthode ressemble? Je pense que C'était dans votre texte, mais je ne peux pas le trouver maintenant(pourquoi?).
  • Vesl, C'est encore moi. Quelle est la différence entre le code que vous avez écrit ici et pour les autres est normal coredata+iCLoud tutoriel code. Je ne parle pas en dessous de resetiCloud méthode, mais ici.
  • le mergeChangesFrom_iCloud:(NSNotification *)notification méthode est dans la question ci-dessus le texte. La différence entre le présent code et que le tutoriel de code, c'est que ce code a un couple de garanties dans le cas où il y a une question de la création de l'iCloud de persistance ou le magasin doit être réinitialisé. Les principales méthodes de création sont basés sur le stock de code fourni
  • et ma question était que là où il est "mergeiCloudChanges" méthode qui est appelée plusieurs fois dans mergeChangesFrom_iCloud méthode.
  • oh, désolé. Je comprends ce que vous demandez. Je vais l'ajouter dans le primaire à la question ci-dessus sous la mergeChangedFrom_iCloud méthode. Désolé pour la confusion.
  • OK, donc je suis venue dans cette voie après le fait, mais quelqu'un a créé une catégorie avec ce code afin qu'il soit un lieu? Je pense que je peux obtenir la version actuelle de ce qui a été fait ici, mais je pense que ce serait formidable si, étant donné qu'il semble avoir aidé beaucoup, il a été mis dans une catégorie et disponible sur github ou similaire.
  • Je vais voir ce que je peux faire pour obtenir un projet de test sur github à cette fin. J'ai quelques jours de congé à venir, et puis. Je vais mettre à jour ce sujet avec un lien vers le code source lorsqu'il est téléchargé
  • ce serait génial. J'ai dû mettre icloud de côté pour l'instant et je peux me concentrer sur les principales fonctions de l'application, mais il est vraiment important d'obtenir que la synchronisation icloud va.

InformationsquelleAutor justin | 2011-11-05