8

È stato rilasciato un aggiornamento minore della nostra app, questa versione ha anche modificato l'ID app da un ID univoco al nostro ID team dal supporto Apple.Il pulsante di azione UILocalNotification di iOS blocca e corrompe i dati dell'app

According to Apple, la modifica all'uso di Team ID deve solo reimpostare l'accesso al portachiavi, non viene utilizzato il portachiavi, quindi non dovrebbe avere alcun effetto sulla nostra app.

Ma dal momento che l'aggiornamento è stato rilasciato, alcuni dei nostri utenti in produzione hanno riscontrato danneggiamento dei dati delle loro app. Ciò si verifica solo quando rispondono a una notifica locale utilizzando un pulsante di azione dal Centro notifiche o dalla schermata di blocco. Può accadere su tutte le versioni iOS supportate.

Gli utenti che hanno questo hanno un altro sintomo, ricevono due notifiche locali invece di una sola, ma l'app vede solo una notifica. Inoltre, queste notifiche non andranno via dopo aver disattivato le notifiche e la cancellazione utilizzando [[UIApplication sharedApplication] cancelAllLocalNotifications].

Queste notifiche duplicate erano pianificate prima che l'app fosse aggiornata dall'App Store, ma dopo che l'app di aggiornamento aveva perso il controllo su di esse per alcuni utenti. Questo problema è descritto in dettaglio in this question.

Il più grande indizio può fissare nei report di crash ricevuti da Apple -

Incident Identifier: ED0E9C.............74B38C 
CrashReporter Key: ae05b............dbc46 
Hardware Model:  iPhone4,1 
Process:    MY_APP [444] 
Path:    /private/var/mobile/Containers/Bundle/Application/65324..................8616/MY_APP.app/MY_APP 
Identifier:   com.mycompany.myapp 
Version:    X.X 
Code Type:   ARM (Native) 
Parent Process:  launchd [1] 

Date/Time:   2015-10-27 21:45:24.24 -0500 
Launch Time:   2015-10-27 21:45:20.20 -0500 
OS Version:   iOS 9.1 (13B143) 
Report Version:  104 

Exception Type: EXC_CRASH (SIGABRT) 
Exception Codes: 0x0000000000000000, 0x0000000000000000 
Exception Note: EXC_CORPSE_NOTIFY 
Triggered by Thread: 0 

Last Exception Backtrace: 
0 CoreFoundation     0x244b3676 __exceptionPreprocess + 122 (NSException.m:162) 
1 libobjc.A.dylib     0x3582ee12 objc_exception_throw + 34 (objc-exception.mm:531) 
2 CoreFoundation     0x244b354c +[NSException raise:format:arguments:] + 100 (NSException.m:131) 
3 Foundation      0x25240bc4 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 88 (NSException.m:152) 
4 UIKit       0x28840754 -[UIApplication _runWithMainScene:transitionContext:completion:] + 2928 (UIApplication.m:3299) 
5 UIKit       0x28853a48 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke3218 + 32 (UIApplication.m:11920) 
6 UIKit       0x2883d71e -[UIApplication workspaceDidEndTransaction:] + 130 (UIApplication.m:2648) 
7 FrontBoardServices    0x2c52dca2 -[FBSSerialQueue _performNext] + 226 (FBSSerialQueue.m:157) 
8 FrontBoardServices    0x2c52df94 -[FBSSerialQueue _performNextFromRunLoopSource] + 44 (FBSSerialQueue.m:204) 
9 CoreFoundation     0x24476bfa __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 10 (CFRunLoop.c:1761) 
10 CoreFoundation     0x244767e8 __CFRunLoopDoSources0 + 448 (CFRunLoop.c:1807) 
11 CoreFoundation     0x24474b56 __CFRunLoopRun + 790 (CFRunLoop.c:2536) 
12 CoreFoundation     0x243c8114 CFRunLoopRunSpecific + 516 (CFRunLoop.c:2814) 
13 CoreFoundation     0x243c7f00 CFRunLoopRunInMode + 104 (CFRunLoop.c:2844) 
14 UIKit       0x28610208 -[UIApplication _run] + 520 (UIApplication.m:2489) 
15 UIKit       0x2860af10 UIApplicationMain + 140 (UIApplication.m:3665) 
16 MY_APP       0xc4972 main + 22 (main.m:14) 
17 libdyld.dylib     0x35f9d86e tlv_get_addr + 42 (threadLocalHelpers.s:310) 

Ha uno stacktrace esattamente lo stesso come in this question, che avviene quando gli utenti rispondono a una notifica push. L'arresto anomalo durante il caricamento dell'app potrebbe spiegare i dati danneggiati dell'app.

Come visto nello stacktrace questo crash non è causato dal nostro codice, non abbiamo cambiato nulla nel codice, ha funzionato bene prima della modifica dell'App ID e succede a ~ 2% dei nostri utenti.

Ecco il codice che gestisce pulsanti di azione di notifiche -

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler { 

    @try { 
     if (notification) { 
      NSDate *alarmTime = notification.userInfo ? [notification.userInfo objectForKey:@"time"] : nil; 
      [logic saveAlarmTime:alarmTime takenAt:[NSDate date]]; 
     } 
    } 
    @catch (NSException *exception) { 
     NSLog(@"Exception: %@", [exception description]); 
    } 
    @finally { 
     completionHandler(); 
    } 
} 

Quali sono le cause di questo incidente?

(lo so che è gettato in -[UIApplication _runWithMainScene:transitionContext:completion:] + 2928 (UIApplication.m:3299), questione è che cosa c'è lì dentro che causa questo il crash.)

+0

può [questa domanda] (http://stackoverflow.com/questions/30884896/application-windows-are-expected-to-have-a-root -view-controller-at-the-end-of-a) essere utile? C'è la stessa traccia di stack per l'arresto come nella tua domanda. È possibile che la tua app trasmetta l'utente a qualche controller di visualizzazione dopo aver aperto l'app tramite la notifica push, ma l'apertura di questo controller viene eseguita con '[window addSubview: viewController.view];' invece di '[window setRootViewController: viewController] ; '? Questo non risolve il problema di due notifiche, ma forse questi sono entrambi i bug/aggiornamenti di Xcode 7 – medvedNick

+0

Solo un suggerimento. Controlla tutti gli osservatori per la notifica. Di sicuro chiamando 'removeObserver:' in 'dealloc' di questi oggetti Observer. E http://stackoverflow.com/questions/26371462/weird-crash-when-launching-app-from-notification-center – anhtu

+0

@anhtu che non è questo tipo di notifica, stiamo parlando di Notifiche locali, gli osservatori non sono stati utilizzati per questo motivo. – Kof

risposta

4

È possibile che questa eccezione non sia correlata alla risposta a una notifica tramite un pulsante di azione in primo luogo. Questa traccia dello stack indica un problema durante il caricamento dell'app, ma ha diverse possibili cause, tutto ciò che causa il crash dell'applicazione durante il caricamento.

Ad esempio, può verificarsi quando l'app viene caricata e alla sua finestra non è assegnato un controller di visualizzazione radice. Può verificarsi anche se è stato aggiunto utilizzando addSubview anziché setRootViewController, come visto here.

È necessario verificare con gli utenti che hanno riscontrato questo arresto anomalo quello che stavano facendo, se in effetti hanno risposto solo a un pulsante di azione di notifica locale o se hanno avuto il crash durante l'apertura dell'app.

-1

Questa linea fa sì che l'incidente:

[UIApplication _runWithMainScene:transitionContext:completion:] + 2928 (UIApplication.m:3299) 

Se una squadra cambia per un app anche l'identificatore di app univoco per quell'app cambia poiché è parte di esso. Le notifiche locali utilizzano l'identificativo dell'app univoco. Quindi è fondamentalmente un bug di Apple, dal momento che iOS dovrebbe riconoscere la notifica che non ha più l'app corrispondente. E questo è anche il tuo crash da quando sei stato lanciato ma non ottieni l'oggetto con cui normalmente lavorerai.

Immagino cieco poiché non conosco il tuo codice. Quando si risponde a una notifica locale, verificare se l'oggetto e tutti i dati associati sono presenti prima di continuare. Sai, qualcosa di simile a:

if (object) { 
    //do the stuff 
} else { 
    // do nothing 
} 

(il modo migliore di eccezioni imho ...)

Per quanto riguarda la notifica che non appartiene più a voi - gli utenti possono cancellato loro stessi. Assicurati di non schiantarti: non fare nulla va bene.Di solito ppl li cancella da solo a un certo punto, quindi puliscono il loro centro di notifica.

+1

Questo in sostanza ripete le conclusioni nella domanda originale, in altre parti non sono nemmeno sicuro di come sia correlato. "è fondamentalmente un bug di Apple" - basato su cosa? – Kof

+0

Vedo che non hai effettuato la connessione. 1) Si tratta di un bug di Apple perché c'è una notifica per l'app che non fa parte della squadra. 2) È un bug anche sul tuo codice dato che non gestisci nulla da qualche parte. Ecco perché vedi l'affermazione saltare in.Ti affidi al tuo codice che qualcosa è lì, ma non lo è. Probabilmente la notifica appartiene alla tua app, ma non alla tua squadra. –

+0

No, tutti gli oggetti vengono controllati per nil prima dell'uso. Non arriva nemmeno al codice dell'app, '0xc4972 main + 22 (main.m: 14)' non è il mio codice, avvia solo 'UIApplicationMain' che è la classe di iOS che esegue l'app, si blocca da qualche parte sul modo, prima di arrivare al codice della mia app. – Kof

0

La causa del danneggiamento dei dati è stata l'opzione "Protezione dati". Può essere abilitato da Xcode o dal portale per sviluppatori iOS, in Identificatori -> ID app.

Xcode data protection option

Ha tre stati: "Protezione completa", "Protected A meno Open" e "Protected Fino Autenticazione primo utente". Finché i dati sono protetti, nemmeno l'app può accedere ai dati.

iOS Developer Portal

Ad esempio, se "Protezione completa" è stato selezionato come nel nostro caso, e un processo in background come il pulsante di azione di notifica è in esecuzione, Core Data non avrà accesso al database a causa di errore di autorizzazione.

Non sono ancora sicuro del motivo per cui ha danneggiato i dati, a volte l'errore "Autorizzazione definita" non veniva visualizzato ma non riusciva ancora a leggere il file SQLite. Forse è anche scritto sul file, ma siccome la crittografia era ON, ha danneggiato il file.

La soluzione è scegliere "Protetto fino a prima autenticazione utente" o per disabilitare la protezione dei dati.

SO connessa interrogazione: CoreData errors/exceptions when app work in background mode

Apple's iOS Security PDF

Problemi correlati