Mon application utilise des données de base. J'ai récemment mis à niveau vers Xcode 10.2 et Swift 5 et depuis lors, je reçois des plantages aléatoires qui ont quelque chose à voir avec les données de base.
D'après ce que j'ai rassemblé, cela s'est produit lors de la tentative de modification des données de base à partir d'un thread d'arrière-plan (après avoir extrait de nouvelles données du serveur).
Je reçois le message d'erreur suivant
2019-03-31 14:49:17.358685+0300 LeaderMES[24226:595701] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSTaggedDate objectForKey:]: unrecognized selector sent to instance 0x8000000000000000'
Ou
2019-03-31 14:37:04.676485+0300 LeaderMES[23749:583097] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSCoreDataTaggedObjectID objectForKey:]: unrecognized selector sent to instance 0x8000000000000000'
Non seulement mon code fonctionnait, ce numéro d'instance semble suspect
Mon application est connectée à crashlytics qui a détecté l'une de ces erreurs. Voici la trace de pile détectée:
Fatal Exception: NSInvalidArgumentException
0 CoreFoundation 0x1086f86e3 (Missing)
1 libobjc.A.dylib 0x10771bac5 objc_exception_throw
2 CoreFoundation 0x108716ab4 (Missing)
3 CoreFoundation 0x1086fd443 (Missing)
4 CoreFoundation 0x1086ff238 (Missing)
5 libswiftCore.dylib 0x109914dcc (Missing)
6 libswiftCore.dylib 0x109b407b9 (Missing)
7 LeaderMES 0x105080a8d closure #1 in LMNotificationRepository.loadNotificationHistory(forFactory:successCompletion:errorCompletion:) (LMNotificationRepository.Swift:360)
8 LeaderMES 0x105091271 partial apply for closure #1 in LMNotificationRepository.loadNotificationHistory(forFactory:successCompletion:errorCompletion:) (<compiler-generated>)
9 LeaderMES 0x10510b872 closure #1 in LMHttpProvider.procedeRequest(_:completionHandler:) (LMHTTPProvider.Swift:299)
10 LeaderMES 0x10510e381 partial apply for closure #1 in LMHttpProvider.procedeRequest(_:completionHandler:) (<compiler-generated>)
11 LeaderMES 0x1050ce176 thunk for @escaping @callee_guaranteed (@guaranteed Data?, @guaranteed NSURLResponse?, @guaranteed Error?) -> () (<compiler-generated>)
12 CFNetwork 0x10adf6178 (Missing)
13 CFNetwork 0x10ae0cc56 (Missing)
14 Foundation 0x10666f412 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__
15 Foundation 0x10666f31a -[NSBlockOperation main]
16 Foundation 0x10666c1f4 -[__NSOperationInternal _start:]
17 Foundation 0x106671f5b __NSOQSchedule_f
18 libdispatch.dylib 0x10a539ccf (Missing)
19 libdispatch.dylib 0x10a53ad02 (Missing)
20 libdispatch.dylib 0x10a53d6be (Missing)
21 libdispatch.dylib 0x10a53cd49 (Missing)
22 libdispatch.dylib 0x10a549ad3 (Missing)
23 libdispatch.dylib 0x10a54a330 (Missing)
24 libsystem_pthread.dylib 0x10a91c6b3 (Missing)
25 libsystem_pthread.dylib 0x10a91c3fd (Missing)
Quels sont tous les dylibs manquants mentionnés?
J'ai essayé de déplacer toute l'activité Core Data vers le thread principal en utilisant DispatchQueue sans succès.
J'ai supprimé l'application du simulateur et l'ai réinstallée et jusqu'à présent, le crash ne se répète pas. Des idées sur la cause de ce crash?
Cela ressemble à un bogue pour les versions non optimisées effectuées dans Xcode 10.2. Je n'utilise pas de données de base dans mon application et cela se bloque également avec
-[xxx objectForKey:]: unrecognized selector sent to instance 0x8000000000000000'
XXX est parfois __NSTaggedDate
, parfois c'est un autre type mais l'adresse est toujours 0x8000000000000000
. Le débogueur s'arrête sur une ligne lorsque j'accède à un dictionnaire valide par une clé valide et ce n'est pas du tout utile. L'application cesse de planter lorsque j'ai modifié l'optimisation en Optimise for speed -O
pour le schéma de débogage.
Vous envoyez une méthode objectForKey: qui est généralement utilisée pour les dictionnaires. Le récepteur est cependant un objet TaggedDate. TaggedDate est fondamentalement le même que NSDate (pour nos besoins ici). Donc, d'une manière ou d'une autre, vous avez réussi à avoir un objet NSDate où vous attendez un dictionnaire.
Ajoutez un point d'arrêt sur exception, afin de pouvoir revenir à l'appelant et comprendre pourquoi vous avez un objet NSDate où vous attendiez un dictionnaire. Attendez-vous à une ligne comme dict [@ "une touche"] lorsque dict s'avère être une NSDate.
Un problème similaire se produisait pour moi lorsque je modifiais et accédais à un objet à partir de deux threads différents (à deux endroits différents dans mon code) en même temps, l'adresse devait avoir changé. J'ai résolu en utilisant un DispatchQueue pour synchroniser l'accès à cet objet
var lock: DispatchQueue = DispatchQueue.init (étiquette: "")
lock.sync {objet d'accès}