Hello, iOS - Approfondimento

La procedura dettagliata Guida introduttiva ha presentato la compilazione e l'esecuzione di un'applicazione Xamarin.iOS di base. È ora il momento di acquisire una conoscenza più approfondita del funzionamento delle applicazioni iOS, per poter creare programmi più complessi. Questa guida esamina i passaggi illustrati nella procedura dettagliata Hello, iOS per consentire la comprensione dei concetti fondamentali dello sviluppo di applicazioni iOS.

Questa guida consente di sviluppare le competenze e le conoscenze necessarie per creare un'applicazione iOS a schermata singola. Al termine di questa guida, si sarà in grado di comprendere le diverse parti di un'applicazione Xamarin.iOS e il modo in cui si integrano tra loro.

Introduzione a Visual Studio per Mac

Visual Studio per Mac è un IDE open source gratuito che combina funzionalità di Visual Studio e Xcode. Include una finestra di progettazione visiva completamente integrata, un editor di testo completo di strumenti di refactoring, un browser di assembly, l'integrazione del codice sorgente e altro ancora. Questa guida presenta alcune funzionalità di base di Visual Studio per Mac, ma se non si ha familiarità con questo strumento, vedere la documentazione di Visual Studio per Mac.

Visual Studio per Mac segue la prassi di Visual Studio di organizzare il codice in soluzioni e progetti. Una soluzione è un contenitore per uno o più progetti. Un progetto può essere un'applicazione (ad esempio per iOS o Android), una libreria di supporto, un'applicazione di test e altro ancora. Nell'app Phoneword è stato aggiunto un nuovo progetto di iPhone tramite il modello App visualizzazione singola. La soluzione iniziale era simile a quanto segue:

A screenshot of the initial solution

Introduzione a Visual Studio

Visual Studio è un potente ambiente di sviluppo integrato di Microsoft. Include una finestra di progettazione visiva completamente integrata, un editor di testo completo di strumenti di refactoring, un browser di assembly, l'integrazione del codice sorgente e altro ancora. Questa guida introduce alcune funzionalità di Visual Studio di base con gli Strumenti Xamarin per Visual Studio.

Visual Studio consente di organizzare il codice in soluzioni e progetti. Una soluzione è un contenitore per uno o più progetti. Un progetto può essere un'applicazione (ad esempio per iOS o Android), una libreria di supporto, un'applicazione di test e altro ancora. Nell'app Phoneword è stato aggiunto un nuovo progetto di iPhone tramite il modello App visualizzazione singola. La soluzione iniziale era simile a quanto segue:

A screenshot of the initial solution

Anatomia di un'applicazione Xamarin.iOS

A sinistra è presente il Pad della soluzione, che contiene la struttura di directory e tutti i file associati alla soluzione:

The solution Pad, which contains the directory structure and all the files associated with the solution

A destra è presente il riquadro della soluzione, che contiene la struttura di directory e tutti i file associati alla soluzione:

The solution Pane, which contains the directory structure and all the files associated with the solution

Nella procedura dettagliata Hello, iOS è stata creata la soluzione Phoneword ed è stato inserito un progetto iOS, Phoneword_iOS, all'interno di questa. Gli elementi all'interno del progetto sono:

  • Riferimenti: contiene gli assembly necessari per compilare ed eseguire l'applicazione. Espandere la directory per visualizzare riferimenti ad assembly .NET quali System, System.Core e System.Xml, nonché un riferimento all'assembly Xamarin.iOS.
  • Pacchetti: la directory Pacchetti contiene pacchetti NuGet pronti all'uso.
  • Risorse: nella cartella Risorse sono archiviati altri file multimediali.
  • Main.cs: contiene il punto di ingresso principale dell'applicazione. Per avviare l'applicazione, è necessario passare il nome della classe principale dell'applicazione, AppDelegate.
  • AppDelegate.cs: questo file contiene la classe principale dell'applicazione ed è responsabile della creazione della finestra, della compilazione dell'interfaccia utente e dell'ascolto di eventi generati dal sistema operativo.
  • Main.storyboard: lo Storyboard contiene la progettazione visiva dell'interfaccia utente dell'applicazione. I file dello Storyboard vengono aperti in un editor grafico, iOS Designer.
  • ViewController.cs: il controller di visualizzazione aziona la schermata (visualizzazione) che viene visualizzata e toccata dall'utente. Il controller di visualizzazione è responsabile della gestione delle interazioni tra l'utente e la visualizzazione.
  • ViewController.designer.cs: designer.cs è un file generato automaticamente che funge da elemento di associazione tra i controlli nella visualizzazione e le relative rappresentazioni in codice nel controller di visualizzazione. Poiché si tratta di un file di meccanismi interni, l'IDE sovrascriverà tutte le modifiche manuali e nella maggior parte dei casi questo file può essere ignorato.
  • Info.plist: in Info.plist vengono impostate le proprietà dell'applicazione, ad esempio il nome, le icone, le immagini di avvio e così via. Si tratta di un file avanzato, per il quale è disponibile un'introduzione completa nella guida Working with Property Lists (Uso degli elenchi di proprietà).
  • Entitlements.plist: l'elenco delle proprietà di entitlement consente di specificare le funzionalità dell'applicazione (dette anche tecnologie dell'App Store), ad esempio iCloud, PassKit e così via. Altre informazioni sul file Entitlements.plist sono disponibili nella guida Working with Property Lists (Uso degli elenchi di proprietà). Per un'introduzione generale agli entitlement, vedere la guida Provisioning dei dispositivi.

Concetti fondamentali dell'architettura e delle app

Prima che un'applicazione iOS possa caricare un'interfaccia utente, è necessario eseguire due operazioni. In primo luogo, è necessario definire unpunto di ingresso dell'applicazione, ovvero il codice da eseguire per primo quando il processo dell'applicazione viene caricato in memoria. In secondo luogo, è necessario definire una classe che gestisca gli eventi a livello dell'intera applicazione e interagisca con il sistema operativo.

Questa sezione studia le relazioni illustrate nel diagramma seguente:

The Architecture and App Fundamentals relationships are illustrated in this diagram

Metodo Main

Il punto di ingresso principale di un'applicazione iOS è la classe Application. La classe Application è definita nel file Main.cs e contiene un metodo Main statico. Contiene una nuova istanza dell'applicazione Xamarin.iOS e passa il nome della classe delegata dell'applicazione che gestirà gli eventi del sistema operativo. Di seguito è riportato il codice del modello per il metodo statico Main:

using System;
using UIKit;

namespace Phoneword_iOS
{
    public class Application
    {
        static void Main (string[] args)
        {
            UIApplication.Main (args, null, "AppDelegate");
        }
    }
}

Classe delegata dell'applicazione

In iOS, la classe delegata dell'applicazione gestisce gli eventi di sistema. Questa classe si trova all'interno di AppDelegate.cs. La classe AppDelegate gestisce la finestra (Window) dell'applicazione. Questa finestra è una singola istanza della classe UIWindow che funge da contenitore per l'interfaccia utente. Per impostazione predefinita, un'applicazione ha una sola finestra in cui caricare il contenuto e tale finestra è associata a una schermata (una singola istanza di UIScreen) che fornisce il rettangolo delimitatore corrispondente alle dimensioni dello schermo fisico del dispositivo.

AppDelegate è anche responsabile della sottoscrizione agli aggiornamenti di sistema relativi a eventi importanti dell'applicazione, ad esempio il completamento dell'avvio o una riduzione eccessiva della memoria disponibile.

Di seguito è riportato il codice del modello di AppDelegate:

using System;
using Foundation;
using UIKit;

namespace Phoneword_iOS
{

    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        public override UIWindow Window {
            get;
            set;
        }

        ...
    }
}

Dopo che l'applicazione ha definito la finestra (Window), può iniziare a caricare l'interfaccia utente. Nella prossima sezione viene illustrata la creazione dell'interfaccia utente.

Interfaccia utente

