Git: file is missing

Quando si usare git su Xocde può capitare che qualcosa vada storto e dei file, magari semplicemente spostati da una cartella ad un altra, risultino mancanti.

È questo il caso di quando appare nella schermata del Commit un punto interrogativo a fianco ad un file e nell’editor di fianco il messaggio:

1
file is missing
file is missing

Ovviamente questo può accadere anche ad una cartella.

Per ovviare a questo fastidioso problema, che provoca anche dei relativi Warning in fase di compilazione, è sufficiente aprire il Terminale, posizionarsi nella cartella del progetto, e forzare un commit con questo comando:

1
git commit -a -m "Commit Message"
git commit -a -m "Commit Message"

A volte, se avete più Xocde installati, potrebbe essere necessario specificare dove si trova la versione che state usando:

1
sudo xcode-select --switch /Applications/Xcode\ 8/Xcode.app
sudo xcode-select --switch /Applications/Xcode\ 8/Xcode.app

The data couldn’t be read because it isn’t in the correct format: ecco come validare un file .plist

Xcode permette di modificare un plist anche in vista “Source Code”, molto comoda per modifiche massicce. Però quando si commette un errore e la sintassi non è più quella corretta, Xcode avvisa solo per il formato non è valido, senza alcuna indicazione sulla riga di codice errata: “The data couldn’t be read because it isn’t in the correct format”.

Inoltre non permette di tornare alla vista Property List finché non si è trovato l’errore.

Per poter validare un plist e trovare gli errori allora basta aprire il Terminale, spostarsi nella cartella del file plist e digitare

1
plutil file-name.plist
plutil file-name.plist

Questo restituirà l’elenco degli errori trovati (es: Encountered misformatted real on line 539) oppure restituirà OK.

Error: Could not load the “…” image referenced from a nib in the bundle with identifier “…”

Può capitare di aggiungere una immagine, o una qualsiasi altra risorsa (anche file di codice .h e .m) ma ricevere questo errore in fase di compilazione:

1
Could not load the "..." image referenced from a nib in the bundle with identifier "…"
Could not load the "..." image referenced from a nib in the bundle with identifier "…"

Questo accade perché il progetto contiene la risorsa ma non è correttamente dichiarata nella sezione “Copy Bundle Resources” che si trova nel “Build Phases” del Target. Basterà quindi aggiungerla manualmente tramite il piccolo pulsante “+” e da quel momento la fase di compilazione non restituirà più questo errore.

Uso del blocco @try

In tutte quelle situazioni in cui possono verificarsi potenziali errori, il linguaggio obiettive-c ci mette a disposizione una struttura di controllo che permette di “provare” il codice. Si tratta del blocco @try, seguito da @catch (eseguito solo se viene sollevata una eccezione) e da @finally (eseguito in ogni caso).

1
2
3
4
5
6
7
8
9
10
11
12
NSString* test = [NSString stringWithString:@"ss"];
 
 @try {
    [test characterAtIndex:6];
 
 }
 @catch (NSException * e) {
    NSLog(@"Exception: %@", e);
 }
 @finally {
    NSLog(@"finally");
 }
NSString* test = [NSString stringWithString:@"ss"];

 @try {
    [test characterAtIndex:6];

 }
 @catch (NSException * e) {
    NSLog(@"Exception: %@", e);
 }
 @finally {
    NSLog(@"finally");
 }

Bisogna ricordarsi di disattivare eventuali breakpoint settari su exception perché il programma si bloccherebbe (in pausa) anche se questo codice è pensato proprio per evitare interruzioni.

Errore: CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 23. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.

Se la Console mostra il seguente errore:

CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 23. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.

 

e la localizzazione sembra non funzionare più, anche se il progetto viene compilato senza errori né  warning, allora vuol dire che avete dimenticato un punto e virgola all’interno del file Localizable.string.

Ricordo, con l’occasione, che usando la funzione

NSLocalizedString(@”Hello”, @”Comment”);

nel file Localizable.string (ad esempio nella sua versione italiana) bisogna scrivere:

“Hello” = “Ciao”;

Importare un UIViewController e il suo xib in un nuovo progetto

Se abbiamo creato e personalizzato un UIViewController, compreso il suo xib, in un progetto, e siamo stati così bravi da voler riutilizzare il tutto, allora possiamo prendere i file .h, .m e .xib e trascinarli nel nuovo progetto.

Unica accortezza sarà quella di selezionare il corretto target nell’inspector dei file .m e .xib nella proprietà “Target Membership”, questo per evitare di ottenere l’errore seguente:

Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Could not load NIB in bundle: ‘NSBundle <percorso app> (loaded)’ with name ‘<nome controller>”

Warning: localizzare l’immagine di Default (Launch image)

Talvolta può presentarsi un Warning quando tentiamo di archiviare (o lanciando un Build for>Archiving) un’app che presenta un localizzazione dell’immagine di default, ovvero l’immagine che appare prima che l’app sia caricata e lanciata.

L’errore è il seguente:

warning: Icon specified in the Info.plist not found under the top level app wrapper: Default-Landscape@2x~ipad.png

lo specifico file è di un’app per iPad ma il problema è del tutto generale e blocca qualsiasi tentativo di pubblicare l’app in App Store.

Nonostante si intuisca dal testo del warning stesso e venga anche specificato nella documentazione di Apple, non è risolutivo includere nella directory di root dell’app l’immagine di default nella lingua di default (quella da visualizzare quando la localizzazione corretta non è disponibile, spesso quindi in lingua inglese), ovvero l’app non viene più bloccata dalla compilazione per l’archiviazione, ma l’immagine di default rimane sempre quella in lingua di default.

Nel mio caso una pulizia completa del Info.plist, eliminando i nomi immagini provvisorie che erano rimaste memorizzate in tale file come immagini di default alternative ma non più utilizzate lanciando un Clean dal menu Product e ricompilando, la successiva compilazione per l’archiviazione è andata buon fine, pur essendo tecnicamente esattamente tutto come prima.

Se qualcuno dovesse trovare una spiegazione a tutto ciò, non esiti a scriverlo nei commenti così che possa integrare questo articolo.

Notifiche Push: idee ed avvertenze

Quando si implementano le Notifiche Push può essere utile, talvolta, di notificare solo il cambiamento di badge, senza suono né testo.

E viceversa si può fare in modo che le notifiche con testo vengano mostrate come UIAlertView quando vengono ricevute ad app aperta, grazie al metodo application:didReceiveRemoteNotification: e grazie ad un dizionario che alla chiave “aps” contiene, fra l’altro, il testo della notifica.

Apple usa JSON come formato di comunicazione fra il server delle notifiche e l’app e questo formato restituisce un NSCFBoolean se il valor è zero, oppure un NSCFString se è una stringa. Quindi cosa accade se riceviamo una notifica muta ad app aperta?

Prima di creare l’alert dobbiamo sincerarci di aver ricevuto una stringa e quindi usiamo il metodo isKindOfClass e la seguente condizione:

1
2
3
4
5
6
id notification = [userInfo objectForKey:@"aps"] valueForKey:@"alert"];
 
if ([notification isKindOfClass:[NSString class]]) {
     // mostra alert
 
}
id notification = [userInfo objectForKey:@"aps"] valueForKey:@"alert"];

if ([notification isKindOfClass:[NSString class]]) {
     // mostra alert

}

In questo modo non si rischierà di usare un booleano dove invece andrebbe usata una stringa, con conseguente crash assicurato dell’app a causa di un errore del tipo:

-[__NSCFBoolean isEqualToString:[: unrecognized selector sent to instance…

wait_fences: failed to receive reply: 10004003

Il criptico warning riportato nel titolo, ovvero “wait_fences: failed to receive reply: 10004003″, può comparire nella Console quando si tenta di fare il push o il presenti di una view prima che un’altra (classico esempio una alertview) sia effettivamente dismessa.

Essendo la presentazione e la dismissione di una alertview animate, non attendere che questa animazione sia completata, prima di caricare un’altra view, può rappresentare un problema, e Xcode ce lo segnala con questo avviso nella Console.

La soluzione sarà quindi semplicemente quella di usare il metodo didDismissWithButtonIndex: (grazie all’UIAlertViewDelegate) per il resto del codice che dev’essere eseguito dopo aver lanciato il dismissWithClickedButtonIndex:animated:

Simmetricamente, se si mostra un alertview per far attendere un caricamento all’utente, bisognerà aspettare che l’alertview sia effettivamente presentata per eseguire il codice che carica il contenuto, ovvero usando un didPresentAlertView. Questo eviterà comportamenti non fluidi nell’animazione, anche se non si rischia di ottenere lo stesso errore che nel caso precedente.

Errori nella Console durante l’uso di AVFoundation nel Simulatore

Se utilizzate il framework AVFoundation per la riproduzione di suoni e video sappiate che gli errori, comparsi nella Console da quando avete aggiornato ad iOS 5, sono perfettamente ignorabili e innocui.

Ecco un piccolo stralcio degli errori che potreste leggere:

1
Error loading /System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn:  dlopen(/System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn, 262): Symbol not found: ___CFObjCIsCollectable
Error loading /System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn:  dlopen(/System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn, 262): Symbol not found: ___CFObjCIsCollectable

Un indizio di quanto questi errori siano in realtà ignorabili sta nel fatto che se non eseguite l’app nel Simulatore, bensì sul dispositivo vero e proprio, vi accorgerete che questi errori scompariranno. Probabilmente si tratta solamente di log prolissi dovuti all’assenza di un reale dispositivo audio video come quello di un iPhone o iPad. È anche probabile che in futuri aggiornamenti di Xcode e/o iOS questa prolissità venga attenuata.