Sostituire un oggetto in una particolare posizione di un array

Ci sono molti casi in cui diventa necessario aggiungere elementi in NSMutableArray senza però usare il metodo addObject:, il quale, ovviamente, aggiunge l’oggetto in coda all’array, in ultima posizione. Si può usare quindi il metodo insertObject:atIndex. Ma ancora più utile è sapere che se, per esempio, si volesse sostituire un UIBarButtonItem in una ToolBar, non è necessario andare andando a cercare nell’array [items mutableCopy] l’UIBarButtonItem da eliminare, rimuoverlo con removeObjectAtIndex: e poi inserire quello nuovo con insertObject:atIndex. Si può infatti direttamente usare replaceObjectAtIndex:.

Sapere se la connessione è andata in timout

Usando NSURLConnection può capitare, per i più svariati motivi, che la connessione e il download dei dati non avvengano entro un certo tempo limite, detto timeout. Superato questo limite la connessione decade.

Per sapere se la connessione si è interrotta proprio per il raggiungimento del timeout si possono sfruttare le informazioni contenute nell’oggetto NSError usato per far partire la connessione, in questo modo:

1
2
3
4
5
6
NSError *error = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
 
if (error.code == NSURLErrorTimedOut) {
 
}
NSError *error = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

if (error.code == NSURLErrorTimedOut) {

}

nel creare la NSURLRequest, si può impostare questo valore di timeout, in secondi:

1
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];

Creare un completion handler

Comodissimi sono i blocchi di codice eseguiti quando un certo metodo si conclude, in particolare animazioni e metodi in background, gestiti con GCD (Grand Central Dispatch) o direttamente da classi Apple, come NSURLConnection. Può essere quindi utile saper creare un completion handler, ovvero un blocco di codice che viene eseguito solo quando un metodo effettivamente si conclude, espandendo quindi le funzionalità in maniera importante.

Innanzitutto si dichiara il blocco di ritorno del completion handler, avendo cura di inserire gli eventuali oggetti e variabili da ritornare: ad esempio un codice che effettui il download di un  pacchetto di dati potrebbe restituire un oggetto NSData e/o un BOOL success:

1
typedef void(^ReturnBlock)(NSData *data, BOOL success);
typedef void(^ReturnBlock)(NSData *data, BOOL success);

Il completion handler può essere quindi una variabile di istanza di tipo ReturnBlock dichiarata nello stesso file d’interfaccia in cui si è definito il ReturnBlock:

1
2
3
4
@interface MyClass : NSObject
{
    ReturnBlock _completionHandler;
}
@interface MyClass : NSObject
{
    ReturnBlock _completionHandler;
}

Il metodo che fa uso di questo completio handler sarà qualcosa del genere

1
- (void)doSomethingWithCompletionHandler:(ReturnBlock)aCompletionHandler;
- (void)doSomethingWithCompletionHandler:(ReturnBlock)aCompletionHandler;

Nella cui implementazione, se ad esempio si sta usando la classe NSURLConnection per gestire il download, si scriverà nel metodo delegato:

1
2
3
4
5
6
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
 
if( _completionHandler )
    _completionHandler(data, YES);
 
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{

if( _completionHandler )
    _completionHandler(data, YES);

}

Quindi, ovunque allochiamo e inizializiamo una istanza di MyClass, possiamo anche usare il seguente modo il metodo:

1
2
3
[myClass doSomethingWithCompletionHandler:^(NSData *data, BOOL success)^{
 
}];
[myClass doSomethingWithCompletionHandler:^(NSData *data, BOOL success)^{

}];

il blocco di codice verrà eseguito solo al completamento di qualunque cosa doSomething faccia, passando l’oggetto data e la variabile booleana success.

N.B.: con ARC non c’è bisogno di copiare il completion handler nel metodo doSomething né di rilasciarlo in dealloc.

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”;