[iOs] Distribuzione “ad hoc” di una app senza sincronizzazione con iTunes, direttamente da device

TestFlightApp LogoVi scrivo qui la procedura che sto seguendo per permettere ad un altro utente di installare la vostra app, senza ogni volta mandargli l’IPA (e relativo certificato di “Ad Hoc Distribution Provisioning”), e senza fargliela sincronizzare con iTunes.

La procedura permette di:

  • inviare una notifica all’utente di rilascio di una nuova versione beta, con relativa descrizione delle funzionalità o correzioni che avete fatto
  • far installare l’app direttamente da device, senza farglielo attaccare via usb al pc e sincronizzare l’IPA e certificato con iTunes
  • ricevere feedback e visualizzare quale è l’effettiva release installata dall’utente sul proprio device, grazie ad una interfaccia web di monitoraggio e di attività

Il servizio si chiama TestFlight ed è disponibile a questo indirizzo: https://testflightapp.com

Appunto, la procedura descritta è quella dell’ installazione “al volo” delle versioni beta delle app (ad hoc distribution over the air) e l’ho trovata molto molto comoda. Basta registrare un account, assolutamente free, e inserire poi le seguenti informazioni da una dashboard:

  • team di progetto: indirizzi email e relativi UUID dei device dei membri del vostro team (siano essi clienti o colleghi di lavoro)
  • certificati di Provisioning: per poter installare una IPA su un device, come sapete, occorre un certificato di ” Provisioning Ad Hoc Distribution”, come descritto anche in un precedente articolo di questo blog: [iOs] Archiviazione e distribuzione di un “ad hoc build” o IPA file con XCode 4

Il certificato di distribuzione “ad hoc” si aggiorna sempre sull’account di Apple Developer, ma lo si inserisce direttamente in TestFlight. Ogni volta, dunque, non dovete inviarlo di nuovo agli utenti, ma verrà aggiornato in automatico da TestFlight stesso quando viene installata la release dell’app inviata.

Per ciascuna release, TestFlight vi permette di inviare una notifica solo ad alcuni utenti a cui dare il permesso di installarla, dandovi informazioni su quando, se e da chi è stata installata.

Nulla di più semplice :)

TestFlightApp

[iOs] Il Logging nelle nostre app con le Preprocessor Macros

Prima di un rilasciare una app iOS su Apple Store, è buona prassi fare un pò di pulizia dei log sparsi nel codice. Molti sviluppatori, infatti, sono restii all’utilizzo del debug e preferiscono utilizzare, man mano che sviluppano, la classe NSLog e farsi stampare gli output sulla console. Dunque, i nostri progetti rimangono pieni di NSLog che, tuttavia, è meglio non rilasciare sulle app in esercizio. Il motivo è dovuto al fatto che la scrittura dei log è onerosa e potrebbe ridurre le performance della nostra app. Inoltre, anche se la console del device è nascosta all’utente, potremmo dimenticare di loggare informazioni sensibili … e ciò è “no buono”.

Ho letto un pò di articoli a riguardo, tra cui i seguenti:

Ecco la procedura che ho seguito, utilizzando le Preprocessor Macros. L’idea è quella di inserire un flag (-DDEBUG) nella configurazione di DEBUG del nostro progetto e importare nelle nostre classi un log “custom” (DLog oppure ALog).

  • Per prima cosa, inserite un file Log.h nel vostro progetto con il seguente contenuto:
#ifdef DDEBUG

#   define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

#else

#   define DLog(...)

#endif

// ALog always displays output regardless of the DEBUG setting

#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
  •  Poi spostatevi nella configurazione del vostro progetto (click sulla root di progetto, selezionate Targets e poi spostatevi nella scheda Builds Settings). Qui, cercate la voce “Other C Flags” e inserite il flag -DDEBUG in corrispondenza della configurazione di DEBUG.

  • NOTA. Il punto precedente non è necessario se in Log.h si va a controllare il valore del flag nativo DEBUG (che è true se siamo in ambiente di debug, false quando si è in modalità Release/Ad Hoc), anzichè DDEBUG (che è una nostra variabile “custom”)
    #ifdef DEBUG
  • Importate l’interfaccia Log.h nel file di progetto <YourApp>_Prefix.pch, in modo da rendere visibile la macro in tutte le classi (senza importare esplicitamente la macro ogni volta). Nel mio caso, ecco il contenuto del .pch:
#import <Availability.h>
#import "Log.h"

#ifndef __IPHONE_5_0
#endif

#ifdef __OBJC__
	#import <UIKit/UIKit.h>
	#import <Foundation/Foundation.h>
#endif
  • Infine, potete utilizzare i log “custom” normalmente come fareste con NSLog, come segue:
 DLog(@"Logging %d con %@",1, @"DLog");
 ALog(@"Logging %d con %@",2, @"ALog");

Eccovi l’output di esempio delle precedenti righe di log:

2012-12-25 15:03:16.276 MyApp [4451:907] -[AppDelegate application:didFinishLaunchingWithOptions:] [Line 33] Logging 1 con DLog
2012-12-25 15:03:16.281 MyApp [4451:907] -[AppDelegate application:didFinishLaunchingWithOptions:] [Line 34] Logging 2 con ALog

DLog e ALog, per come sono stati configurati nel Log.h, stampano anche il nome della classe, il metodo e la riga di codice in cui si trovano. ALog stampa anche se non siamo in DEBUG (quindi, come NSLog, loggherebbe anche quando abbiamo rilasciato l’app su Apple Store o con una distribuzione “ad hoc”).

Quindi, lanciando la vostra app in DEBUG (sia sul Simulatore che sul device) vi troverete i log stampati sulla console. In Release (sia su App Store che su una distribuzione “ad hoc” dell’IPA) non verrà loggato nulla sul device dell’utente, se avete utilizzato DLog (e non ALog oppure NSLog).

[iOS] Apps that are not very useful – Guidelines reject (2.12 – App Store Review)

Il più frustrante punto di violazione delle Apple Store Review Guidelines (tradotte anche su questo blog al Luglio 2012) è il seguente:

2.12. Apps that are not very useful, unique, are simply web sites bundled as Apps, or do not provide any lasting entertainment value may be rejected

Solitamente la motivazione che viene riportata, dal team di review di Apple nella mail di risposta, è la seguente:

2.12

We found that your app only provides a very limited set of features. While we value simplicity, we consider simplicity to be uncomplicated – not limited in features and functionality

We understand that there are no hard and fast rules to define useful or entertaining, but Apple and Apple customers expect apps to provide a really great user experience. Apps should provide valuable utility or entertainment, draw people in by offering compelling capabilities or content, or enable people to do something they couldn’t do before or in a way they couldn’t do it before.

We encourage you to review your app concept and evaluate whether you can incorporate additional content and features to be in compliance with the Guidelines. For information on the basics of creating great apps, watch the video The Ingredients of Great Apps. If you feel we didn’t understand the features of your app, or that we missed key functionality, and your app was incorrectly rejected, you may appeal to the  App Review Board.

 

Definire questo punto “frustrante” è dir poco, visto che non è una “bocciatura” a cui si può mettere una “pezza” (tecnicamente parlando). Apple ci fa semplicemente capire che la nostra app non serve a nulla o è troppo semplice, dove la linea di “confine” per definire il concetto di semplicità – spiega Apple – non è definibile con regole rigide.

Come si risolve?

Potrei scrivere qui dei suggerimenti, ma dipende dalla vostra app e dall’utilità che offre, visto che ad Apple “sta a cuore” che sia utile e trasmetta agli utenti una “grandiosa esperienza”. La vostra app deve dimostrare che ci sia un lavoro “complesso” dietro: in poche parole, una app con poche funzionalità e con una grafica poco curata, ha bassa probabilità di superare la review.

Arricchitela con maggiori funzionalità: magari una galleria fotografica e video (vedi Three20), più tabelle con contenuti magari scaricati da un server (vedi chiamate asincrone su iOS). Per la parte grafica, rispettate le risoluzioni delle immagini per ciascun device (vedi Custom Icon & Image Creation Guidelines) e le iOS Human Interface Guidelines.

