"Mausprogrammierung" in Swift Teil 2 - Navigation

  • Tutorial
Hallo nochmal, Chabarowsk! Ich

entwickle das Thema des vorherigen Artikels und schreibe über das Programmieren der Navigation zwischen den Fenstern Ihrer Anwendung mit einem Minimum an Code. Ich möchte gleich erwähnen, dass der Artikel für Anfänger geschrieben wurde. Wenn Sie ein erfahrener Entwickler in dieser Angelegenheit sind, ist es unwahrscheinlich, dass er Ihnen etwas bringt.



Also fangen wir an.

Vorbereitung


Erstellen Sie ein Projekt, bevor Sie mit dem Schreiben der Anwendung selbst beginnen

Weil Die meisten von ihnen sind bereits dazu in der Lage. Lassen Sie uns hier ein einfaches Video machen:


Starterfüllung


Großartig, das Projekt ist fertig.
Wir möchten mehrere VCs mit einer Auswahl über die Registerkartenleiste erstellen, also legen wir die Farbe des Hauptfensters fest, wickeln es in einen TabViewController ein und fügen dort ein paar weitere VC (= ViewController) hinzu.

Drücken Sie unseren ViewController zur Vereinfachung der Anzeige in der Größe zusammen und „malen“ Sie ihn rot



"Wrap" die Hauptseite im Tab Bar Controller

Dazu wählen wir unsere Hauptseite aus, wählen Sie Editor -> Einbetten -> Tab Bar Controller aus dem Menü


Ok, jetzt haben wir bereits ein "Menü", aber bisher macht es keinen Sinn - es gibt nur eine Seite. Nun, fügen Sie noch ein paar hinzu:

Fügen Sie 2 weitere ViewController hinzu

Wie im vorherigen Artikel ziehen wir sie auf unser Storyboard und „drücken“ sie gleichzeitig zusammen, um eine bessere Wahrnehmung zu erzielen. Und stellen Sie die Farben ein - zum Beispiel Gelb und Grün.


Fügen Sie sie nun unserem Menü hinzu

Halten Sie dazu die rechte Maustaste auf dem Tab Bar Controller gedrückt, ziehen Sie die Maus auf das, was Sie dem Menü hinzufügen möchten, und wählen Sie in der angezeigten Liste Relationship Segue -> View Controller


Letzter Schritt

Schauen Sie sich jetzt Ihren TabView Controller an - es wird so etwas wie [Item] [Item] [Item] geben. Es ist irgendwie nicht freundlich, also ändern wir die Namen unserer VCs im Menü. Wählen Sie dazu die Schaltfläche [Element] am unteren Rand der VC, die sie im Menü darstellt, und stellen Sie die Werte ein, die wir dort benötigen. Zum Beispiel ändere ich nur den Namen, aber hier können Sie experimentieren.


Navigationstests

Wir haben also bereits ein vollwertiges Menü erstellt, ohne eine einzige Codezeile zu schreiben . Zur Überprüfung werden wir unsere Anwendung auf dem fünften iPhone-Simulator starten, nachdem wir zuvor Labels mit einer Beschreibung der aktuellen Seite zur besseren Übersicht geworfen haben:


Wie Sie sehen können, erfordert das Erstellen eines einfachen Menüs fast keinen Aufwand. Es gibt nur noch einen wichtigen Punkt: die Reihenfolge der Elemente in unserem Menü. Wenn Sie die Menüelemente austauschen möchten, geschieht dies ebenfalls mit minimalem Aufwand. Ziehen Sie sie einfach per Drag & Drop, indem Sie die linke Maustaste in der Menüleiste des Registerkartenleisten-Controllers drücken:


Im Prinzip wird diese Option für viele Anwendungen ausreichen, aber was ist, wenn wir eines der Elemente im Navigationscontroller "einschließen" möchten?

Verschachtelte Menüs



Weil Navigationscontroller und Tabellenansicht werden fast immer zusammen verwendet. Ziehen Sie eine solche Option in Betracht. In diesem Fall müssen Sie in jedem Fall Code schreiben, wenn zumindest die geringste Wahrscheinlichkeit besteht, dass diese Beschriftungen nicht konstant sind.

Aber seitdem Faulheit ist der Motor des Fortschritts. Wir verwenden die bereits für uns erstellte TableVC in unseren VC "Details" mithilfe der Containeransicht. Es wird etwas schlechter aussehen (ein Haufen eingebauter Controller), aber Sie können weniger Code schreiben.

Einbetten eines Controllers in einen anderen Controller

