2017-04-18 4 views
0

Le Christ est ressuscité (avec une joie de la fête de Pâques)!
Lors du test d'une application après le refactoring d'une petite application, j'ai reçu un journal de panne "Crashlytics". Essayait de changer le modèle pour éviter l'appel de la méthode de double synchronisation (en même temps) en envoyant tous les prochains appels (à partir du deuxième appel) vers la file d'attente série privée. J'ai ajouté le code suivant:Comment savoir ce qui a causé un rapport d'erreur sur un périphérique IOS?

@interface SynchronizationModel() 

@property (nonatomic) dispatch_queue_t synchronizationQueue; 

@end 

@implementation SynchronizationModel 

BOOL isSynchronizationNotCalled = YES; 

#pragma mark - Synchronization 

+ (dispatch_queue_t)synchronizationQueue { 
    static dispatch_queue_t queue; 
    static dispatch_once_t onceToken; 
    const char *queueID = "com.app.synchronizationModel.queue"; 

    dispatch_once(&onceToken, ^{ 
     queue = dispatch_queue_create(queueID, DISPATCH_QUEUE_SERIAL); 

    }); 

    return queue; 
} 

+ (void)sychronizeOfflineObjects { 
    if (isSynchronizationNotCalled) { 
     NSLog(@"%d synchronization without a queue, flag notCalled =", isSynchronizationNotCalled); 
     isSynchronizationNotCalled = NO; 
     [self synchronizeOfflineObjectsNonAsynchronous]; 
    } else { 
     NSLog(@"%d synchronization inside of a queue, flag notCalled =", isSynchronizationNotCalled); 
     isSynchronizationNotCalled = NO; 
     __weak typeof(self)weakSelf = self; 
     dispatch_async(self.synchronizationQueue, ^{ 
      __strong typeof(weakSelf)strongSelf = weakSelf; 
      [strongSelf synchronizeOfflineObjectsNonAsynchronous]; 
     }); 
    } 
// [self sychronizeOfflineObjects]; - uncomment for recursive test 
    isSynchronizationNotCalled = YES; 
    } 

Testé en utilisant un appel récursif comme vous pouvez le voir. Cela a fonctionné. Mais avoir la possibilité d'essayer de lancer l'application sur un appareil personnellement.
Cette méthode est appelée dans les très rares endroits. Principalement dans le contrôleur apparent:

- (IBAction)buttonWasTapped:(id)sender { 
    if(self.buttonImage.layer.animationKeys.count == 0){ 
     [self synchronizationMethod]; 
    } 
} 

- (void)synchronizationMethod { 
    NSLog(@"startWorkWithServer - originally here is some code but it works perfect"); 
     [SynchronzationModel sychronizeOfflineObjects]; 
    } else { 
     [self startAnimation]; 
     [self performSelector:@selector(delayStop) withObject:nil afterDelay:2.0]; 
     if([webConnectionAllowed isEqualToString:@"NotAllowed"]){ 
      [self showAlertWithTitle:nil message:NSLocalizedString(@"Connection is allowed", nil)]; 
     } 
    } 
} 

J'ai envoyé l'application à mon chef d'équipe pour le check-out. Il a lancé une application sur un périphérique, mais en un instant (supposons que cela fonctionne depuis un certain temps), il a été désactivé avec un message d'erreur SIGABRT.

rapport Crashlytics retourne:

#0. Crashed: com.twitter.crashlytics.ios.exception 
0 App       0x18751d CLSProcessRecordAllThreads + 820509 
1 App       0x18751d CLSProcessRecordAllThreads + 820509 
2 App       0x187415 CLSProcessRecordAllThreads + 820245 
3 App       0x17b34f CLSHandler + 770895 
4 App       0x185dfb __CLSExceptionRecord_block_invoke + 814587 
5 libdispatch.dylib    0x1c942083 _dispatch_client_callout + 22 
6 libdispatch.dylib    0x1c94e33b _dispatch_barrier_sync_f_invoke + 50 
7 App       0x1857fd CLSExceptionRecord + 813053 
8 App       0x185625 CLSExceptionRecordNSException + 812581 
9 App       0x18513b CLSTerminateHandler() + 811323 
10 libc++abi.dylib    0x1c4f393f std::__terminate(void (*)()) + 78 
11 libc++abi.dylib    0x1c4f3443 __cxa_rethrow + 90 
12 libobjc.A.dylib    0x1c4ff1bb objc_exception_rethrow + 42 
13 CoreFoundation     0x1d1a55a1 CFRunLoopRunSpecific + 596 
14 CoreFoundation     0x1d1a5341 CFRunLoopRunInMode + 104 
15 GraphicsServices    0x1e97cbfd GSEventRunModal + 156 
16 UIKit       0x223b3e27 -[UIApplication _run] + 574 
17 UIKit       0x223ae551 UIApplicationMain + 150 
18 App       0x148daf main (main.m:14) 
19 libdispatch.dylib    0x1c96f50b (Missing) 

Mais depuis au moins je n'ai pas le fichier dSYM (seulement txt de Crashlytics) s `aucune manière évidente pour moi de symbolicate le journal d'accident ou de comprendre les causes le problème. Je vais le tester sur mon appareil, mais je ne suis pas sûr qu'il va tomber en panne.

Il semble que quelque chose se passe avec un Threads, mais je ne suis pas sûr exactement ce qu'est l'indice. Quelqu'un peut-il conseiller comment déterminer l'emplacement causant le problème.

Un ajout de plus: il y a quelques personnes qui travaillent sur un projet (je suis assez nouveau) et je ne suis même pas sûr que le code placé dessus a déclenché l'erreur (mais très probablement) était même avant que mes changements ont eu lieu. J'ai juste aded une petite méthode, appelant la méthode normalement pour la 1ère fois et envoyant tous les appels de repos se produit dans la même heure à la file d'attente sérielle privée. Comme cela a fonctionné de manière récursive et qu'il s'agit d'un petit changement et qu'il n'utilise qu'une seule file d'attente série privée supplémentaire, il me semble un peu trop petit pour un crash réel (avec le problème Threads dans un rapport).

Apprécierait n'importe quel conseil.

+0

Vous n'avez pas fourni de définition pour: 'synchronizeOfflineObjectsNonAsynchronous' – Brandon

+0

Oui, j'imagine que ce modèle fonctionnait correctement avant que j'apporte les modifications par-dessus, donc j'ai ajouté seulement du code qui a été fait par moi-même. Et cela rendrait également ce post plus grand.Mais si vous pensez que cela pourrait clarifier la situation, je pourrais ajouter plus de code? – Alexander

+0

+ (void) synchronizeOfflineObjectsNonAsynchronous {[self changeUser]; if ([AppGroups allObjects] .count == 0) {[[OfflineChangesModel sharedInstance] terminé]; revenir; } if (! mainGroupId) {[self synchronisationForNoMainGroupID]; } else {[self synchronisationForMainGroupID]; }}. Je pourrais ajouter plus de code pour le synchronizationForNoMainGroupID et le synchronizationForMainGroupID si c'est nécessaire mais cela a fonctionné bien avant que j'aie fait les changements écrits ci-dessus. – Alexander

Répondre

0

Il semblerait que j'aurais dû utiliser les modificateurs corrects ici. Ajouter le "fort" à la propriété synchronizationQueue a résolu ce problème.

Ce message a aidé à trouver la solution.

What property should I use for a Dispatch Queue after ARC?

Avant ARC les files d'attente utilisées à traiter comme un type d'objet non si le "Assign" a un long chemin. Le laisser vide fonctionnerait parce que c'était un modificateur par défaut pour les types non-objet.

Non après l'introduction de l'ARC, les files d'attente sont traitées comme des objets Objective-c et nous devons utiliser "strong" avec elles. Pour être mentionné, le "fort" est maintenant un attribut de propriété par défaut pour les objets Objective-c, mais je ne sais toujours pas pourquoi il n'a pas fonctionné dans le cas donné ci-dessus.