arbejde med Tabelvisningskontrollere i hurtig

skrevet af Reinder de Vries den 3. August 2020 i appudvikling, iOS

arbejde med Tabelvisningskontrollere i hurtig

i denne vejledning viser jeg dig trin for trin, hvordan tabelvisningskontrollere fungerer, og hvordan du kan bruge dem. Vi går ind i hele spektret af UITableViewController ved at dykke ned i objektorienteret programmering, delegation og bag-scenes-mekanismerne i bordvisninger.

en tabelvisningskontroller viser strukturerede, gentagelige oplysninger i en lodret liste. Du bruger UITableViewController – klassen i din iOS-app til at oprette en tabelvisningscontroller.

at arbejde med en tabelvisningskontroller betyder også at arbejde med et par vigtige iOS-udviklingskoncepter, såsom underklassering, delegationsdesignmønsteret og genbrug af visninger.

det er vigtigt for professionelle og praktiske iOS udviklere (din!) at mestre at arbejde med tabelvisningskontrollere. Når du har vænnet dig til at arbejde på en sådan multifacetteret UI-komponent, som UITableViewController, vil andre mere komplekse aspekter af iOS-udvikling også begynde at give mening.

klar? Lad os dykke ind!

  1. Sådan fungerer en Tabelvisningscontroller
  2. opsætning af en simpel Tabelvisningscontroller
  3. kodning af Tabelvisningscontrollerens datakilde
  4. tilvejebringelse af celler til Tabelvisningscontrolleren
  5. reaktion på brugerinteraktion
  6. yderligere læsning

hvordan en tabel fungerer Vis controller fungerer

hvis du har brugt en iOS-app før, har du brugt Tabelvisningskontrollere før. De bruges så ofte i iOS-apps!

her er et eksempel på en tabelvisningscontroller:

tabelvisning controller eksempel

en tabelvisning controller har typisk disse synlige komponenter:

  • en tabelvisning, som er brugergrænsefladekomponenten eller visningen, der vises på skærmen. En tabelvisning er en forekomst af klassen UITableView, som er en underklasse af UIScrollView.
  • Tabelvisningsceller, som er de gentagelige rækker eller visninger, der vises i tabelvisningen. En tabelvisningscelle er en forekomst af en UITableViewCell klasse, og denne klasse er ofte underklasseret for at oprette brugerdefinerede tabelvisningsceller.

en tabelvisningskontroller er også afhængig af brugen af disse komponenter bag kulisserne:

  • en tabelvisning delegeret, som er ansvarlig for at styre layoutet af tabelvisningen og reagere på brugerinteraktionshændelser. En delegeret til tabelvisning er en forekomst af klassen UITableViewDelegate.
  • en tabelvisningsdatakilde, som er ansvarlig for at administrere dataene i en tabelvisning, herunder tabelvisningsceller og sektioner. En datakilde er en forekomst af UITableViewDataSource – klassen.

en navigationscontroller bruges ofte i forbindelse med en tabelvisningskontroller for at aktivere navigation mellem tabelvisningen og efterfølgende visningskontrollere og for at vise en navigationslinje over tabelvisningen.

den mest interessante del af arbejdet med bordvisningskontrollere er selve bordvisningskontrolleren! Hvordan det?

er du bekendt med Model-Vis-Controller-arkitekturen? I henhold til model-Vis-Controller-arkitekturen er en tabelvisning og en tabelvisningscelle visninger, og en tabelvisningscontroller er en controller.

visninger er ansvarlige for at vise oplysninger synligt for brugeren med en brugergrænseflade (UI). Controllere er ansvarlige for at implementere logik, styre data og tage beslutninger. Sagt anderledes: Du kan ikke se en controller, men den er der og styrer det, du ser gennem visninger.

når du bruger en tabelvisningskontroller i din app, underklasser du klassen UITableViewController. UITableViewController – klassen i sig selv er en underklasse af Uiviecontroller.

her er klassehierarkiet for en eksempeltabelvisningskontroller, der viser kontaktoplysninger:

  • en forekomst af ContactsTableViewController
    • underklasser UITableViewController
      • underklasser UIViewController

i henhold til principperne for objektorienteret programmering (OOP), når klasse RaceCar underklasser klasse Vehicle, arver den egenskaberne og funktionerne i den superklasse, såsom maxSpeed og drive().

Vehicle klassen kaldes derefter superklasse af RaceCar. Dette princip kaldes arv.

forvirrende? Det kan være! Tænk over det sådan: for at din tabelvisningskontroller skal fungere OK, skal du arve en masse kode, så du ikke behøver at skrive al den kode selv. Klassehierarkiet og OOP er der for at strukturere denne arv.

tabelvisning controller klassediagram

du kan arbejde med tabelvisninger uden at bruge en tabelvisning controller. Du skal blot tilføje en UITableView til en visningscontroller, give den implementeringer af funktionerne tabelvisning og datakilde, så er du færdig.

klassen UITableViewController indeholder standardimplementeringer af disse tabelvisningsdelegat-og tabelvisningsdatakildefunktioner. Det er et afgørende aspekt ved at arbejde med en tabelvisningskontroller!

som du vil se i de næste kapitler i denne tutorial, tilsidesætter vi disse funktioner med vores egne implementeringer. Vi kan tilpasse tabelvisningscontrolleren ved at gøre det.

Lær, hvordan du opbygger iOS-apps

kom i gang med iOS 14 og hurtig 5

Tilmeld dig mit iOS-udviklingskursus, og lær, hvordan du opbygger fantastiske iOS 14-apps med hurtig 5 og kode 12.

opsætning af en simpel tabelvisning Controller

Okay, lad os sætte alt det i praksis. I dette afsnit skal vi opbygge en simpel tabelvisningscontroller. Du skal implementere de funktioner, der er nødvendige for at få det til at fungere, og jeg vil forklare, hvordan de fungerer, når vi går sammen. Lad os komme videre!

du kan bruge 3 forskellige tilgange til at arbejde med UIs i kode:

  1. kode dem i hånden
  2. opsætning af UI ‘er i Interface Builder og tilslutning af dem med hurtig kode via USB
  3. opsætning af UI’ er og deres overgange i Interface Builder ved hjælp af Storyboards
  4. (teknisk set kan du også bruge Hurtigtui, men hvad angår tabelvisningskontrollere, er det uden for rammerne af denne tutorial.)

det er kedeligt og uproduktivt at kode UIs for hånd. Hvis du ikke er forsigtig med Storyboards, ender de med at skjule kompleksitet fra udvikleren. Vi skal arbejde med Storyboards, mens vi finder ud af, hvordan de fungerer bag kulisserne.

her er hvad du skal gøre:

først skal du oprette et nyt Kodeprojekt via Filkr nyt Kart-projekt…. Sørg for at vælge den app skabelon, og vælge Storyboard til Interface og UIKit App delegeret for livscyklus.

tag derefter disse trin:

  1. Højreklik på dit projekt i projektnavigatoren, og vælg Ny fil…
  2. Vælg Cocoa Touch Class-skabelonen (iOS)
  3. Vælg UITableViewController for underklasse af
  4. navngiv klassen ContactsTableViewController
  5. marker ikke også Opret en fil
  6. endelig, klik på Næste og gem filen sammen med de andre hurtige filer

endelig gør dette:

  1. gå ind i Main.storyboard og fjern den eksisterende Visningskontrollerscene
  2. Tilføj en ny Tabelvisningskontroller til storyboardet via biblioteket
  3. når tabelvisningskontrolleren er valgt, skal du gå til Attributinspektøren og markere afkrydsningsfeltet is Initial Visningskontroller
  4. endelig skal du gå til Identitetsinspektøren og indstille klassen til at se controlleren, når du har valgt tabelvisningskontrolleren ContactsTableViewController

sådan! Du har nu en tabelvisningskontroller inde i projektets storyboard, og du har tilsluttet den til Hurtigklassen ContactsTableViewController.

Kodetabelvisning controller oprettet

som du har gættet, er din ContactsTableViewController klasse en underklasse af UITableViewController. Du kan se det i den hurtige Fil øverst i klassedeklarationen.

class ContactsTableViewController: UITableViewController { ···

denne syntaks betyder: klassen ContactsTableViewController er en underklasse af UITableViewController.

når du højreklikker på” Uitablevisecontroller”, mens du holder Option-tasten nede, kan du i klassedeklarationen se, at UITableViewController er en underklasse på UIViewController og overholder protokollerne UITableViewDelegate og UITableViewDataSource.

se tabel Vis Controller dokumentation i kode

det er kraften i tabellen visning controller! Det giver os ikke kun de enkelte komponenter til at lave en tabelvisning, controlleren giver også en standardimplementering. Derfor underklasser vi UITableViewController i stedet for at oprette en tom visningskontroller med en tabelvisning.

på dette tidspunkt kan du køre din app med Command-R eller afspilningsknappen, og se den tomme tabelvisningscontroller vises på skærmen.

Hvorfor er det forresten? Vi har ikke kodet noget endnu! Det skyldes, at tabelvisningscontrolleren har en standardimplementering, der bare viser tomme celler på skærmen. Pænt!

 tabelvisning controller eksempel i iPhone Simulator

afhængigt af din version af koden har vi brugt scenedelegatet til at konfigurere den oprindelige visningscontroller for dit appprojekt. Læs mere her: scenen delegeret i kode

en NIB og en NIB er stort set den samme ting – de indeholder layoutoplysninger. En NIB har et binært format, mens en NIB har et binært format. Det er derfor, Uikits funktioner altid taler om en “nib”, mens kode altid kalder det en “nib”.

kodning af Tabelvisningskontrollerens datakilde

nu hvor din tabelvisningskontroller er oprettet, lad os bringe den til live! I dette kapitel fokuserer vi på de forskellige funktioner, du skal implementere for at få din tabelvisningscontroller til at fungere.

som forklaret tidligere hører disse funktioner enten til tabelvisningscontrollerens delegeret eller tabelvisningscontrollerens datakilde. Begge disse protokoller bruger delegation til at tilpasse tabelvisningen.

de vigtigste funktioner for UITableViewDataSource er:

  • numberOfSections(in:)
  • tableView(_:numberOfRowsInSection:)
  • tableView(_:cellForRowAt:)

andre relevante funktioner for UITableViewDelegate er:

  • tableView(_:didSelectRowAt:)
  • tableView(_:willDisplay:for:)

du kan finde flere funktioner i Apple-udviklerdokumentationen til Uitableviedelegate og Uitableviedatasource.

tilføjelse af kontaktdata

du skal starte med at tilføje kontaktoplysningerne for tabelvisningscontrolleren. Tilføj følgende egenskab til ContactsTableViewController klassen:

let contacts:] = , , , , , , , , , , , , , , , , ]

det er en rollodeks, vi alle gerne vil have, ikke? Sådan fungerer det:

  • let contacts erklærer en konstant med navn contacts. Du har tilføjet det som en egenskab til klassen, så hver klasseinstans har adgang til denne konstant i hele klassens kode.
  • typen af contacts er ], som er array af arrays af strenge. Du opretter i det væsentlige et array, hvoraf elementerne er arrays af strenge. (Et variabelnavn og dets type er adskilt med et kolon :)
  • koden = tildeler et array bogstaveligt til contacts, udfyldt med navne og telefonnumre på nogle få milliardærer.

på et senere tidspunkt kan vi bruge antallet af elementer i arrayet med contacts.count. Og vi kan få individuelle navne og telefonnumre med contacts og contacts, ved hjælp af subscript syntaks.

registrering af en tabelvisning Celleklasse

før du kan bruge celler i en tabelvisning controller, skal du registrere dem med tabelvisningen. Du kan gøre det på to måder:

  1. ved at angive en tabelvisningscelleklasse og en identifikator
  2. ved at angive en tabelvisningscelle og en identifikator