Zunächst müssen wir einen Controller erstellen, der unsere Platte verarbeitet. Dies ist eine reguläre TableVC, daher wird nur Video angezeigt:

Als nächstes werden wir unseren Tabellencontroller mithilfe der Containeransicht in den „gelben“ Controller einbetten. Wenn Sie eine Containeransicht in Ihrer VC erstellen, wird automatisch eine "untergeordnete" VC erstellt, die Sie entfernen möchten.
Ziehen und halten Sie dann die rechte Maustaste, die Linie von der Containeransicht zu unserer TableVC, und wählen Sie "Einbetten" aus der Dropdown-Liste. Jetzt wird Ihr "Kind" VC in das "Elternteil" gezeichnet und versucht, in seine Größe zu passen.
In dem Moment, in dem Sie nur noch „machen“ müssen: Strecken Sie die Containeransicht über die gesamte Ansicht und lassen Sie oben etwas Platz für andere Inhalte (z. B. Titel), wählen Sie Ihre „gelbe“ VC aus und wählen Sie Editor -> Automatische Layoutprobleme beheben -> Alle Ansichten -> Auf vorgeschlagene Einschränkungen zurücksetzen .
Eine Krücke ist notwendig, weil Das automatische Layout wird in diesem Artikel nicht behandelt.


Nachdem wir unsere Platte eingebettet haben, müssen wir die Daten irgendwie in sie laden. Erstellen Sie zunächst eine Klasse für unsere TableVC.
Erstellen Sie eine Swift-Datei "MyTable.swift" und schreiben Sie diesen Code hinein
Versteckter Text
import UIKit
class MyTable: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}


Dann wählen wir in Stroryboard unseren Tabellencontroller aus und ändern seine Klasse in MyTable


Laden von Daten in MyTable

Der Vorteil unseres TableViewControllers besteht darin, dass Sie nichts mit irgendetwas verknüpfen müssen - definieren Sie einfach die Funktionen neu, die wir benötigen (Anzahl der Abschnitte, Anzahl der Zeilen in einem Abschnitt, Objekt der n-ten Zeile eines Abschnitts usw.) von TableView. Und hier hilft uns die automatische Vervollständigung - es ist nicht in Worten klar, aber im Video können Sie gut zeigen:

Für das Tablet benötigen wir eine Beispielzeile der Tabelle, die wie folgt aus dem Storyboard erstellt werden kann:


Füllen Sie nun unsere Datei mit dem Code:
MyTable.swift
import UIKit
class MyTable: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //кол-во элементов для каждой из секций
        return 10
    }
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //надо вернуть объект для отображения n-ной ячейки таблицы
        let cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as UITableViewCell
        cell.textLabel.text = "Строка #\(indexPath.item)"
        return cell
    }
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        //а это вызывается если юзер кликнул по какой-то ячейке
    }
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        //а здесь нао вернуть кол-во секций(для простой таблицы это 1)
        return 1
    }
}


Nun müssen wir ein 10-zeiliges Etikett anzeigen. Überprüfen Sie Folgendes:
Alles arbeitet


Wir haben also ein Tablet. Für sich genommen ist kein Navigationscontroller erforderlich. Dazu benötigen wir eine VC, die detaillierte Informationen zu einigen Elementen der Platte anzeigt.
Erstellen Sie eine Klasse für den Controller in der Datei Detail.swift
import UIKit
class Detail: UIViewController {
    required init(coder aDecoder: NSCoder) {
        id = 0
        super.init(coder: aDecoder)
    }
    @IBOutlet weak var idDetail: UILabel!//эта перменная связана с лэйблом с текстом "id..."
// получается, как и все, перетаскиванием 
    var id: Int //для передачи id в объект нашего view при переходе
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        idDetail.text = "\(id)"
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}



Erstellen Sie eine VC und binden Sie sie an Detail.swift und MyTableVC. Verbindung MyTable -> Detail heißt "ToDetail"


Bearbeiten Sie nun die MyTable-Datei:
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {//вызывается перед кадым показом Detail
        let vc = segue.destinationViewController as Detail
        let id = sender as Int//сохраним отправителя в поле такого же типа в Detail
        vc.id = id
    }
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        //а это вызывается если юзер кликнул по какой-то ячейке
        performSegueWithIdentifier("ToDetail", sender: indexPath.item)//отправителем мы задали номер ячейки, а можно любой объект
    }

Infolgedessen sieht der Code so aus

import UIKit
class MyTable: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //кол-во элементов для каждой из секций
        return 10
    }
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //надо вернуть объект для отображения n-ной ячейки таблицы
        let cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as UITableViewCell
        cell.textLabel.text = "Строка #\(indexPath.item)"
        return cell
    }
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {//вызывается перед кадым показом Detail
        let vc = segue.destinationViewController as Detail
        let id = sender as Int//сохраним отправителя в поле такого же типа в Detail
        vc.id = id
    }
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        //а это вызывается если юзер кликнул по какой-то ячейке
        performSegueWithIdentifier("ToDetail", sender: indexPath.item)//отправителем мы задали номер ячейки? а можно любой объект
    }
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        //а здесь нао вернуть кол-во секций(для простой таблицы это 1)
        return 1
    }
}



Detaillierte Demo

Wir haben bereits alles getan, um das Laden von Daten beim Öffnen von Detail zu simulieren. Checken Sie den Simulator ein:

Wie Sie sehen können, werden unsere Details geladen und erhalten das, was angezeigt werden soll. Wir können jedoch nicht zur Liste der Optionen zurückkehren. Und hier können Sie den Navigationscontroller verwenden und nicht Ihr Fahrrad.

Navigationscontroller in der Registerkartenleiste


Am einfachsten ist es, unsere „gelbe“ VC in den NavigationConctroller einzupacken:

Unterwegs legen wir den Navigationstitel für die „gelbe“ VC und den Text der Zurück-Schaltfläche fest.

Schon nicht schlecht, wir können sofort zurückkehren, ohne Code zu schreiben. Das untere Menü wird jedoch in einer Detailansicht angezeigt, obwohl es dort nicht benötigt wird. Um es zu entfernen, aktivieren Sie das Kontrollkästchen "Untere Leiste beim Drücken ausblenden" auf "Detail"


Das Problem ist, dass es standardmäßig nur die Schaltfläche "Zurück" gibt, die nur für eine einfache Rückgabe verwendet wird. Wenn wir vor dem Verlassen etwas tun möchten, müssen wir sie an andere Schaltflächen anhängen.
Stellen Sie sich vor, der Benutzer kann etwas "kaufen". Wir fügen zwei Optionen hinzu: über die obere Navigationsleiste und durch Klicken auf eine Schaltfläche.

Der Kauf selbst wird über die Funktion doIt aufgerufen
    func doIt() {
        //делаем тут что-то с нашим id
        println(id)
        //возвращаемся назад
        navigationController?.popViewControllerAnimated(true)
    }

Beachten Sie die Navigation? .PopViewControllerAnimated (true) ist es dank dieser Linie , wie wir zurückkommen , wenn Sie auf die Schaltfläche „Zurück“ in der Navigationsleiste gedrückt.

Bei einer Schaltfläche wird der Aufruf dieser Funktion einfach im TouchUpInside-Ereignishandler der Schaltfläche platziert, bei der Schaltfläche in der Navigation müssen Sie jedoch hinzufügen
        var rightButton = UIBarButtonItem(title: "Купить", style: .Done, target: self, action: "doIt")
        self.navigationItem.rightBarButtonItem = rightButton

in viewDidLoad.
Infolgedessen sieht der Code so aus
import UIKit
class Detail: UIViewController {
    required init(coder aDecoder: NSCoder) {
        id = 0
        super.init(coder: aDecoder)
    }
    @IBOutlet weak var idDetail: UILabel!//чтобы показать, что мы получили id
    var id: Int//для того, чтобы передать этому vc id
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        idDetail.text = "\(id)"
        var rightButton = UIBarButtonItem(title: "Купить", style: .Done, target: self, action: "doIt")
        self.navigationItem.rightBarButtonItem = rightButton
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    @IBAction func buyPressed(sender: AnyObject) {
        doIt()
    }
    func doIt() {
        //делаем тут что-то с нашим id
        println(id)
        //возвращаемся назад
        navigationController?.popViewControllerAnimated(true)
    }
}


Schauen wir uns das Endergebnis in der Demo an.


Das ist alles für jetzt. Ein Beispielprojekt kann hier heruntergeladen werden .
Viele Punkte mussten ignoriert werden, um nicht zu überladen. Wenn Sie jedoch der Meinung sind, dass etwas hinzugefügt werden muss, schreiben Sie an die PM.
Hoffe, dieser Artikel ist für jemanden hilfreich.

Nur registrierte Benutzer können an der Umfrage teilnehmen. Bitte komm rein .

Weiter schreiben "Anfängerhandbücher"?

  • 84,7% Ja 189
  • 3,5% Nein, ich bin neu bei 8
  • 6,2% Nein, ich bin ein erfahrener Entwickler und ich denke, Ihre Artikel sind unnötig 14
  • 5,3% Format ändern 12

Jetzt auch beliebt: