Als je de vorige lessen van deze serie hebt gelezen, zou je nu een goed begrip moeten hebben van de grondbeginselen van de Swift-programmeertaal. We hadden het over variabelen, constanten en functies, en in de vorige les bespraken we de basisprincipes van objectgeoriënteerd programmeren in Swift.
Hoewel speeltuinen een geweldig hulpmiddel zijn om met Swift te spelen en de taal te leren, is het tijd om verder te gaan en ons eerste Swift-project in Xcode te maken. In deze les gaan we de basis leggen voor een eenvoudige taak met Xcode en Swift. Onderweg komen we meer te weten over objectgeoriënteerd programmeren en zullen we ook de integratie van Swift en Objective-C nader bekijken..
Als je me wilt volgen, zorg er dan voor dat Xcode 8.3.2 of hoger op je computer is geïnstalleerd. Xcode 8.3.2 is verkrijgbaar bij de App Store van Apple.
Start Xcode 8.3.2 of hoger en selecteer Nieuw> Project ... van de het dossier menu. Van de iOS sectie, kies de Toepassing enkele weergave sjabloon en klik volgende.
Geef het project een naam Te doen En instellen Taal naar Snel. Zorg ervoor dat apparaten ingesteld op iPhone en de selectievakjes aan de onderkant zijn uitgeschakeld. Klik volgende doorgaan.
Vertel Xcode waar u uw project wilt opslaan en klik op creëren rechtsonder om je eerste Swift-project te maken.
Voordat we onze reis naar Swift voortzetten, laten we even kijken wat Xcode voor ons heeft gecreëerd. Als je de ontwikkeling van Xcode en iOS nieuw hebt, is het meeste nieuw voor je. Door met een Swift-project te werken, krijgt u echter een beter gevoel van hoe klassen en structuren eruit zien en hoe zij zich in Swift gedragen.
De projectsjabloon verschilt niet veel van een project gemaakt met Objective-C als de programmeertaal. De belangrijkste verschillen hebben betrekking op de AppDelegate
en ViewController
klassen.
Als u in het verleden met Objective-C hebt gewerkt, zult u merken dat de projectsjabloon minder bestanden bevat. Er is geen header (.h) of implementatie (.m) bestanden te vinden in ons project. In Swift hebben klassen geen afzonderlijk headerbestand waarin de interface wordt gedeclareerd. In plaats daarvan wordt een klasse gedeclareerd en geïmplementeerd in een single .snel het dossier.
Ons project bevat momenteel twee Swift-bestanden, een voor de AppDelegate
klasse, AppDelegate.swift, en nog een voor de ViewController
klasse, ViewController.swift. Het project bevat ook twee storyboards, Main.storyboard en LaunchScreen.storyboard. We zullen later in deze les met het belangrijkste storyboard werken. Het bevat momenteel alleen de scène voor de ViewController
klasse.
Er zijn een paar andere bestanden en mappen in het project opgenomen, maar we gaan deze voorlopig negeren. Ze spelen geen belangrijke rol in het kader van deze les.
Het eerste wat we in deze les zullen bespreken is overerving, een gemeenschappelijk paradigma in objectgeoriënteerd programmeren. In Swift kunnen alleen klassen van een andere klasse erven. Met andere woorden, structuren en opsommingen ondersteunen geen overerving. Dit is een van de belangrijkste verschillen tussen klassen en structuren.
Open ViewController.swift om vererving in actie te zien. De interface en implementatie van de ViewController
De les is behoorlijk kaal, wat het ons gemakkelijker maakt om ons op de essentie te concentreren.
Bovenop ViewController.swift, u zou een importverklaring voor het UIKit-framework moeten zien. Vergeet niet dat het UIKit-framework de infrastructuur biedt voor het maken van een functionele iOS-applicatie. De importverklaring bovenaan maakt deze infrastructuur voor ons beschikbaar in ViewController.swift.
importeer UIKit
Onder de import-opdracht definiëren we een nieuwe klasse met de naam ViewController. De dubbele punt na de klassenaam vertaalt zich niet in is van het type zoals we eerder in deze serie zagen. In plaats daarvan is de klasse na de dubbele punt de superklasse van de ViewController
klasse. Met andere woorden, het volgende fragment kan als volgt worden gelezen we definiëren een klasse met de naam ViewController
die erft van UIViewController
.
class ViewController: UIViewController
Dit verklaart ook de aanwezigheid van de importinstructie bovenaan ViewController.swift sinds de UIViewController
klasse wordt gedefinieerd in het UIKit-framework.
De ViewController
klasse bevat momenteel twee methoden, maar merk op dat elke methode wordt voorafgegaan door de override
trefwoord. Dit geeft aan dat de methoden zijn gedefinieerd in de superklasse van de klasse - of hoger in de overervingsboom - en worden overschreven door de ViewController
klasse.
class ViewController: UIViewController override func viewDidLoad () super.viewDidLoad () override func didReceiveMemoryWarning () super.didReceiveMemoryWarning ()
De override
construct bestaat niet in Objective-C. In Objective-C implementeert u een overschreven methode in een subklasse zonder expliciet aan te geven dat deze een methode hoger in de overervingsboom overschrijft. De runtime Objective-C zorgt voor de rest.
Terwijl hetzelfde geldt voor Swift, de override
trefwoorden voegt veiligheid toe aan het overschrijven van methoden. Omdat we het viewDidLoad ()
methode met de override
trefwoord, Swift verwacht deze methode in de superklasse van de klasse of hoger in de overervingsboom. Eenvoudig gesteld, als u een methode overschrijft die niet bestaat in de overervingsboom, zal de compiler een fout genereren. Je kunt dit testen door de spelling verkeerd te spellen viewDidLoad ()
methode zoals hieronder getoond.
Laten we een tabelweergave toevoegen aan de weergavecontroller om een lijst met taken weer te geven. Voordat we dat doen, moeten we een uitlaatklep maken voor het tabeloverzicht. Een outlet is niets meer dan een property die zichtbaar en instelbaar is in Interface Builder. Om een outlet in de te verklaren ViewController
klasse, we prefixen de eigenschap, een variabele, met de @IBOutlet
attribuut.
class ViewController: UIViewController @IBOutlet var tableView: UITableView! override func viewDidLoad () super.viewDidLoad () override func didReceiveMemoryWarning () super.didReceiveMemoryWarning ()
Merk op dat de uitlaat een impliciet niet ingepakte optie is. Een wat? Laat ik beginnen met te zeggen dat een stopcontact altijd een optioneel type moet zijn. De reden is simpel. Elke eigenschap van de ViewController
klasse moet een waarde hebben na initialisatie. Een uitgang is echter alleen tijdens runtime na de gebruikersinterface verbonden met de gebruikersinterface ViewController
instantie is geïnitialiseerd vandaar het optionele type.
Wacht even. De tableView
outlet wordt gedeclareerd als een impliciet niet-verpakt optioneel, geen optioneel. Geen probleem. We kunnen de tableView
stopcontact als een optie door het uitroepteken in het bovenstaande fragment te vervangen door een vraagteken. Dat zou prima compileren. Dit zou echter ook betekenen dat we de eigenschap expliciet moeten uitpakken telkens als we toegang willen tot de waarde die is opgeslagen in de optionele. Dit zou snel omslachtig en uitgebreid worden.
In plaats daarvan verklaren we de tableView
outlet als een impliciet niet-ingepakte optie, wat betekent dat we de optionele niet expliciet hoeven uit te pakken als we toegang tot de waarde ervan nodig hebben. Kortom, een impliciet niet-verpakt optionele is een optionele, maar we kunnen toegang krijgen tot de waarde die is opgeslagen in de optionele als een gewone variabele. Het belangrijkste om in gedachten te houden is dat uw applicatie zal crashen als u probeert toegang te krijgen tot zijn waarde als er geen waarde is ingesteld. Dat is de schuld. Als het stopcontact correct is aangesloten, kunnen we er echter zeker van zijn dat het stopcontact is ingesteld wanneer we het voor het eerst proberen te openen.
Wanneer het stopcontact is gedeclareerd, wordt het tijd om het in Interface Builder aan te sluiten. Open Main.storyboard, en selecteer de weergavecontroller. Kiezen Insluiten> Navigatiecontroller van de Editor menu. Hiermee wordt de weergavecontroller ingesteld als de rootview-controller van een navigatiecontroller. Maak je daar nu geen zorgen over.
Sleep een UITableView
bijvoorbeeld van de Objectbibliotheek naar de weergave van de view controller en voeg de nodige lay-out beperkingen toe. Met de tabelweergave geselecteerd, opent u de Verbindingen Inspecteur en stel de tabelweergave's in databron
en delegeren
uitlaten naar de view controller.
Met de Verbindingen Inspecteur Open nog steeds, selecteer de view controller en sluit de tableView
Uitgang naar de tafelweergave die we zojuist hebben toegevoegd. Dit verbindt de tableView
outlet van de ViewController
klasse naar de tabelweergave.
Voordat we de applicatie kunnen bouwen en uitvoeren, moeten we de UITableViewDataSource
en UITableViewDelegate
protocollen in de ViewController
klasse. Dit gaat om verschillende dingen.
We moeten de compiler vertellen dat het ViewController
klas voldoet aan de UITableViewDataSource
en UITableViewDelegate
protocols. De syntaxis lijkt op die in Objective-C.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate ...
De protocollen waaraan de klasse voldoet, worden na de superklasse weergegeven, UIViewController
in het bovenstaande voorbeeld. Als een klasse geen superklasse heeft, wat niet ongebruikelijk is in Swift, worden de protocollen onmiddellijk na de klassenaam en dubbele punt weergegeven.
UITableViewDataSource
ProtocolOmdat het UITableViewDelegate
protocol definieert de vereiste methoden niet, we gaan alleen de UITableViewDataSource
protocol voor nu. Voordat we dit doen, laten we een variabele-eigenschap maken om de actiepunten die we in de tabelweergave zullen vermelden op te slaan.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate @IBOutlet var tableView: UITableView! var items: [String] = [] ...
We verklaren een variabel eigendom items
van type [Draad]
en stel een lege array in, []
, als de beginwaarde. Dit zou er nu bekend uit moeten zien. Laten we vervolgens de twee vereiste methoden van de UITableViewDataSource
protocol.
De eerste vereiste methode, numberOfRows (inSection :)
, is makkelijk. We retourneren eenvoudig het aantal items dat is opgeslagen in de items
eigendom.
func tableView (_ tableView: UITableView, numberOfRowsInSection sectie: Int) -> Int return items.count
De tweede vereiste methode, cellForRow (bij :)
, heeft een uitleg nodig. We gebruiken de subscriptsyntaxis items
voor het item dat overeenkomt met de huidige rij.
func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell // Fetch Item let item = items [indexPath.row] // Cel van wachtrij laten cel = tableView.dequeueReusableCell (withIdentifier: "TableViewCell", voor: indexPath ) // Celcell.textLabel configureren? .Text = cel van item retourneren
Vervolgens vragen we de tabelweergave voor een cel met ID "TableViewCell"
, doorgeven van het indexpad voor de huidige rij. Merk op dat we de cel in een constante opslaan, cel
. Het is niet nodig om te verklaren cel
als een variabele.
In de volgende regel code configureren we de tabelweergavecel en stelt de tekst van het tekstlabel in met de waarde van item
. Merk op dat in de Swift de TextLabel
eigendom van UITableViewCell
wordt aangegeven als een optioneel type, vandaar het vraagteken. Deze coderegel kan als volgt worden gelezen stel de tekstlabels in tekst
eigendom aan item
als TextLabel
is niet gelijk aan nul
. Met andere woorden, het tekstlabel is tekst
eigenschap is alleen ingesteld als TextLabel
is niet nul
. Dit is een zeer handige veiligheidsconstructie in Swift, bekend als optionele ketting.
Er zijn twee dingen die we moeten uitzoeken voordat we de applicatie bouwen. Eerst moeten we het tabeloverzicht vertellen dat het de UITableViewCell
klasse om nieuwe tabelview-cellen te maken. We doen dit door aan te roepen registerClass (_: forCellReuseIdentifier :)
, passeren in de UITableViewCell
klasse en de hergebruiksidentificatie die we eerder hebben gebruikt, "TableViewCell"
. Werk het viewDidLoad ()
methode zoals hieronder getoond.
override func viewDidLoad () super.viewDidLoad () // Klasse registreren voor Cell Reuse tableView.register (UITableViewCell.self, forCellReuseIdentifier: "TableViewCell")
We hebben momenteel geen items die in de tabelweergave kunnen worden weergegeven. Dit kan eenvoudig worden opgelost door het items
eigendom met een paar te maken items. Er zijn verschillende manieren om dit te bereiken. Ik heb ervoor gekozen om de items
eigendom in de viewDidLoad ()
methode zoals hieronder getoond.
override func viewDidLoad () super.viewDidLoad () // Populate Items items = ["Koop melk", "Finish Tutorial", "Play Minecraft"] // Klasse registreren voor Cell Reuse tableView.register (UITableViewCell.self, forCellReuseIdentifier: "TableViewCell")
Het is tijd om onze applicatie voor een spin te nemen. kiezen Rennen van Xcode's Artikel menu of druk op Command-R. Als je hebt meegedaan, zou je het volgende resultaat moeten behalen.
Merk op dat ik een titel heb toegevoegd, Te doen, bovenaan de weergave in de navigatiebalk. U kunt hetzelfde doen door de titel
eigendom van de ViewController
bijvoorbeeld in de viewDidLoad ()
methode.
override func viewDidLoad () super.viewDidLoad () // Titel instellen title = "Taken" // Items vullen met items = ["Melk kopen", "Les voltooien", "Minecraft spelen"] // Klasse registreren voor hergebruik van cellen tableView.register (UITableViewCell.self, forCellReuseIdentifier: "TableViewCell")
Hoewel we zojuist een eenvoudige applicatie hebben gemaakt, heb je heel wat nieuwe dingen geleerd. We hebben methoden voor overerving en overriding verkend. We hebben ook protocollen behandeld en hoe we de UITableViewDataSource
protocol in de ViewController
klasse. Het belangrijkste dat je echter hebt geleerd, is hoe je kunt communiceren met Objective-C API's.
Het is belangrijk om te begrijpen dat de API's van de iOS SDK zijn geschreven in Objective-C. Swift is ontworpen om compatibel te zijn met deze API's. Op basis van eerdere fouten begreep Apple dat Swift in staat moest zijn om de iOS SDK te gebruiken zonder elke API in Swift te hoeven herschrijven.
Het combineren van Objective-C en Swift is mogelijk, maar er zijn enkele waarschuwingen die we in meer detail zullen bekijken als we verder gaan. Vanwege de niet-aflatende focus van Swift op veiligheid, moeten we van tijd tot tijd een paar hindernissen nemen. Geen van deze hindernissen is echter te groot, zoals we zullen zien in de volgende les waarin we blijven werken aan onze to-do-toepassing.
Bekijk in de tussentijd enkele van onze andere cursussen en zelfstudies over de ontwikkeling van de Swift-taal voor iOS!