Ecco altro materiale, suggerito da Apple, e che vi consiglio di vedere:

 

Creative Commons License
This work by Francesco Ficetola is licensed under a Creative Commons Attribution 4.0 International License.
Based on a work at www.francescoficetola.it.
Permissions beyond the scope of this license may be available at http://www.francescoficetola.it/2012/12/03/apple-review/.

[iOs] Archiviazione e distribuzione di un “ad hoc build” o IPA file con XCode 4

Se volessimo distribuire la nostra app senza rilasciarla su Apple Store, magari per farla testare ad altri utenti, occorre seguire i seguenti passi.
Teoricamente, occorrerebbe creare un pacchetto “ad-hoc” (ad hoc build) firmandolo con un “ad hoc distribution provisioning profile” (certificato per la distribuzione creato su iOs Dev Center). Cioè dovremmo condividere oltre che il file .app anche un file .mobileprovision (con il certificato).
L’utente dovrà importare il file .mobileprovision nella barra sinistra di iTunes, insieme al file .app.
Il modo migliore è distribuire un file IPA contrassegnato con un “ad hoc distribution profile“, così che l’utente dovrà fare soltanto un doppio click sull’IPA file e installarlo in iTunes.

Operazione preliminare – Build & Archive
Per creare un file IPA, occorre usare direttamente XCode e rilasciare un Archivio (scheda Product e poi Archive). Verrà creato un archivio nell’Organizer, dove si dovrà scegliere il provisioning profile per firmarlo.
E’ buona norma utilizzare un “ad hoc distribution provisioning profile“, oppure è possibile usare un distribution profile con un nome generico (o con wildcard).

IMPORTANTE. Occorre generare un certificato “Ad Hoc Distribution” sulla propria pagina personale di DEV APPLE, associando il certificato ai dispositivi su cui poi si dovrà installare l’app (per la distribuzione al cliente, per esempio, prima della pubblicazione definitiva su Apple Store). Il dispositivo su cui installare l’app si associa inserendo nella pagina di DEV APPLE il codice UDID di 40 cifre alfanumeriche (vi riporto alla fine del presente articolo un riferimento che spiega come recuperarlo). Dopo averlo inserito, occorre generare un certificato di distribuzione “Ad Hoc” associandolo al dispositivo (sempre in DEV APPLE), scaricarlo e importarlo in Organizer di XCode (basta fare il doppio click sul file .mobileprovisioning). Una volta importato, occorre associare il certificato alla configurazione di XCode, come spiegato di seguito).

Creazione di una nuova configurazione in Project Settings
Si crea una configurazione (la possiamo chiamare Ad Hoc Distribution). Cliccare sul nome del progetto (pannello a sinistra) e nel pannello Groups & Files selezionare prima il progetto e poi il target.

Si duplica la voce Release e si crea una nuova configurazione a cui dare un nome (Ad Hoc Distribution, per esempio).

Setup del target
Nella scheda del Target, assicurarsi che sotto il tab Build Settings, selezionando ALL e COMBINED, in corrispondenza della voce Code Signing vi sia il corretto certificato per la distribuzione (nel nostro caso, “Ad Hoc Distribution”).

Skip install
Se nel progetto ci sono librerie statiche (tipo Cocos2d oppure Three20), occorre eseguire uno step extra che assicuri che esse vengano incluse nell’app binaria correttamente. Basta selezionare le singole librerie e nel pannello a destra, per ognuna di esse, occorre trovare la voce Skip Install (in Build Settings, gruppo Deployment – utilizzate la funzione di ricerca per velocizzare) e inserire il valore YES per la configurazione creata al passo precedente (“Ad Hoc Distribution“, nel nostro caso) .

NOTA. Lo step “Skip Install” è necessario solo se il progetto contiene le static libraries e deve essere eseguito SOLO per le static library e NON per il Target o il progetto della propria app.

