werken met Table View Controllers in Swift
geschreven door Reinder de Vries op 3 augustus 2020 In App Development, iOS
in deze tutorial zal ik u stap-voor-stap laten zien hoe tabelweergavecontrollers werken en hoe u ze kunt gebruiken. We gaan in het volledige gamma van UITableViewController
, door te duiken in objectgeoriënteerd programmeren, delegeren en de achter-de-schermen mechanismen van tafelweergaven.
een tabelweergavecontroller toont gestructureerde, herhaalbare informatie in een verticale lijst. U gebruikt de klasse UITableViewController
in uw iOS-app om een tabelweergavecontroller te bouwen.
werken met een tabelweergavecontroller betekent ook werken met een paar belangrijke iOS-ontwikkelingsconcepten, zoals subclassering, het delegatieontwerp en hergebruik van weergaven.
het is belangrijk voor professionele en praktische iOS-ontwikkelaars (u!) om het werken met tabelweergavecontrollers onder de knie te krijgen. Als je eenmaal gewend bent aan het werken aan zo ‘ n veelzijdige UI-component, zoals UITableViewController
, zullen ook andere meer complexe aspecten van iOS-ontwikkeling zinvol worden.
klaar? Laten we erin duiken!
- Hoe werkt een Tabelweergavecontroller
- een eenvoudige Tabelweergavecontroller instellen
- coderen van de Tabelweergavecontroller gegevensbron
- cellen leveren aan de Tabelweergavecontroller
- reageren op gebruikersinteractie
- verder lezen
Hoe werkt een Tabelweergavecontroller
als u eerder een iOS-app hebt gebruikt, hebt u tabel gebruikt controllers eerder bekijken. Ze worden vaak gebruikt in iOS-apps!
hier is een voorbeeld van een tabelweergavecontroller:
een tabelweergavecontroller heeft meestal deze zichtbare componenten:
- een tabelweergave, dat is de gebruikersinterface component, of weergave, die wordt weergegeven op het scherm. Een tabelweergave is een instantie van de klasse
UITableView
, die een subklasse vanUIScrollView
is. - Tabelweergavecellen, de herhaalbare rijen of weergaven, die worden weergegeven in de tabelweergave. Een tabelweergavecel is een instantie van een
UITableViewCell
– klasse, en die klasse wordt vaak gesubclasseerd om aangepaste tabelweergavecellen te maken.
een tabelweergavecontroller vertrouwt ook op het gebruik van deze componenten, achter de schermen:
- een gedelegeerde voor tabelweergave, die verantwoordelijk is voor het beheer van de opmaak van de tabelweergave en het reageren op gebruikersinteractiegebeurtenissen. Een tabelweergave gedelegeerde is een instantie van de
UITableViewDelegate
klasse. - een gegevensbron voor tabelweergave, die verantwoordelijk is voor het beheer van de gegevens in een tabelweergave, inclusief tabelweergavecellen en-secties. Een gegevensbron is een instantie van de klasse
UITableViewDataSource
.
een navigatiecontroller wordt vaak gebruikt in conjunctie met een tabelweergave controller om navigatie tussen de tabelweergave en de daaropvolgende weergavecontrollers mogelijk te maken, en om een navigatiebalk boven de tabelweergave weer te geven.
het interessantste deel van het werken met tabelweergavecontrollers is de tabelweergavecontroller zelf! Hoe dat zo?
bent u bekend met de Model-View-Controller-architectuur? Volgens de Model-View-Controller-architectuur zijn een tabelweergave en een tabelweergavecel weergaven en is een tabelweergavecontroller een controller.
Views zijn verantwoordelijk voor het zichtbaar weergeven van informatie voor de gebruiker, met een gebruikersinterface (UI). Controllers zijn verantwoordelijk voor het implementeren van logica, het beheren van gegevens en het nemen van beslissingen. Anders gezegd: Je kunt geen controller zien, maar het is er wel, het beheren van wat je ziet door middel van views.
wanneer u een tabelweergavecontroller gebruikt in uw app, wordt de klasse UITableViewController
gesubclasseerd. De UITableViewController
klasse zelf is een subklasse van UIViewController.
hier is de klassenhiërarchie van een voorbeeld tabelweergavecontroller die contactinformatie weergeeft:
- een exemplaar van
ContactsTableViewController
- subklassen
UITableViewController
- subklassen
UIViewController
- subklassen
- subklassen
volgens de principes van objectgeoriënteerd programmeren (OOP) erft klasse RaceCar
subklassen klasse Vehicle
de eigenschappen en functies van die superklasse, zoals maxSpeed
en drive()
.
de klasse Vehicle
wordt dan de superklasse van RaceCar
genoemd. Dit principe heet overerving.
verwarrend? Dat kan het zijn! Denk er zo over na.: om je table view controller goed te laten werken, moet je een hoop code erven, zodat je niet al die code zelf hoeft te schrijven. De klassenhiërarchie, en OOP, is er om die erfenis te structureren.
u kunt met tabelweergaven werken zonder een tabelweergavecontroller te gebruiken. Voeg gewoon een UITableView
toe aan een weergavecontroller, geef het implementaties van de functies table view delegate en data source, en je bent klaar.
de klasse UITableViewController
biedt standaard implementaties van deze tabelweergave gedelegeerde en tabelweergave gegevensbronfuncties. Dat is een cruciaal aspect van het werken met een table view controller!
zoals u zult zien in de volgende hoofdstukken van deze handleiding, zullen we deze functies overschrijven met onze eigen implementaties. We kunnen de tabelweergave controller aanpassen door dat te doen.
leer hoe u iOS-apps
aan de slag gaat met iOS 14 en Swift 5
Meld u aan voor mijn iOS-ontwikkelcursus en leer hoe u geweldige iOS 14-apps kunt bouwen met Swift 5 en Xcode 12.
het opzetten van een eenvoudige tabelweergave Controller
goed, laten we dat allemaal in de praktijk brengen. In deze sectie, gaan we een eenvoudige tabel view controller te bouwen. Je gaat de functies implementeren die nodig zijn om het te laten werken, en Ik zal uitleggen hoe ze werken terwijl we verder gaan. Laten we opschieten!
U kunt gebruik maken van 3 verschillende benaderingen van het werken met UIs in Xcode:
- weergaven Maken programmatisch, d.w.z. codering ze met de hand
- Instellen UIs in Interface Builder en ze te verbinden met Swift-code via XIBs
- Instellen UIs en hun overgangen in Interface Builder gebruik van Storyboards
- (Technisch, kunt u gebruik maken van SwiftUI ook, maar voor de tabelweergave controllers, dat is buiten de scope van deze handleiding.)
het is vervelend en onproductief om code UI ‘ s met de hand. Als je niet voorzichtig bent met Storyboards, verbergen ze complexiteit voor de ontwikkelaar. We gaan met Storyboards werken, terwijl we achter de schermen precies uitzoeken hoe ze werken.
dit is wat je gaat doen:
maak eerst een nieuw Xcode project aan via File → New → Project…. Zorg ervoor dat u de app template te kiezen, en kies Storyboard voor Interface en UIKit app Delegate voor Life Cycle.
neem dan deze stappen:
- Rechtermuisknop op je project in de Project Navigator en kies Bestand…
- Kies het Cocoa Touch-Klasse-sjabloon (iOS)
- Kies
UITableViewController
voor Subklasse van - de Naam van de klasse
ContactsTableViewController
- niet aanvinkt Ook XIB-bestand
- tot slot, klik op Volgende en sla het bestand op naast de andere Swift bestanden
en ten Slotte, doen dit:
- Ga naar
Main.storyboard
en verwijder de bestaande View Controller Scène - Voeg een nieuwe Tabel Weergeven de Controller aan het storyboard via de Bibliotheek
- Met de table view-controller geselecteerd, gaat u naar de Eigenschappen Inspecteur en vink het Is de Eerste View Controller checkbox
- ten Slotte, ga naar de Identiteit van de Inspecteur ingestelde Klasse
ContactsTableViewController
Dat is het! Je hebt nu een tabelweergavecontroller in het storyboard van het project, en je hebt deze aangesloten op de ContactsTableViewController
Swift-klasse.
zoals u al geraden hebt, is uw ContactsTableViewController
klasse een subklasse van UITableViewController
. Je kunt dat zien in het Swift-bestand, bovenaan, in de klassenverklaring.
class ContactsTableViewController: UITableViewController { ···
deze syntaxis betekent: de klasse ContactsTableViewController
is een subklasse van UITableViewController
.
wanneer u met de rechtermuisknop op “UITableViewController” klikt terwijl u de Option-key vasthoudt, kunt u in de class declaration zien dat UITableViewController
een subklasse van UIViewController
is en voldoet aan de protocollen UITableViewDelegate
en UITableViewDataSource
.
dat is de kracht van de tabelweergavecontroller! Het geeft ons niet alleen de individuele componenten om een tabelweergave te maken, de controller biedt ook een standaard implementatie. Daarom geven we een subklasse UITableViewController
, in plaats van een lege weergavecontroller te maken met een tabelweergave.
op dit punt kunt u uw app uitvoeren met Command-R
of de afspeelknop en de lege tabelweergavecontroller op het scherm zien verschijnen.
Waarom is dat trouwens? We hebben nog niets gecodeerd! Dat komt omdat de table view controller een standaard implementatie heeft, die alleen lege cellen op het scherm toont. Gaaf!
afhankelijk van uw versie van Xcode hebben we de scene delegate gebruikt om de eerste weergavecontroller van uw app-project in te stellen. Meer informatie hier: de Scene Delegate in Xcode
een XIB en een penpunt zijn in principe hetzelfde – ze bevatten lay-out informatie. Een XIB heeft een XML formaat, terwijl een penpunt een binair formaat heeft. De XML wordt gecompileerd naar binair wanneer je je app bouwt, dus dat is waarom UIKit ‘ s functies altijd praten over een “nib”, terwijl Xcode het altijd een “xib”noemt.
coderen van de Table View Controller gegevensbron
nu uw table view controller is ingesteld, laten we het tot leven brengen! In dit hoofdstuk zullen we ons concentreren op de verschillende functies die u moet implementeren om uw tabelweergavecontroller te laten werken.
zoals eerder uitgelegd, behoren deze functies ofwel tot de tabel weergave controller gedelegeerde, of de tabel weergave controller gegevensbron. Beide protocollen gebruiken delegatie om de tabelweergave aan te passen.
De belangrijkste functies voor UITableViewDataSource
zijn:
numberOfSections(in:)
tableView(_:numberOfRowsInSection:)
tableView(_:cellForRowAt:)
Overige relevante functies voor UITableViewDelegate
zijn:
tableView(_:didSelectRowAt:)
tableView(_:willDisplay:for:)
U vindt meer functies in het Apple Developer-Documentatie voor UITableViewDelegate en UITableViewDataSource.
de contactgegevens toevoegen
u begint met het toevoegen van de contactgegevens voor de tabelweergavecontroller. De volgende eigenschap toevoegen aan klasse ContactsTableViewController
:
let contacts:] = , , , , , , , , , , , , , , , , ]
dat is een rolodex die we allemaal willen hebben, toch? Zo werkt het:
- de
let contacts
verklaart een constante met naamcontacts
. Je hebt het Toegevoegd als een eigenschap aan de klasse, dus elke klasse instantie heeft toegang tot deze constante in de code van de klasse. - het type van
contacts
is]
, dat is array of arrays of strings. Je maakt in wezen een array, waarvan de items arrays van strings zijn. (Een variabele naam en zijn type worden gescheiden door een dubbele punt:
) - de code
=
kent een array toe aancontacts
, ingevuld met de namen en telefoonnummers van enkele miljardairs.
later kunnen we het aantal items in de array gebruiken met contacts.count
. En we kunnen individuele namen en telefoonnummers krijgen met contacts
en contacts
, met behulp van subscript syntaxis.
het registreren van een Tabelweergavecelklasse
voordat u cellen in een tabelweergavecontroller kunt gebruiken, moet u ze registreren met de tabelweergave. U kunt dit op twee manieren doen:
- door een tabelweergavecelklasse en een identifier
- door een tabelweergavecel XIB en een identifier
op te geven wanneer u een aangepaste tabelweergavecel gebruikt, wilt u waarschijnlijk een XIB daarvoor registreren. Wanneer u de standaard tabelweergavecellen of een andere programmatische cel gebruikt, registreert u de klasse. We gebruiken de klas, voor nu!
voeg de volgende code toe aan de functie viewDidLoad()
:
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")
zorg ervoor dat u het onder de super.viewDidLoad()
regel toevoegt. Zoals u waarschijnlijk Weet, maakt de functie viewDidLoad()
deel uit van de levenscyclus van de weergavecontroller en behoort deze tot de klasse UIViewController
.
u overschrijft de functie viewDidLoad()
om te reageren op deze gebeurtenis in de levenscyclus van een weergavecontroller, zodat u uw weergave kunt instellen nadat deze is geladen. In ons geval gebruiken we de functie om de tabelweergavecel te registreren.
wanneer u een tabelweergavecel registreert, moet u ook een identifier opgeven. Dit is gewoon om de klasse van de cel te associëren met een naam die u later kunt gebruiken bij het dequeuing van de cel in tableView(_:cellForRowAt:)
.
bent u er nog? Laten we verder gaan!
implementeren van ” numberOfSections (in:)”
de eerste gedelegeerde functie die we gaan implementeren is numberOfSections(in:)
.
een tabelweergave kan meerdere secties of groepen hebben. Elke groep heeft een header die bovenop de verticale rij cellen drijft. In een Contacten app, je kon contacten samen Alfabetisch groeperen. Dit wordt eigenlijk gedaan in de contacten app op de iPhone, waar de contacten zijn gegroepeerd A-Z.
de app die we bouwen heeft slechts een sectie. Voeg de volgende functie toe aan de klasse:
override func numberOfSections(in tableView: UITableView) -> Int{ return 1}
simpel, toch? De functie geeft 1
terug als deze wordt aangeroepen.
implementatie van “tableView (_: numberOfRowsInSection:)”
een soortgelijke functie is tableView(_:numberOfRowsInSection:)
. In plaats van het aantal secties, Het geeft het aantal rijen in een sectie. Omdat in een tabelweergave cellen in een verticale lijst worden weergegeven, komt elke cel overeen met een rij in de tabelweergave.
de app die we bouwen heeft slechts één sectie, en die ene sectie heeft een aantal items gelijk aan het aantal items in de contacts
array. Dus, dat is contacts.count
!
voeg de volgende functie toe aan de klasse:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return contacts.count}
zie je hoe dat werkt? We geven gewoon contacts.count
terug. Als u een andere naam en telefoonnummer aan contacts
zou toevoegen, zou dit ook mooi in de tabelweergave verschijnen.
rijen en secties begrijpen
onze contacten app is eendimensionaal, het toont slechts een lijst met namen en telefoonnummers, en het maakt geen gebruik van groepen. Maar wat als u een gegroepeerde tabelweergave hebt?
in de meeste gevallen zou uw gegevensbron, zoals de contacts
array, ook multi-dimensionaal zijn. Je zou groepen organiseren op het eerste niveau, en individuele items op het tweede niveau, “onder” de groepen.
- Countries - A - Afghanistan - Albania - ... - B - Bahamas - Bahrain - ... - C - Cambodia - Cameroon - ...
het aantal groepen is gelijk aan countries.count
, en het aantal landen in een enkele groep is gelijk aan countries.count
, waarbij x
de sectie-index is. Die sectieindex wordt gegeven als parameter in tableView(_:numberOfRowsInSection:)
.
is het u opgevallen dat deze twee functies een parameter hebben met de naam tableView
? Dat is onderdeel van het objectgeoriënteerde Programmeerprincipe. U kunt technisch een tabelweergave-gegevensbron gebruiken en delegeren om meerdere tabelweergaven aan te passen. U gebruikt tableView
om te bepalen met welke tabelweergave u werkt.
stel je voor dat je een Contactenapp hebt die telefoonnummers op naam kan weergeven, of telefoonnummers georganiseerd per bedrijf. Je zou dat op meerdere manieren kunnen implementeren, bijvoorbeeld door je tabelweergavecontrollers te hergebruiken. Of wat als u de lay-out van uw contacten-app wilt hergebruiken om vergelijkbare informatie weer te geven, zoals restaurants, locaties of Skype-Gebruikersnamen? Dat is waar code hergebruik met OOP komt in!
cellen leveren aan de Tabelweergavecontroller
We komen er! Laten we verder gaan met de belangrijkste functie van een tabelweergavecontroller: tableView(_:cellForRowAt:)
.
we zullen de functie implementeren voordat we in de details duiken, maar er zijn een paar dingen die je erover moet begrijpen:
- als het
- heet wat een indexpad is
- hoe het cellen
hergebruikt, voeg dan eerst de volgende functie toe aan de klasse ContactsTableViewController
:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{}
zo werkt het:
- de functie overschrijft de superclass-implementatie van
UITableViewController
. Je weet nu hoe dat werkt, toch? We negeren de standaard implementatie, en vervangen onze eigen. Dat komt omdatUITableViewController
al de table view delegate en data source voor ons heeft geïmplementeerd. - net als voorheen heeft de functie één parameter
tableView
die we kunnen gebruiken om de tabelweergave te identificeren waarop deze functie wordt aangeroepen. - een andere parameter is
indexPath
, met argument labelcellForRowAt
. Het indexpad identificeert de indicesrow
ensection
van de cel. Daarover later meer. - het functietype is
UITableViewCell
. Dat is interessant. Deze functie wordt aangeroepen door de tabelweergavecontroller, elke keer dat we een tabelweergavecel moeten bieden!
wanneer u door de contacten in deze app scrolt, wordt telkens wanneer een cel op het scherm moet worden weergegeven, de functie tableView(_:cellForRowAt:)
aangeroepen. Elke keer! Ik zal het je zo bewijzen.
laten we nu het functielichaam schrijven. Voeg de volgende code toe in de functie:
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath)print("\(#function) --- section = \(indexPath.section), row = \(indexPath.row)")cell.textLabel?.text = contactsreturn cell
Dit is wat er gebeurt:
- eerst dequeue we een cel met een identifier. Het is precies dezelfde identificatie die we eerder gebruikten, bij het registreren van de cel. Op die manier weet de tabelweergave welk type cel we willen. De in de wachtrij geplaatste cel wordt toegewezen aan de constante
cell
. Nu hebben we een tabelweergavecel om mee te werken. Meer over dequeuing later. - vervolgens printen we wat informatie naar de Console. Dit is zodat we kunnen zien wanneer deze functie wordt aangeroepen, wanneer de app draait.
- vervolgens wijzen we de naam van het contact toe aan het tekstlabel van deze tabelweergavecel.
contacts
bevat de waarde van de naam van het contact, die we bereiken metindexPath.row
. Elke instantie vanUITableViewCell
heeft een eigenschaptextLabel
vanUILabel
, en elk label van dat type heeft een eigenschaptext
. Je gebruikt het om de tekst op het label in te stellen.
maak je geen zorgen, we zullen elk van deze dingen in meer detail bespreken. Eerst, kijk of u uw app kunt uitvoeren. Zie je namen van contactpersonen? Ziet u de debug-uitvoer in de Console? Probeer de app te scrollen!
wanneer wordt “tableView (_: cellForRowAt:)” aangeroepen?
als u de contacten-app hebt uitgevoerd en hebt gespeeld met op en neer scrollen, kunt u niet anders dan opmerken dat elke keer dat u scrolt, debug-uitvoer wordt weergegeven in de Console.
elke keer dat een cel verschijnt die niet eerder op het scherm stond, wordt de functie tableView(_:cellForRowAt:)
aangeroepen en verschijnt er een nieuwe regel in de Console.
dus wanneer wordt tableView(_:cellForRowAt:)
aangeroepen? Elke keer dat een tabelweergave-cel op het scherm moet worden weergegeven!
de tabelweergavecontroller heeft bepaald dat een cel nodig is, dus wordt tableView(_:cellForRowAt:)
aangeroepen. Onze implementatie van die functie dequeueert een cel, verandert deze, en geeft deze terug aan de tabelweergavecontroller. De table view controller, en het UIKit framework, dan maakt het Grafisch op het scherm.
Wat is een Indexpad?
elke keer dat de tabelweergavecontroller een cel van tableView(_:cellForRowAt:)
nodig heeft, biedt deze een indexpad als argument voor de functie. Binnen de functie kunt u de parameter indexPath
gebruiken om precies te weten welke cel de tabelweergavecontroller nodig heeft.
een indexpad is als een adres, of een coördinaat in een raster. Een typische grafiek heeft een X-as en een Y-as, dus je kunt een coördinaat in die grafiek uitdrukken als x, y
zoals 0, 1
en 42, 3
. Evenzo heeft een spreadsheet rijen en kolommen met indices.
een tabelweergave gebruikt secties en Rijen. Zoals eerder besproken, kunt u secties gebruiken om cellen samen te groeperen. Onze app heeft slechts één sectie, en het heeft contacts.count
rijen. De rijen van de tabelweergave lopen van boven naar beneden.
zei anders: de secties en rijen van een tabelweergave zijn wat kolommen en rijen zijn voor een spreadsheet. Een indexpad definieert een locatie in de tabelweergave, met behulp van een rij en een sectie.
de rijen en secties worden weergegeven door getallen, die indices worden genoemd. Deze indices beginnen bij nul, dus de eerste rij en sectie hebben indexnummer 0
.
wanneer u terugkijkt op de vorige schermafbeelding, is dit veel logischer. De eerste cel heeft indexpad 0, 0
, de tweede cel 0, 1
, die verder gaat tot de laatste zichtbare cel met indexpad 0, 11
.
het Hergebruikmechanisme voor tabelweergave
het meest opvallende aan de tabelweergave is het mechanisme voor celhergebruik. Het is eigenlijk heel simpel.
- elke keer dat een tabelweergavecontroller een cel op het scherm moet weergeven, wordt de functie
tableView(_:cellForRowAt:)
aangeroepen, zoals we eerder hebben besproken. - in plaats van elke keer dat die functie wordt aangeroepen een nieuwe tabelweergavecel aan te maken, kiest deze een eerder aangemaakte cel uit een wachtrij.
- de cel reset naar een lege toestand, wist zijn uiterlijk, en de cel wordt opnieuw aangepast in
tableView(_:cellForRowAt:)
. - wanneer een cel buiten het scherm wordt geschoven, wordt deze niet vernietigd. Het is toegevoegd aan de wachtrij, wachtend om te worden hergebruikt.
het is heel slim, toch? In plaats van cellen te maken en te verwijderen, hergebruikt u ze gewoon. Maar … waarom?
het is veel minder geheugenintensief om cellen te hergebruiken. De tabelweergavecontroller zou constant naar het geheugen schrijven bij het maken en verwijderen van cellen. Het beheer van het geheugen zou ook intensiever zijn. Wanneer cellen worden hergebruikt, wordt het geheugen efficiënter gebruikt en zijn er minder geheugenbewerkingen nodig.
ook is itt iets minder CPU-intensief om cellen te hergebruiken in plaats van ze te maken en te verwijderen, omdat er simpelweg minder bewerkingen zijn betrokken bij het hergebruiken, in vergelijking met het maken en verwijderen van cellen.
wanneer u snel door een tabelweergave scrolt, ziet u geen nieuwe cellen – u ziet dezelfde cellen keer op keer, met nieuwe informatie.
de code die betrokken is bij celhergebruik is deze:
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath)
de functie dequeueReusableCell(withIdentifier:)
probeert een cel te dequeue. Als er geen cellen in de wachtrij staan, wordt er een cel voor ons gemaakt. De identifier wordt gebruikt om elk type cel in hun eigen wachtrij te houden en om ervoor te zorgen dat de juiste klasse wordt gebruikt om nieuwe cellen te maken.
leer hoe u iOS-apps
aan de slag gaat met iOS 14 en Swift 5
Meld u aan voor mijn iOS-ontwikkelcursus en leer hoe u geweldige iOS 14-apps kunt bouwen met Swift 5 en Xcode 12.
reageren op gebruikersinteractie
Eén ding ontbreekt in onze tabelweergavecontroller: de mogelijkheid om mensen in onze contactenlijst te bellen! Maar voordat we dat doen, laten we ervoor zorgen dat u ook kunt zien telefoonnummer van een contactpersoon in de tabel weergave controller.
de standaard UITableViewCell
klasse heeft 4 verschillende typen, zoals uitgedrukt in de UITableViewCellStyle
opsomming. U kunt kiezen tussen:
-
.default
– een eenvoudige weergave met een lijn van zwarte tekst -
.value1
– een eenvoudige weergave met een lijn van zwarte tekst op een van de links, en een klein blauw label aan de rechterkant (gebruikt in de Instellingen-app) -
.value2
– een eenvoudige weergave met een lijn van zwarte tekst aan de rechterkant, en een klein blauw label aan de linkerkant (gebruikt in de Contacten app) -
.subtitle
– een eenvoudige weergave met een lijn van zwarte tekst, en een kleinere lijn van de grijze tekst hieronder het
de Meeste ontwikkelaars maken gebruik van aangepaste tabel bekijk de cellen van deze dagen, dus je zult niet zien deze celtypen dat vaak. Maar ze zijn er!
we moeten de code in tableView(_:cellForRowAt:)
enigszins aanpassen. Vervang de eerste regel van de functie door de volgende code:
var cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")if cell == nil{ cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellIdentifier")}
als je goed kijkt, zul je zien dat we het for: indexPath
deel van de dequeueReusableCell(...)
aanroep hebben verwijderd. In plaats daarvan, die functie geeft nu een optioneel. Wanneer een cel niet kan worden gedequeue, geeft de functie nil
terug.
we springen er dan zelf in om de cel te maken, als deze nil
is. Dat zie je in het tweede deel van de code. U gebruikt een conditionele if
statement om te controleren of cell
gelijk is aan nil
, en als dat waar is, maakt u de cel met behulp van de UITableViewCell(style:reuseIdentifier:)
initializer.
die initializer krijgt twee argumenten, de celstijl .subtitle
, en de identifier die we eerder hebben gebruikt.
op dit moment hebben we een probleem, omdat cell
nu optioneel is! Het type is UITableViewCell?
, maar de functie return type vereist dat we een instantie retourneren met niet-optioneel type UITableViewCell
.
gelukkig is dit een van die gevallen waarin we veilig force unwrapping kunnen gebruiken om de optionele waarde uit te pakken. Vanwege de manier waarop onze code geschreven is, is het onmogelijk voor cell
om nil
buiten de voorwaarde te zijn. U kunt garanderen dat cell
niet nil
is na het if
statement.
zorg ervoor dat u de functie bijwerkt om forceer uitpakken te gebruiken voor cell
. Voeg ook de volgende regel code toe onder cell!.textLabel ...
om de ondertitel van de cel in te stellen die het telefoonnummer van het contact toont.
cell!.detailTextLabel?.text = contacts
de gehele functie ziet er nu zo uit:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{ var cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") if cell == nil { cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellIdentifier") } print("\(#function) --- section = \(indexPath.section), row = \(indexPath.row)") cell!.textLabel?.text = contacts cell!.detailTextLabel?.text = contacts return cell!}
zorg er ten slotte voor dat u de volgende regel uit viewDidLoad()
verwijdert. Het voorkomt dat de tabelweergave cellen met het verkeerde type initialiseert.
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")
prima! Voer uw app uit met Command + R of de afspeelknop en controleer of het werkt. Zie je namen en telefoonnummers? Goed!
laten we dan voor de pièce-de-résistance die gebruikersinteractiefunctie toevoegen. Nu je de fijne kneepjes van de table view controller hebt geleerd, denk ik dat je al weet hoe deze volgende functie werkt.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){ if let url = URL(string: "tel://" + contacts) { UIApplication.shared.open(url) }}
opnieuw overschrijven we de standaard implementatie van de tableView(_:didSelectRowAt:)
functie. Deze functie wordt aangeroepen wanneer een gebruiker de cel van een tabelweergave tikt, en het behoort tot het UITableViewDelegate
protocol. Net als de andere functies, wordt het indexpad gegeven van de getikte cel.
in de functie body maken we gewoon een tel://
URL van het telefoonnummer. Vervolgens vertellen we de app om die URL te openen, die effectief vertelt iOS om een oproep te starten naar dit nummer. Die code is er alleen ter illustratie. Merk op dat dit niet werkt op de iPhone Simulator, en dat de nummers in onze app zijn nep. (Nog steeds, je zou deze code gebruiken als je het maken van een echte Contacten app!)
u kunt de volgende code aan de functie toevoegen als u wilt controleren of het goed werkt.
print("\(#function) --- Calling: \(contacts)")
dit zal een debug-bericht afdrukken wanneer u op de cel van de tabelweergave tikt.
verder lezen
en dat is alles! Het was een hele reis, maar nu weet je hoe een table view controller werkt.