når du bruger en brugerdefineret tabelvisningscelle, vil du sandsynligvis registrere en celle til det. Når du bruger standardtabelvisningscellerne eller en anden programmatisk celle, registrerer du klassen. Vi bruger klassen, indtil videre!

tilføj følgende kode til viewDidLoad() – funktionen:

tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")

sørg for at tilføje det under linjen super.viewDidLoad(). Som du sikkert ved, er funktionen viewDidLoad() en del af visningskontrollerens livscyklus og tilhører klassen UIViewController.

du tilsidesætter funktionen viewDidLoad() for at svare på denne begivenhed i en visningscontrollers livscyklus, så du kan konfigurere din visning, når den er indlæst. I vores tilfælde bruger vi funktionen til at registrere tabelvisningscellen.

når du registrerer en tabelvisningscelle, skal du også angive en identifikator. Dette er simpelthen for at forbinde klassen af cellen med et navn, du kan bruge senere, når du afkører cellen i tableView(_:cellForRowAt:).

er du stadig med mig? Lad os komme videre!

implementering af “numberOfSections(in:)”

den første delegerede funktion, vi skal implementere, er numberOfSections(in:).

en tabelvisning kan have flere sektioner eller grupper. Hver gruppe har en overskrift, der flyder oven på den lodrette række af celler. I en Kontaktapp kan du gruppere kontakter alfabetisk. Dette gøres faktisk i appen Kontakter på iPhone, hvor kontakter er grupperet A-Å.

den app, vi bygger, har kun et afsnit. Tilføj følgende funktion til klassen:

override func numberOfSections(in tableView: UITableView) -> Int{ return 1}

simpelt, ikke? Funktionen returnerer 1, når den kaldes.

implementering af “tabelvisning(_:nummerfrøinsektion:)”

en lignende funktion er tableView(_:numberOfRowsInSection:). I stedet for at angive antallet af sektioner, giver det antallet af rækker i en sektion. Da en tabelvisning viser celler på en lodret liste, svarer hver celle til en række i tabelvisningen.

den app, vi bygger, har kun et afsnit, og det ene afsnit har et antal elementer svarende til antallet af elementer i contacts arrayet. Det er contacts.count!

tilføj følgende funktion til klassen:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return contacts.count}

se hvordan det virker? Vi vender tilbage contacts.count. Hvis du skulle tilføje et andet navn og telefonnummer til contacts, ville det også dukke op pænt i tabelvisningen.

forståelse af rækker og sektioner

vores kontakter-app er endimensionel, den viser bare en liste med navne og telefonnumre, og den bruger ikke grupper. Men hvad nu hvis du har en grupperet tabelvisning?

i de fleste tilfælde vil din datakilde, ligesom contacts array, også være multidimensionel. Du vil organisere grupper på første niveau og individuelle elementer på andet niveau, “under” grupperne.

- Countries - A - Afghanistan - Albania - ... - B - Bahamas - Bahrain - ... - C - Cambodia - Cameroon - ...

antallet af grupper er lig med countries.count, og antallet af lande i en enkelt gruppe er lig med countries.count, hvor x er sektionsindekset. Dette sektionsindeks er angivet som en parameter i tableView(_:numberOfRowsInSection:).

har du bemærket, hvordan disse to funktioner har en parameter kaldet tableView? Det er en del af det objektorienterede Programmeringsprincip. Du kan teknisk set bruge en tabelvisningsdatakilde og delegere til at tilpasse flere tabelvisninger. Du kan bruge tableView til at identificere, hvilken tabelvisning du arbejder med.

Forestil dig, at du har en Kontaktapp, der kan vise telefonnumre efter navn eller telefonnumre organiseret efter firma. Du kan implementere det på flere måder, for eksempel ved at genbruge dine tabelvisningskontrollere. Eller hvad hvis du vil genbruge layoutet på din Kontakter-app til at vise lignende oplysninger, som restauranter, spillesteder eller Skype-brugernavne? Det er her kode genbrug med OOP kommer ind!

tilvejebringelse af celler til Tabelvisningskontrolleren

vi kommer derhen! Lad os gå videre til den vigtigste funktion af en tabelvisningskontroller: tableView(_:cellForRowAt:).

vi implementerer funktionen, før vi dykker ned i detaljerne, men der er et par ting, du skal forstå om det:

  • når det hedder
  • hvad en indekssti er
  • hvordan den genbruger celler

Tilføj først følgende funktion til klassen ContactsTableViewController :

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{}

Sådan fungerer det:

  • funktionen tilsidesætter dens superklasse implementering fra UITableViewController. Nu ved du, hvordan det fungerer, højre? Vi tilsidesætter standardimplementeringen og erstatter vores egen. Det skyldes, at UITableViewController allerede har implementeret delegeret til tabelvisning og datakilde for os.
  • som før har funktionen en parameter tableView, som vi kan bruge til at identificere den tabelvisning, som denne funktion kaldes til.
  • en anden parameter er indexPath, med argumentetiket cellForRowAt. Indeksstien identificerer cellens row og section indekser. Mere om det senere.
  • funktionen returtype er UITableViewCell. Det er interessant. Denne funktion kaldes af tabelvisningscontrolleren, hver gang vi har brug for at give en tabelvisningscelle!

når du ruller gennem kontakterne i denne app, kaldes funktionen tableView(_:cellForRowAt:) hver gang en celle skal vises på skærmen. Hver gang! Jeg vil bevise det for dig om et øjeblik.

næste op, lad os skrive funktionen krop. Tilføj følgende kode inde i funktionen:

let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath)print("\(#function) --- section = \(indexPath.section), row = \(indexPath.row)")cell.textLabel?.text = contactsreturn cell

her er hvad der sker:

  • først dekøer vi en celle med en identifikator. Det er nøjagtig den samme identifikator, vi brugte før, da vi registrerede cellen. På den måde ved tabelvisningen, hvilken type celle vi ønsker. Den afkøede celle er tildelt cell konstanten. Nu har vi en tabelvisningscelle at arbejde med. Mere om afkørsel senere.
  • derefter udskriver vi nogle oplysninger til konsollen. Dette er så vi kan se, hvornår denne funktion kaldes, når appen kører.
  • derefter tildeler vi navnet på kontakten til tekstetiketten i denne tabelvisningscelle. contacts indeholder værdien af navnet på kontakten, som vi kommer til ved at bruge indexPath.row. Hver forekomst af UITableViewCell har en egenskab textLabel af UILabel, og hver etiket af den type har en egenskab text. Du bruger den til at indstille teksten på etiketten.

bare rolig, vi gennemgår hver af disse ting mere detaljeret. Se først, om du kan køre din app. Kan du se kontaktnavne? Kan du se debug output i konsollen? Prøv at rulle app!

tabelvisning controller rækker

hvornår kaldes “tabelvisning(_:celleforvævning:)”?

hvis du kørte appen Kontakter og spillede rundt med at rulle op og ned, kan du ikke undgå at bemærke, at hver gang du ruller, vises debug output i konsollen.

hver gang en celle, der ikke var på skærmen før, vises, kaldes funktionen tableView(_:cellForRowAt:), og en ny linje vises i konsollen.

så hvornår hedder tableView(_:cellForRowAt:)? Hver gang en tabel visning celle skal vises på skærmen!

tabelvisningskontrolleren har bestemt, at der er behov for en celle, så den kalder tableView(_:cellForRowAt:). Vores implementering af denne funktion dekoder en celle, ændrer den og giver den tilbage til tabelvisningscontrolleren. Tabelvisningscontrolleren og UIKit-rammen gengiver den derefter Grafisk på skærmen.

Hvad er et indeks sti?

hver gang tabelvisningskontrolleren har brug for en celle fra tableView(_:cellForRowAt:), giver den en indekssti som et argument for funktionen. I funktionskroppen kan du bruge parameteren indexPath til at vide nøjagtigt, hvilken celle tabelvisningscontrolleren har brug for.

en indekssti er som en adresse eller en koordinat i et gitter. En typisk graf har en h-akse og en Y-akse, så du kan udtrykke en koordinat i den graf som x, y som 0, 1 og 42, 3. På samme måde har et regneark rækker og kolonner med indekser.

en tabelvisning bruger sektioner og rækker. Som diskuteret før kan du bruge sektioner til at gruppere celler sammen. Vores app har kun et afsnit, og det har contacts.count rækker. Rækkerne i tabelvisningen løber fra top til bund.

sagt anderledes: sektionerne og rækkerne i en tabelvisning er, hvad kolonner og rækker er til et regneark. En indekssti definerer en placering i tabelvisningen ved hjælp af en række og en sektion.

rækkerne og sektionerne er repræsenteret af tal, kaldet indekser. Disse indekser starter ved nul, så den første række og sektion vil have indeksnummer 0.

når du ser tilbage på det forrige skærmbillede, giver det meget mere mening. Den første celle har indeks sti 0, 0, den anden celle 0, 1, fortsætter op til den sidste synlige celle med indeks sti 0, 11.

tabelvisningen Genbrugsmekanisme

det mest bemærkelsesværdige ved tabelvisningen er dens mekanisme til cellegenbrug. Det er faktisk ret simpelt.

  • hver gang en tabelvisningskontroller skal vise en celle på skærmen, kaldes funktionen tableView(_:cellForRowAt:), som vi har diskuteret før.
  • i stedet for at oprette en ny tabelvisningscelle, hver gang denne funktion kaldes, vælger den en tidligere oprettet celle fra en kø.
  • cellen nulstilles til en tom tilstand, rydder dens udseende, og cellen tilpasses igen i tableView(_:cellForRowAt:).
  • når en celle rulles uden for skærmen, ødelægges den ikke. Det føjes til køen og venter på at blive genbrugt.

det er ret klogt, ikke? I stedet for at oprette og slette celler genbruger du dem simpelthen. Men … hvorfor?

det er meget mindre hukommelseskrævende at genbruge celler. Tabelvisningskontrolleren skriver konstant til hukommelsen, når du opretter og sletter celler. Styring af hukommelsen ville også være mere intensiv. Når celler genbruges, bruges hukommelsen mere effektivt, og der kræves mindre hukommelsesoperationer.

itt er også lidt mindre CPU-intensiv til at genbruge celler i stedet for at oprette og slette dem, fordi der simpelthen er mindre operationer involveret i genbrug sammenlignet med at oprette og slette celler.

når du hurtigt ruller gennem en tabelvisning, ser du ikke nye celler – du ser de samme celler igen og igen med nye oplysninger.

koden involveret i cellegenbrug er dette:

let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath)

funktionen dequeueReusableCell(withIdentifier:) forsøger at afkø en celle. Når ingen celler er i køen, vil det skabe en celle for os. Identifikatoren bruges til at holde hver type celle i deres egen kø, og for at sikre, at den korrekte klasse bruges til at oprette nye celler.

Lær, hvordan du opbygger iOS-apps

kom i gang med iOS 14 og hurtig 5

Tilmeld dig mit iOS-udviklingskursus, og lær, hvordan du opbygger fantastiske iOS 14-apps med hurtig 5 og kode 12.

svar på brugerinteraktion

en ting mangler i vores tabelvisningskontroller: muligheden for at ringe til folk på vores kontaktliste! Men inden vi gør det, lad os sørge for, at du også kan se en kontakts telefonnummer i tabelvisningscontrolleren.

standardklassen UITableViewCell har 4 forskellige typer, som udtrykt i UITableViewCellStyle tællingen. Du kan vælge mellem:

  • .default – en enkel visning med en linje med sort tekst
  • .value1 – en simpel visning med en linje med sort tekst til venstre og en lille blå etiket til højre (bruges i appen Indstillinger)
  • .value2 – en simpel visning med en linje med sort tekst til højre og en lille blå etiket til venstre (bruges i appen Kontakter)
  • .subtitle – en enkel visning med en linje med sort tekst og en mindre linje med grå tekst under den

de fleste udviklere bruger brugerdefinerede tabelvisningsceller i disse dage, så du kan ikke se disse celletyper så ofte. Men de er der!

vi skal justere koden lidt i tableView(_:cellForRowAt:). Udskift den første linje i funktionen med følgende kode:

var cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")if cell == nil{ cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellIdentifier")}

hvis du ser nøje, vil du se, at vi har fjernet for: indexPath – delen af dequeueReusableCell(...) – opkaldet. I stedet returnerer denne funktion nu en valgfri. Når den ikke kan afkø en celle, returnerer funktionen nil.

vi hopper derefter i os selv for at oprette cellen, hvis den er nil. Du ser det i anden del af koden. Du bruger en betinget if sætning til at kontrollere, om cell er lig med nil, og hvis det er sandt, opretter du cellen ved hjælp af UITableViewCell(style:reuseIdentifier:) initialisatoren.

denne initialisator får to argumenter, cellestilen .subtitle og den identifikator, vi brugte tidligere.

på dette tidspunkt har vi et problem, fordi cell er en valgfri nu! Dens type er UITableViewCell?, men funktionen returtype kræver, at vi returnerer en forekomst med ikke-valgfri type UITableViewCell.

heldigvis er dette et af de tilfælde, hvor vi sikkert kan bruge kraftudpakning til at pakke den valgfri værdi ud. På grund af den måde, vores kode er skrevet på, er det umuligt for cell at være nil ud over det betingede. Du kan garantere, at cell ikke er nil efter if – erklæringen.

sørg for at opdatere funktionen til at bruge kraftudpakning til cell. Tilføj også følgende kodelinje under cell!.textLabel ... for at indstille underteksten til cellen Vis telefonnummeret til kontakten.

cell!.detailTextLabel?.text = contacts

hele funktionen ser nu sådan ud:

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!}

endelig skal du sørge for at fjerne følgende linje fra viewDidLoad(). Det forhindrer tabelvisningen i at initialisere celler med den forkerte type.

tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")

mægtig fint! Kør din app med Command + R eller Play-knappen, og kontroller, om den fungerer. Kan du se navne og telefonnumre? Godt!

lad os derefter tilføje den brugerinteraktionsfunktion til PI kristice-de-R-kristianistance. Nu hvor du har lært indviklingen i tabelvisningskontrolleren, tror jeg, du allerede ved, hvordan denne næste funktion fungerer.

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){ if let url = URL(string: "tel://" + contacts) { UIApplication.shared.open(url) }}

igen tilsidesætter vi standardimplementeringen af funktionen tableView(_:didSelectRowAt:). Denne funktion kaldes, når en bruger trykker på cellen i en tabelvisning, og den hører til UITableViewDelegate – protokollen. Ligesom de andre funktioner er det angivet indeksbanen for den celle, der tappes.

i funktionskroppen opretter vi simpelthen en tel:// URL fra telefonnummeret. Vi beder derefter appen om at åbne den URL, som effektivt beder iOS om at starte et opkald til dette nummer. Denne kode er kun der til illustrative formål. Bemærk, at dette ikke virker på iPhone Simulator, og at tallene i vores app er falske. (Alligevel vil du bruge denne kode, hvis du laver en rigtig Kontaktapp!)

du kan tilføje følgende kode til funktionen, hvis du vil kontrollere, om den fungerer OK.

print("\(#function) --- Calling: \(contacts)")

dette udskriver en fejlsøgningsmeddelelse, når du trykker på cellen i tabelvisningen.

yderligere læsning

og det er alt der er til det! Det har været noget af en tur, men nu ved du, hvordan en tabelvisningskontroller fungerer.