L'interfaccia utente di un'app iOS è come una vetrina: l'applicazione ha in genere una sola vetrina (corrispondente alla finestra), ma può riempirla con tutti gli oggetti necessari. Gli oggetti e la loro disposizione possono essere modificati secondo le esigenze dell'applicazione. Gli oggetti di questo scenario, ovvero gli elementi visibili per l'utente, sono chiamati visualizzazioni. In un'applicazione con un'unica finestra, le visualizzazioni vengono disposte una sopra l'altra in una gerarchia di visualizzazione del contenuto gestita da un unico controller di visualizzazione. Le applicazioni con più schermate hanno più gerarchie di visualizzazione del contenuto, ognuna con un proprio controller di visualizzazione, e l'applicazione inserisce visualizzazioni nella finestra per creare gerarchie di visualizzazione del contenuto diverse in base alla schermata visualizzata dall'utente.

Per altre informazioni sulla creazione di un'interfaccia utente con storyboard, vedere la sezione Progettazione con storyboard di Xcode Overview (Panoramica di Xcode) nella libreria per sviluppatori iOS di Apple.

Il diagramma seguente illustra le relazioni tra la finestra, le visualizzazioni, le visualizzazioni secondarie e il controller di visualizzazione che visualizzano l'interfaccia utente sullo schermo del dispositivo:

The relationships between the Window, Views, Subviews, and view controller

La prossima sezione illustra come usare le visualizzazioni nel codice e come creare un programma per l'interazione utente usando i controller di visualizzazione e il ciclo di vita della visualizzazione.

Controller di visualizzazione e ciclo di vita della visualizzazione

A ogni gerarchia di visualizzazione del contenuto corrisponde un controller di visualizzazione che dà vita all'interazione utente. Il ruolo del controller di visualizzazione è di gestire le visualizzazioni presenti nella gerarchia di visualizzazione del contenuto. Il controller di visualizzazione non fa parte della gerarchia di visualizzazione del contenuto e non è un elemento dell'interfaccia ma fornisce il codice che dà vita alle interazioni dell'utente con gli oggetti sullo schermo.

Controller di visualizzazione e storyboard

All'interno di uno Storyboard il controller di visualizzazione è rappresentato sotto forma di una barra nella parte inferiore della scena. Quando si seleziona il controller di visualizzazione, vengono visualizzate le proprietà nel riquadro delle proprietà:

Selecting the view controller brings up its properties in the Properties Pane

È possibile impostare una classe controller di visualizzazione personalizzata per la gerarchia di visualizzazione del contenuto rappresentata da questa scena modificando la proprietà Classe nella sezione Identità del riquadro delle proprietà. L'applicazione Phoneword, ad esempio, imposta ViewController come controller di visualizzazione per la prima schermata, come illustrato nello screenshot riportato di seguito:

The Phoneword application sets the ViewController as the view controller

All'interno di uno Storyboard il controller di visualizzazione è rappresentato sotto forma di una barra nella parte inferiore della scena. Quando si seleziona il controller di visualizzazione, vengono visualizzate le proprietà nel riquadro Proprietà:

Selecting the view controller brings up its properties in the Properties Pane

È possibile impostare una classe controller di visualizzazione personalizzata per la gerarchia di visualizzazione del contenuto rappresentata da questa scena modificando la proprietà Classe nella sezione Identità del riquadro Proprietà. L'applicazione Phoneword, ad esempio, imposta ViewController come controller di visualizzazione per la prima schermata, come illustrato nello screenshot riportato di seguito:

The Phoneword application sets the ViewController as the view controller

Questa operazione collega la rappresentazione del controller di visualizzazione nello Storyboard alla classe C# ViewController. Aprire il file ViewController.cs. Si noti che ViewController è una sottoclasse di UIViewController, come illustrato nel codice seguente:

public partial class ViewController : UIViewController
{
    public ViewController (IntPtr handle) : base (handle)
    {

    }
}

ViewController ora consente il funzionamento delle interazioni della gerarchia di visualizzazione del contenuto associate a questo controller di visualizzazione nello Storyboard. Verrà quindi presentato il processo detto del ciclo di vita della visualizzazione, attraverso il quale si apprenderà il ruolo del controller di visualizzazione nella gestione delle visualizzazioni.

Nota

Per le schermate di sola visualizzazione che non richiedono alcuna interazione con l'utente, la proprietà Classe nel riquadro delle proprietà può essere lasciata vuota. In questo modo la classe sottostante del controller di visualizzazione viene impostata come implementazione predefinita di UIViewController. Ciò è corretto se non si prevede di aggiungere codice personalizzato.

Ciclo di vita della visualizzazione

Il controller di visualizzazione ha il compito di caricare e scaricare le gerarchie di visualizzazione del contenuto dalla finestra. Quando un'azione importante interessa una visualizzazione all'interno della gerarchia di visualizzazione del contenuto, il sistema operativo informa il controller di visualizzazione tramite eventi del ciclo di vita della visualizzazione. Eseguendo l'override dei metodi nel ciclo di vita della visualizzazione è possibile interagire con gli oggetti sullo schermo e creare un'interfaccia utente dinamica e reattiva.

Ecco i metodi di base del ciclo di vita e le funzioni corrispondenti:

  • ViewDidLoad: viene chiamato una volta la prima volta che il controller di visualizzazione carica la propria gerarchia di visualizzazione del contenuto in memoria. Questo è un ottimo momento per eseguire la configurazione iniziale, perché è il momento in cui le visualizzazioni secondarie diventano disponibili nel codice.
  • ViewWillAppear: viene chiamato ogni volta che una visualizzazione del controller di visualizzazione sta per essere aggiunta a una gerarchia di visualizzazione del contenuto e compare sullo schermo.
  • ViewWillDisappear: viene chiamato ogni volta che una visualizzazione del controller di visualizzazione sta per essere rimossa da una gerarchia di visualizzazione del contenuto e scompare dallo schermo. Questo evento del ciclo di vita viene usato per la pulizia e il salvataggio dello stato.
  • ViewDidAppear e ViewDidDisappear: vengono chiamati quando una visualizzazione viene rispettivamente aggiunta o rimossa dalla gerarchia di visualizzazione del contenuto.

Quando si aggiunge codice personalizzato a una qualsiasi fase del ciclo di vita, è necessario eseguire l'override dell'implementazione di base del metodo corrispondente del ciclo di vita. A questo scopo, toccare il metodo del ciclo di vita esistente, a cui è già associato del codice, e ampliare quest'ultimo con codice aggiuntivo. L'implementazione di base viene chiamata dall'interno del metodo per assicurarsi che il codice originale venga eseguito prima del nuovo codice. Un esempio di queste operazioni è illustrato nella prossima sezione.

Per altre informazioni sull'uso dei controller di visualizzazione, vedere View Controller Programming Guide for iOS (Guida alla programmazione del controller di visualizzazione) e UIViewController reference (Informazioni di riferimento su UIViewController) nel sito Web Apple.

Risposta all'interazione dell'utente

Il ruolo più importante del controller di visualizzazione è rispondere all'interazione dell'utente, ad esempio alla pressione di pulsanti, allo spostamento e così via. Il modo più semplice per gestire l'interazione dell'utente è di associare un controllo per l'ascolto dell'input dell'utente e di collegare un gestore dell'evento per rispondere all'input. È ad esempio possibile associare un pulsante per rispondere a un evento di tocco, come illustrato nell'app Phoneword.

Vediamo come funziona il codice. Nel progetto Phoneword_iOS, è stato aggiunto il pulsante TranslateButton alla gerarchia di visualizzazione del contenuto:

A button was added called TranslateButton to the Content View Hierarchy

Quando viene creato un punto di uscita di riferimento tramite Xcode Interface Builder, Xcode Sync esegue automaticamente il mapping a un controllo nella ViewController.designer.cs, rendendo disponibile all'interno TranslateButton della ViewController classe . I controlli diventano disponibili a partire dalla fase ViewDidLoad del ciclo di vita della visualizzazione. Per rispondere al tocco dell'utente viene quindi usato questo metodo del ciclo di vita:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // wire up TranslateButton here
}

Per l'ascolto del tocco dell'utente, l'app Phoneword usa un evento di tocco denominato TouchUpInside. TouchUpInside è in ascolto di eventi di tocco (sollevamento del dito dallo schermo) che seguono un contatto (contatto del dito con lo schermo) all'interno dei limiti del controllo. L'evento contrario a TouchUpInside è l'evento TouchDown, generato quando l'utente preme un controllo. L'evento TouchDown acquisisce molto rumore e non offre all'utente la possibilità di annullare il tocco trascinando il dito fuori dal controllo. TouchUpInside rappresenta il modo più comune per rispondere al tocco di un elemento Pulsante e crea l'esperienza che l'utente si aspetta quando preme un pulsante. Altre informazioni su questo argomenti sono disponibili in iOS Human Interface Guidelines (Linee guida per l'interfaccia umana iOS) nel sito Web Apple.

L'app ha gestito l'evento TouchUpInside con un'espressione lambda, ma avrebbe potuto usare anche un delegato o un gestore dell'evento denominato. Il codice finale del pulsante è simile al seguente:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    string translatedNumber = "";

    TranslateButton.TouchUpInside += (object sender, EventArgs e) => {
      translatedNumber = Core.PhonewordTranslator.ToNumber(PhoneNumberText.Text);
      PhoneNumberText.ResignFirstResponder ();

      if (translatedNumber == "") {
        CallButton.SetTitle ("Call", UIControlState.Normal);
        CallButton.Enabled = false;
      } else {
        CallButton.SetTitle ("Call " + translatedNumber, UIControlState.Normal);
        CallButton.Enabled = true;
      }
  };
}

Altri concetti introdotti in Phoneword

L'applicazione Phoneword ha introdotto alcuni concetti non trattati in questa guida. Essi includono:

  • Modifica del testo del pulsante: l'app Phoneword ha illustrato come modificare il testo di un Pulsante chiamando SetTitle per il Pulsante stesso e passando il nuovo testo e lo stato del controllodel Pulsante. Il codice seguente, ad esempio, modifica il testo dell'elemento CallButton in "Call" (Chiama):

    CallButton.SetTitle ("Call", UIControlState.Normal);
    
  • Abilitazione e disabilitazione dei pulsanti: lo stato degli elementi Pulsante può essere Enabled o Disabled. Un Pulsante disabilitato non risponde all'input dell'utente. Ad esempio, il codice seguente disabilita CallButton:

    CallButton.Enabled = false;
    

    Per altre informazioni sui pulsanti, vedere la guida relativa ai pulsanti.

  • Chiusura della tastiera: quando l'utente tocca il campo di testo, iOS visualizza la tastiera per consentire all'utente di immettere input. Non esiste una funzionalità incorporata che consenta di chiudere la tastiera. Il codice seguente viene aggiunto a TranslateButton per nascondere la tastiera quando l'utente preme TranslateButton:

    PhoneNumberText.ResignFirstResponder ();
    

    Per un altro esempio di rimozione della tastiera, fare riferimento alla sezione Dismiss the Keyboard (Nascondere la tastiera).

  • Chiamata telefonica con URL: nell'app Phoneword per avviare l'app telefono di sistema viene usato uno schema URL Apple. Lo schema URL personalizzato è costituito dal prefisso "tel:" e dal numero di telefono convertito, come illustrato nel codice seguente:

    var url = new NSUrl ("tel:" + translatedNumber);
    if (!UIApplication.SharedApplication.OpenUrl (url))
    {
        // show alert Controller
    }
    
  • Visualizzazione di un avviso: quando un utente tenta di effettuare una chiamata telefonica in un dispositivo che non supporta tali chiamate, ad esempio il simulatore o un iPod Touch, viene visualizzata una finestra di dialogo di avviso che informa l'utente che la chiamata non può essere effettuata. Il codice seguente crea e popola un controller di avvisi:

    if (!UIApplication.SharedApplication.OpenUrl (url)) {
                    var alert = UIAlertController.Create ("Not supported", "Scheme 'tel:' is not supported on this device", UIAlertControllerStyle.Alert);
                    alert.AddAction (UIAlertAction.Create ("Ok", UIAlertActionStyle.Default, null));
                    PresentViewController (alert, true, null);
                }
    

    Per altre informazioni sulla visualizzazione di avvisi in iOS, vedere Alert Controller recipe (Recipe controller di avvisi).

Test, distribuzione e finalizzazione

Visual Studio per Mac e Visual Studio offrono entrambi numerose opzioni per il test e la distribuzione di un'applicazione. Questa sezione descrive le opzioni di debug, illustra le funzionalità di test di applicazioni in un dispositivo e presenta alcuni strumenti per la creazione di icone e immagini di avvio dell'app personalizzate.

Strumenti di debug

I problemi del codice di un'applicazione sono talvolta difficili da diagnosticare. Per facilitare la diagnosi di problemi complessi del codice, è possibile impostare un punto di interruzione, eseguire il codice un'istruzione alla volta o visualizzare le informazioni di output nella finestra del log.

Eseguire la distribuzione in un dispositivo

Il simulatore iOS consente di testare le applicazioni in modo rapido. Il simulatore è dotato di numerose ottimizzazioni utili per l'esecuzione di test, ad esempio un percorso fittizio, la simulazione di movimento e così via. Gli utenti, tuttavia, non utilizzeranno l'app finale in un simulatore. È necessario testare tutte le applicazioni con dispositivi reali in modo tempestivo e frequente.

Il provisioning di un dispositivo richiede tempo e un account sviluppatore Apple. La guida Provisioning dei dispositivi offre istruzioni esaurienti per la predisposizione di un dispositivo per lo sviluppo.

Nota

Al momento, a causa di un requisito Apple, per compilare codice per un dispositivo fisico o per il simulatore, è necessario un certificato di sviluppo o un'identità di firma. Per soddisfare questo requisito, seguire i passaggi nella guida Provisioning dei dispositivi.

Dopo il provisioning del dispositivo, per usare il dispositivo stesso come destinazione della distribuzione è necessario collegarlo, modificare la destinazione sulla barra degli strumenti di compilazione per il dispositivo iOS e premere Avvia ( Riproduci) come illustrato nello screenshot seguente:

Pressing Start/Play

Pressing Start/Play

L'app verrà distribuita nel dispositivo iOS:

The app will deploy to the iOS device and run

Generare icone e immagini di avvio personalizzate

Non tutti hanno una finestra di progettazione disponibile per creare le icone personalizzate e avviare immagini che un'app deve distinguersi. Ecco diversi approcci alternativi alla generazione di immagini personalizzate dell'app:

  • Pixelmator: versatile app di modifica delle immagini per Mac a un costo di circa 30 dollari.
  • Fiverr: consente di scegliere all'interno di un ampio pool un designer che crei il set di icone dell'applicazione, a partire da 5 dollari. I risultati possono essere imprevedibili, ma si tratta di una risorsa valida nel caso in cui sia necessario un set di icone in tempi brevi
  • Visual Studio: è possibile usare questo strumento per creare un set di icone semplici per l'app direttamente nell'IDE.
  • Fiverr: consente di scegliere all'interno di un ampio pool un designer che crei il set di icone dell'applicazione, a partire da 5 dollari. I risultati possono essere imprevedibili, ma si tratta di una risorsa valida nel caso in cui sia necessario un set di icone in tempi brevi

Per altre informazioni sulle dimensioni e sui requisiti delle icone, vedere la guida Uso delle immagini.

Riepilogo

Complimenti. A questo punto si ha una solida conoscenza dei componenti delle applicazioni Xamarin.iOS e degli strumenti necessari per creare tali applicazioni. Nella prossima esercitazione della serie introduttiva, l'applicazione verrà estesa in modo da gestire più schermate. Nello stesso tempo, verrà implementato un controller di spostamento, verranno illustrati gli Storyboard Segue e verrà presentato lo schema MVC (Model, View, Controller).