Filtrare un NSArray con un criterio

Vogliamo eliminare da un array tutti gli elementi che non rispettano un certo criterio? Esiste un metodo velocissimo che permette di fare questo se, ad esempio, si tratta di Array di NSString. Eccolo

1
2
//il predicato conserva solo gli elementi la cui condizione è vera
Array = [Array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != %@", string]];
//il predicato conserva solo gli elementi la cui condizione è vera
Array = [Array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != %@", string]];

 

Controllare che un NSArray contenga un dato oggetto

Esiste un metodo molto veloce per controllare che un NSArray contenga un dato oggetto senza dover sfogliare a mano tutti gli elementi.

Si tratta del metodo indexOfObject: che controlla in automatico tutti gli elementi e restituisce un intero se l’elemento viene trovato, mentre restituisce NSNotFound se non viene trovato. Ecco un esempio:

1
2
3
4
5
if ([myArray indexOfObject:myObject == NSNotFound) {
 
//fai qualcosa
 
}
if ([myArray indexOfObject:myObject == NSNotFound) {

//fai qualcosa

}

Mostrare una notifica push ad app aperta

Il centro notifiche reagisce all’invio di una notifica push solo quando l’app è inattiva. Ma come possiamo avvisare ugualmente l’utente che una notifica è stata ricevuta quando l’app è in esecuzione.

È sufficiente, nell’App Delegate, usare il metodo che viene scaturito quando l’app riceve una notifica remota e usare il dizionario userInfo allegato per mostrare il testo, ad esempio, su un UIAlertView, in questo modo:

1
2
3
4
5
6
7
8
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
    NSLog(@"userInfo: %@", userInfo);
 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Notifica" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
 
    [alert show];
 
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
    NSLog(@"userInfo: %@", userInfo);

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Notifica" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];

    [alert show];

}

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.

Il momento giusto per modificare proprietà e outlet

Quando viene caricata una vista si possono sfruttare i vari metodi viewWill- viewDid- in combinazione con Load, Appear, Unload e Disappear. Se però dobbiamo impostare qualche proprietà della vista o qualche proprietà di outlet dal metodo che carica la vista, ci sono alcune considerazioni da fare per evitare comportamenti anomali.

Se dobbiamo modificare direttamente un outlet (ovvero il collegamento ad un oggetto dell’interfaccia grafica) dobbiamo necessariamente farlo dopo aver caricato la view che contiene l’outlet.

Se invece dobbiamo modificare una proprietà (o una “vecchia” variabile d’istanza) possiamo (e dovremmo) farlo prima del caricamento della view. Infatti se impostassimo una proprietà della view dopo il caricamento della view stessa dovremmo iniziare a usarla solo nel metodo viewWillAppear, cosa molto scomoda quando questa variabile d’istanza influenza in qualche modo il comportamento dell’interfaccia grafica.

Viceversa, non possiamo impostare il contenuto di un oggetto della interfaccia grafica collegato ad un outlet se non dopo che questo è stato caricato insieme alla view.

Coordinare metodo che carica e preimposta una view e metodi della view è quindi importante per evitare comportamenti anomali o antiestetici (come un’interfaccia grafica che si popola solo dopo essere apparsa).

URL leggibili per le app

Apple permette l’uso di URL molto leggibili per il collegamento alla pagina iTunes della propria app, o alla pagina relativa allo sviluppatore. In questo modo si può reindirzzare l’utente, su queste pagine, direttamente dall’app. la struttura dei link è la seguente:

  • Nome Compagnia o Sviluppatore
    http://itunes.com/apps/<companyname>
    per esempio http://itunes.com/apps/davidetroise
  • Nome Applicazione
    http://itunes.com/apps/<applicationname>
    per esempio http://itunes.com/apps/familyfinance
  • Applicatione e nome Compagnia (o Sviluppatore)
    http://itunes.com/apps/<companyname>/<applicationname>
    per esempio http://itunes.com/apps/davidetroise/familyfinance

Secondo Nathan S. si possono usare i prefissi itms:// o itms-apps:// al posto di http:// per evitare il redirect passando da Safari.

Modificare l’icona e il titolo di un elemento di TabBar

Nel caso servisse impostare o modificare via codice il titolo e l’immagine di un elemento di una TabBar, sarà sufficiente sostituire al tabBarItem del ViewController attuale con un tabBarItem allocato e inizializzato sul momento.

Ecco come:

1
2
3
4
yourViewController.tabBarItem = [[UITabBarItem alloc]
initWithTitle:NSLocalizedString(@"Name", @"Name")
image:[UIImage imageNamed:@"tab_ yourViewController.png"]
tag:3];
yourViewController.tabBarItem = [[UITabBarItem alloc]
initWithTitle:NSLocalizedString(@"Name", @"Name")
image:[UIImage imageNamed:@"tab_ yourViewController.png"]
tag:3];

L’esempio è tratto da una risposta su stackoverflow.

Se all’apertura di questo ViewController dovessimo settare il titolo anche di tutti gli altri allora bisogna usare la property viewControllers del tabBarController dell’AppDelegate: l’unico che conosce tutta la struttura dell’app.

Prelevato dall’array viewControllers l’elemento voluto, sarà sufficiente chiamare settile per impostare il nuovo titolo dell’elemento della TabBar.