Configurazione per l’Archive Scheme
Nel menù Product, vi è la voce Edit Scheme. Selezionare Archive dal pannello sinistro e poi settare Build Configuration con la propria configurazione (“Ad Hoc Distribution“, nel nostro caso), salvando.

Creazione dell’archivio
E’ possibile ora creare l’Archivio. Nel top menu, sotto la voce Product vi è l’opzione Archive. Quando l’operazione è terminata correttamente, sotto l’Organizer vi è il tab Archives con il nostro pacchetto.

Creazione del file IPA
Selezionato l’archivio appena creato, si può creare il file IPA, cliccando su Share e poi confermando il provisioning profile utilizzato. Andando avanti, scegliendo in corrispondenza di Contents la voce “iOS App Store Package .ipa“, si crea l’IPA file con un nome e lo si salva.

Adesso siamo pronti per distribuire il pacchetto IPA. L’utente che lo riceverà, dovrà semplicemente fare un doppio click e sincronizzare il proprio device con iTunes, per trovarsi l’app così installata.

Riferimenti:

[iOs] Distribuzione su Apple Store: errore “No architectures to compile for armv6”

Chi ha avuto esperienza di programmazione su XCode 3 e ha iniziato a sviluppare un progetto lì e poi ad importarlo su XCode 4, sicuramente è incappato nell’errore “No architectures to compile for (ARCHS=i386, VALID_ARCHS=armv6 armv7)“.

Questo errore non avviene a tempo di compilazione, ma all’atto della distribuzione su Apple Store.

Ho letto che capita anche sviluppando direttamente su XCode 4 e si verifica quando si crea un progetto che di default viene testato su una architettura armv7, che per intenderci è il processore che gira dagli iPhone 3GS a salire.

L’iPhone 3G monta un processore armv6, quindi, affinchè si possa deployare sui modelli da 3G a 4S, occorre settare la predisposizione a questa architettura sul compilatore. A partire dal firmware 4.3 apple ha tolto il supporto ai dispositivi basati su armv6 (iPod Touch/IPhone 1G, 2G, 3G), per cui se vi occorre rendere compatibile e scaricabile la vostra app anche su di essi, vi occorre compilarla su firmware 4.2 al massimo e dichiarare esplicitamente la compatibilità con l’architettura armv6.

Per prima cosa, occorre andare sulle proprietà del vostro progetto e settare una architettura valida (voce Valid Architecture):

  1. Navigare sul tab Build Settings e trovare le voci sotto il gruppo Architectures
  2. Per le voci presenti sotto tale gruppo settare i seguenti valori: Architectures: Standard (armv6 armv7); Base SDK: Latest iOS (iOS 4.3), Build Active Architecture Only: No, Supported Platforms: iphonesimulator, iphoneos e Valid Architectures: armv6 armv7 i386;
  3. Se nella voce Valid Architectures vi sono già i valori armv6 armv7, cancellarle, restartare XCode e reinserirle. Se vi è il valore $(ARCHS_STANDARD_32_BIT), vi consiglio di cancellarlo e inserire le due voci armv6 e armv7;
  4. Sempre in Valid Architectures, il valore i386 non è obbligatorio, ma permette di definire correttamente l’architettura utilizzata dal Simulatore che gira su un MacIntel.

Vi consiglio di fare anche il seguente passo, perchè mi è capitato che dopo essere riuscito ad uploadare la mia app su Apple Store, nonostante non mi abbia più dato l’errore “No architectures to compile for (ARCHS=i386, VALID_ARCHS=armv6 armv7)“, mi segnalava l’app compatibile anche per iPhone 3G, ma quando la si provava a scaricare ed installare, non succedeva nulla (ovvero nè la scaricava nè la installava sul device).

5. Nel vostro progetto vi è sicuramente un file che si chiama yourProjectName-Info.plist, che contiene tutte le info di configurazione della vostra app. Occorre che cancellate tutte i valori presenti sotto la voce Required device capabilities (se c’è).

enter image description here

Vi allego gli screenshot dei passi descritti e i due post che mi sono serviti per risolvere questo bel problema di compatibilità sui dispositivi con armv6: