Programutvikling for Mac OS X, del 2 - Interface Builder

Forrige gang installerte vi XCode, og kikket på litt enkel C-kode, i dette avsnittet, skal vi se på Interface Builder, og lage et enkelt GUI-program. Her er del 2 av utviklingsguiden.

(Har du ikke lest Del 1 ennå, anbefales det på det sterkeste før du starter på del 2)

Så, hvordan lager man et enkelt program som er mer enn teksten vi lærte oss å jobbe med sist? Hvordan får vi vinduer på skjermen? Vel, i god mac-ånd, skal vi dra dem på plass, og skrive ca 8 linjer kode denne gangen.

Vi kommer til å hoppe glatt over den inngående forklaringen av en del underliggende konsepter denne gangen, for å komme tilbake til dette senere, jeg HÅPER at det fortsatt er mulig å forstå grunnleggende Interface Builder-bruk.

Det vi skal lage, er et HELT enkelt program som lar deg kopiere tekst fra et tekstfelt til et annet, ved hjelp av noen knapper. I løpet av dette, får vi sett hvordan man kobler knapper til handlinger (actions), og tekstfelt til datakilder (outlets). Helt til slutt kommer jeg tilbake til nettopp hva som har skjedd i klikkeløypa vår.
Vi setter i gang:
Først av alt, åpne XCode, start et nytt prosjekt, og velg: "Cocoa Application":

Gi prosjektet et navn, trykk Save, og få opp prosjektvinduet. Her skal du finne MainMenu.xib, og dobbeltklikke på denne for å få opp Interface Builder:

Interface Builder, er verktøyet du kommer til å designe brukergrensesnittet ditt i, akkurat nå sitter vi med et blankt vindu:

La oss legge til et tekstfelt. Se til venstre på skjermen, der skal du finne "Library"-vinduet, nederst i dette kan du skrive "TextF"

Velg TextField, og dra 2 slike til vinduet vårt:

Legg merke til de blå hjelpelinjene som dukker opp når du prøver å plassere tekstfeltet, disse hjelper deg å plassere ting på lik høyde, og akseptabel avstand, og forsøker å gjøre det lettere å følge Apples retningslinjer for brukergrensesnitt, ikke kjemp mot dem, la dem hjelpe deg. (Dessverre visste det seg vanskelig å ta bilder av dem)

Så, trenger vi 2 knapper, søk etter Button, og dra inn 2 Push Buttons i vinduet vårt.

Så skal vinduet vårt se noe sånt ut:

Gi knappene en annen tekst ved å dobbeltklikke på dem:

Så, skal vi gjøre den litt tricky biten, nemlig få disse tingene til å kunne gjøre noe. Gå tilbake til Library, velg Classes

Søk opp "Object", velg NSObject, høyreklikk, og velg "New Subclass"

Gi kontroll-klassen vår et navn:

Den skal nå være valgt i listen, i motsatt fal søk den opp ved navnet du ga den, og klikk på den.

I Bildet over står muspekeren over en boks merket "Inheritance", denne skal du velge "outlets" i, og så bruke +-knappen under til å legge til to "outlets" som vist: (Her er det verdt å nevne at jeg burde ha kalt mine outlets for textLeft, og textRight, for å gjøre koden klarere, men men). Sørg for å endre "id" til NSTextField også.

Tilsvarende skal vi velge "Actions" i menyen, og legge til to actions som vist:

Så, drar du objektet fra ruten RETT over Actions-boksen (Der det står IntroController i bildet over), og over i "prosjekt"-vinduet til IB:

Det vi har gjort nå, er å definere noen knagger vi kan hente data og sende handlinger til og fra elementene i vinduet vårt med, objektet vi har laget skal være "limet" mellom vinduet, og koden vår, så før vi får gjort noe fornuftig her, må vi koble sammen objektet med vinduselementene. Høyreklikk på en knapp i vinduet, og dra en linje til objektet vi lagde i sted.

Velg den passende handlingen, og repeter for den andre knappen.

Vinduet forer altså objektet vårt med informasjon FRA knappene (dvs vi får beskjed når de trykkes på), men vinduet må også fores med informasjon FRA objektet, til tekstfeltene våre (denne koblingen er forsåvidt toveis). Men, høyreklikk på objektet, og dra til tekstfeltet:

og velg riktig "knagg".

Da er det på tide å jobbe oss tilbake til XCode, gå til Library-vinduet, finn kontroller-klassen, høyreklikk og velg "Generate Class Files"

Behold standardverdiene her.

Og sett kryss for å legge til filen her. Trykk så Eple-S for å lagre vinduet vi har jobbet med i Interface Builder

I XCode får vi da to nye filer, en header (.h-fil), hvor du kanskje kjenner igjen noen outlets og actions?

og en .m-fil som skal inneholde koden som er koblet til actions-ene våre, som igjen er koblet til knappene i vinduet.

Vi vil at knappene skal kopiere teksten fra venstre til høyre og motsatt, så vi skriver noe simpel Objective-C-kode til formålet, nøyaktig hvordan Objective-C fungerer kommer vi tilbake til i en senere del, men kort fortalt, så leser vi av tekstverdien til "right"-tekstfeltet, i første linje, og setter "str" lik denne. Så setter vi det andre feltets tekstverdi til å bli det "str" er.

Prøver du å kjøre programmet med denne koden, så fungerer det som tenkt, tekst kopieres fra boks til boks.

Men, vi har kanskje lyst til å leke litt med det vi gjorde forrige gang med tall også? Vel, da går vi tilbake til Interface Builder, og gjør vinduet vårt slik:

Så finner vi igjen IntroController-klassen (viktig, å velge Classes i Library) vårt, og legger til noen ekstra actions:

og outlet:

Som du kanskje så tidligere, skal disse matche tekst i .h-fila vår, noe som ikke skjer helt automatisk når vi gjør dette fra Interface Builder (men, andre veien fungerer ganske bra, endringer i .h-fila synes i IB rimelig fort), du må derfor DRA outleten og actions-ene til .h-fila i XCode, på riktig sted:

Lagrer du .h-fila di nå, skal du kunne se at action/outlet-listen i IB, nå lister alt under .h-fila, istedenfor fordelt på .xib/.h, som 2 bilder over.

Gå tilbake til Interface-Builder, og dra koblinger til knapper og tekstfelt, gå så tilbake til XCode, så skal vi få på plass den siste kodebiten her:
Vi vil at knappene våre teller opp og ned, så vi må derfor finne "tall-verdien" av tekstfeltet vårt", og så endre denne, her er koden for minus-knappen: (Den skal før @end)

denne skal inn i .m-fila vår, hvordan pluss-koden skal se ut, er en utfordring til dere.

Oppgave
Nå har vi laget et vindu, som gjør helt enkle ting med knapper og tekstfelt, vi har også sett hvordan vi får tekst til og fra tekstfelt, og kanskje mest interessant, sett hvordan vi kan få, og endre int-verdier i tekstfelt, dette burde åpne for muligheten til å lage forrige dels "gjetteprogram" med et vindu, gjerne med et tekstfelt som forteller deg om gjetningen din er større, mindre, eller korrekt. Jeg anbefaler også å leke litt med Interface-Builder, og se på hva "inspectoren" på høyre side av skjermen, kan gjøre med de forskjellige elementene i vinduet, o.l. Vi kommer til å ta en grundigere titt på denne senere.

Teori
I denne gjennomgangen har vi sett outlets, actions, objekter, og klasser, samt xib-filer, .m-filer, og .h-filer, det er kanskje greit å få en LITEN forklaring på hva alt dette egentlig er. Ikke tenkt så alt for nøye på det, jeg tar det mest med som en oppvarming til objekt-teorien som kommer.

Klasser
En klasse, er et "konsept", eller en "oppskrift", på samme måte som "Bil", "Porsche 911 Turbo" eller "Airbus A400", altså ikke spesifikke "instanser" av de forskjellige "klassene", men mer "definisjonen" av de, et spesifikt "Airbus A400"-fly, ville vært et objekt. Det er kanskje litt utydelig i klikkeløypa vår i dag, men det var KLASSEN "IntroController" vi endret på, men Objektet vi koblet ting til.

Objekter
Er tilfeller, instanser, eller utgaver av en klasse, der "Audi A3" er en klasse, er "Audi A3 med skiltnr AA 12345" et objekt av den klassen, det vi dro ting til og fra i Interface Builder var et slikt objekt, av klassen IntroController.

Outlets/Actions
Når vi skriver kode, som skal forholde seg til et GUI, trenger koden å kunne fore data til GUIet, få data fra GUIet, og også hendelser, GUIet på sin side, trenger å kunne si ifra at ting har skjedd, og få dataene sine fra et sted, derfor foretrekker GUIet å ha elementene sine tilkoblet outlets, og at de har et sted å fyre actions-ene sine, og der slutter egentlig ansvaret til GUIet. Vi må derfor koble GUIet vårt til koden vår gjennom outlets/actions, og behandle det gjennom disse i koden vår.

NIB/XIB
.xib-fila (også kjent som NIB-fila) definerer ett eller flere vinduer for programmet ditt, objektene som hører til de, samt koblingene mellom disse og hva som skal lages av instillinger ved programstart.

.h/.m
Matcher C-verdenens ".C/.H"-filer, og C++'s ".CPP/.H"-filer, .h-fila definerer klassens struktur, mens .m-fila definerer metodene/funksjonenes faktiske innhold. Detajene her kommer vi tilbake til.

Videre, og viktig lesning:
Apples retningslinjer for brukergrensesnitt

Neste gang
Jeg er klar over at dette kan ha vært litt uklart, derfor jobber jeg med å lage en videoversjon av akkurat denne guiden, men av tekniske årsaker så har dette ikke gått helt i mål ennå. Siden vi nå har kikket på verktøyene vi har å jobbe med, er neste steg å å lære oss litt mer C, samt kanskje noe Objektorienterings-teori. Følg med i neste del av guiden.

Oppdatert:Del 3 er nå ute

palelnans bilde

palelnan

Disse artiklene er verdt mange tusen kroner.

Onizuka89

"du må derfor DRA outleten og actions-ene til .h-fila i XCode, på riktig sted"
virker det ikke å trykke på tannhjulet i Library når man er i introController og velge "write updated Class Files", å kjøre enten en merge eller replace da?

EinarJ

Hmm, ja, det burde det vel, det er flere måter å gjøre ting på i IB, og jeg har mine fra IB 1.3 i Panther, og har vel egentlig bare tilpasset disse til IB 2, nå vil jeg allikevel si at rent pedagogisk er det greit å forklare denne måten å gjøre det på, siden man da ser koblingen mellom .h-fila og IB litt klarere.

Men, takk for tipset, det var jeg faktisk ikke klar over.

tacomodo

Dette ble komplisert jævlig fort. Her var det mye black magic.

EinarJ

Det var det jeg fryktet egentlig, idèen var å vise kjapt hvordan man bruker IB, selv om man har en del forutsetninger som bør være på plass først, for å ha luftet en del konsepter, jeg skal prøve å sette brikkene mer på plass i neste del, i en eller annen ende må man starte, og stort sett for å motivere litt, valgte jeg å gå for GUI tidlig.

Onizuka89

det kan være greit å se sammenhengen, men det kan du også se i merge tror jeg, siden du ser forrige utgave av .h fila, og den nye, så du ser hva som har blitt gjort forskjellig, å velge hva du vil ha, og ikke ha. Eneste som virker som et problem med merge er at jeg ikke ser noen mulighet til å lagre den merge'de fila på rett sted automatisk :/

må forresten gratulere med enda en strålende artikkel, er gøy å lære dette her :D

EinarJ

Forøvrig tacomodo: Det jeg skrev ble vel kanskje litt kjapt selvforsvar når jeg leser over det nå, det var ikke meningen, jeg setter pris på tilbakemeldingen, det hjelper veldig å få høre at det ikke var helt klart, så jeg kan ta det med i betraktningen når jeg lager neste del, og dermed få forklart det som var uklart.

Missy TommeN

Jeg gler meg til å begynne på dette om noen år :D nå skal jeg først lære meg PHP+MySQL. (Etter mer avansert HTML+CSS)

steffenz

Jeg har sittet her hver eneste dag og klikket oppdater i håp om denne artikkelen. Noe lettfattelig for iallefall å få en SMULE begrep om hva jeg holder på med. Denne artikkelen er gull verdt, meget meget bra.

Tips til forfatteren - Det er mangel på slik fakta på norsk, en bok hadde nok solgt i hauger og lass.

Supert iallefall, tusen hjertelig takk :)

theC

Flott! Keep it up :)

eeerlend

Hei! Super guide!

Jeg har et par spørsmål. Jeg prøver å lage den "gjettefunksjonen" vi lagde i kommandolinjen forrige gang. Men jeg sliter med å sette variabler:

int felt = 4; // Denne går bra
str tekststreng = "Blablabla"; // Min logikk sier noe sånt:p Men det fungerer ikke.

Altså hvordan lagre en tekststreng i en variabel?

EDIT: Jeg vet ikke om jeg har løst det riktig, men det fungerte i allefall:)

- (IBAction)guess:(id)sender {
   int svar = 25;
   int num = [guessField intValue];
   if (num == svar) {
      NSString* str = @"Helt Riktig!";
      [answerField setStringValue:str];
   }
}

tacomodo

Selv om jeg sa det ble komplisert fryktelig fort så setter jeg stor pris på disse guidene og jeg gleder meg til å følge, hva jeg håper blir, en lang serie av disse delene!

EinarJ

eeerlend: Å sette strenger i Objective-C, gjøres på formen @"Blablabla", alfakrøllen foran er viktig, på grunn av noe kollisjon med hvordan slikt fungerer i gammeldags C.

Det må jeg forøvrig huske på å dra med i en forklaring ja.

hammond

Dette var virkelig bra. Men hva med noe tilsvarende for ophone apps?

EinarJ

Vel, et sted må man starte, og det meste som gjennomgås her med det første vil være rimelig relevant for iPhone også.

Larsaronen

@eeerlend:

Det er heller ingen klasse som heter str.

Siden Obj-C er ett supersett av C, kan du deklarere en klassisk c sring (klasse char) slik:

char *tekstreng = "Blablabla";
eller alternativt slik:
char tekstreng[] = "Blablabla";

Men en Objective-C string er av klasse NSString og deklareres slik:

NSString *tekstreng = @"Blablabla";

eeerlend

takker for hjelp!

Jeg ser frem til neste del. Til nå har jeg kommet så langt jeg pleier å komme hver gang jeg prøver å lære meg dette:p For å lage noe nyttig, må jeg enten kunne koble meg til datakilder i form av f.eks database, enten lokalt eller på en webserver, da det er det jeg er vant til fra webutvikling... Men jeg får vel bare smøre meg med tolmodighet, og håpe at det er noe som kommer til å bli gjennomgått:)

Et spørsmål, hvordan kan man enkelt sette inn et bilde fra harddisken i IB'en?

iAndrews bilde

iAndrew

Gleder meg til å følge både del 1 og del 2 når eksamensperioden er over for i år : )

ggt667s bilde

ggt667

Mye fint her, mulig vi kan lage en "innføring" til slutt? En slags fuskelapp for programmering i obj-c til iPad.

Larsaronen

@eeerlend:

Sett in ett NSImageView..

ggt667s bilde

ggt667

Finnes en NSWebKitViewer? For å få en lokal "safari"-viewer?

HenrikWLs bilde

HenrikWL

Veldig bra, EinarJ!

Jeg er programmerer av yrke, men har ikke drevet mye med hverken Obj-C eller XCode, så til og med jeg drar nytte av denne typen nybegynner-guider. :) Ser dog at det er en del generelle grunnprinsipper om programmering her som forbigås og antas kjent, men sånn må det vel nesten bli hvis du skal unngå at det blir en hel bok av dette her.

Jeg ser at du i del 1 lenker videre til anbefalt lesning; mulig det kunne gitt merverdi også for denne artikkelen å gjøre det samme.

eeerlend

Sitter nå å leser en bok om Objective-C. Til nå har denne gjort underverker, og er beregnet på oss "nybegynnere" i Objective-C. Jeg ble anbefalt å lese denne boken FØR jeg begynte med Interface Builder og slikt for å først lære meg grunnprinsippene i selve programmeringsspråket. Lettleselig og gode eksempler:)

Kan varmt anbefales til andre nybegynnere i Obj.C:

Programming in Objective-C 2.0 av Stephen G. Kochan

Larsaronen

Jeg slenger meg på eeerlend sin anbefaling.. Var faktisk mitt første steg når jeg lærte programmering..

Når du begynner å få forståelsen anbefaler jeg å gå over til:

[url">http://www.bignerdranch.com/book/cocoa%C2%AE_programming_for_mac%C2%AE_os_x_3rd_edition

Og eller er det masse god info på developer.apple.com

@ggt667:
[url">http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/WebKit/Classes/WebView_Class/Reference/Reference.html

EinarJ

Jeg innrømmer at jeg vipper litt begge veier mtp rekkefølgen jeg har staket ut for guiden, litt av poenget er å holde interessen oppe, noe en grundig teoretisk innføring før man får gjort noe nok ikke er så egnet for.

Litt av idèen her, er å kunne bruke eksempler, og jobbe seg delvis bakover i teorien, altså, introdusere konsepter etterhvert som vi får behov for dem i eksempler. Alternativet er å gjennomgå OO-teori og C grundig først, noe som forsåvidt er gjort ganske mange steder allerede (men langt færre steder på norsk).

Ellers så vil det måtte bli en del pedagogiske løgner, eller i det minste forenklinger her og der, siden jeg ellers vil måtte skrive en bok, som det har blitt sagt. Jeg prøver allikevel å ha et halvt øye åpent for å unngå å sette ut noen store feller.

Klart, hvis interessen holder seg, så kommer vi etterhvert til å gå igjennom ganske mye, men det har aldri vært meningen at guiden skal erstatte en god bok, eller et godt kurs. Personlig vil jeg forøvrig anbefale Hillegras' bok.

ggt667: Hmm, ja, det mener jeg, sist jeg tok i NSWebKit var vel i IB1.3, da kunne man mer eller mindre lage en enkel Safari-klone på 5-6 minutter.

eeerlend: Som jeg skriver over, har jeg valgt å gå for litt mer "getting your feet wet first"-teorien. Personlig lærer jeg ting bedre hvis jeg har en vag idè om hvorfor det er relevant, men jeg er ingen pedagog, så jeg kan ikke garantere for at den approachen fungerer for andre, så feedback er gull.

Henrik989

Vet noen hvorfor xcode ikke vil lastes ned fra devcenter?
Har prøvd 100 ganger nå. Den stopper bare..

mjeje

lærerikt og bra for en nysgjerrig uviten kar. bra jobba! gleder meg til neste del :)

eeerlend

Er det flere enn meg som mener at denne gudien kanskje også burde legges ut på dev1.no? Er synd at det på dev1 er lite artikler:)

kimmey2k3

Veldig bra skrevet! Håper på mer ASAP! =)

EinarJ

Det har vært, og er, eksamensperiode for tiden, så jeg har ikke fått tid til å fullføre Del 3 ennå, og jeg tørr egentlig ikke love noe tidspunkt for den på stående fot. Men, den kommer.

snippet

Veldig bra at du tar deg tid til å lage dette. Venter på fortsettelsen.

MacBjorn

Ahhh. Blir nødt til å krype til korset her...
Jeg får ikke opp det tomme IB vinduet når jeg dobbelttrykker på MainMenu.xib

Vinduet blir "grått" etter dobbeltklikking, som om et annet vindu er aktivt, men det kommer ikke opp noe nytt IB vindu.

Jeg finner heller ikke ut hvordan dette kan åpnes via "høyreklikking" - åpne som... osv..

Tips?

MacBjorn

Fant det ut. Måtte finne IB og starte den separat. Aner ikke hvorfor den ikke åpnet seg automatisk på dobbeltklikking. Good to Go...

EinarJ

Da er del 3 ute.

NorthPlayer

Hei!

Har litt problemer med en ting, den vil ikke koble sammen actions til Minus og Pluss knappene. Det når jeg trykker høyreklikker på IntroControllen og drar den bort til Minus og Pluss vil den liksom ikke!

Noen som har en ide?

NP

EinarJ

motsatt mener du vel, du klikker på knappene og drar til kontrolleren?

martmort

Mulig det bare er jeg som har dette problemet (mest sannsynlig fordi jeg gjør dette på en mac jeg har stående hjemme via fjernstyring) men når jeg høyreklikker på en av knappene (holder inn høyreklikken) og drar opp til Intro Controller får jeg ikke opp en blå strek.

Når jeg slipper musetasten over IntroController kommer det opp et gråsvart vindu "Window (cocota-test)" (som er prosjektnavnet mitt).

Der har jeg en liste over Outlets og Received Actions osv.

Jeg kan dra en blå strek fra en av de sirklende i denne listen til hva jeg vil. Noen klarer å havne på Intro Controller, noen ikke.

Da jeg ikke klarer å få streken bare ved å dra en høyreklikk fra knappen antar jeg at det er en av disse sirklene i listen jeg skal dra til Intro Controller. Prøvde med et par forskjellige som virket logisk, men da vil desverre ikke kopieringen skje senere i guiden, ved første test.

Noen idéer?

ggt667s bilde

ggt667

Kanskje litt feil tråd å ta opp dette i? Du sier ikke hvilken fjernstyringsmekanisme du bruker.

Kan admin flytte denne posten, posten med spørsmålet i til en ny tråd?

martmort

Jeg føler egentlig spørsmålet er direkte relatert til guiden og lurer egentlig bare hva man faktisk gjør når man "limer" objektet med koden..

EinarJ

Rimelig sikker på at høyreklikket ditt registreres utelukkende på vinduet, og det er dette vinduets connectionlist du får opp.

ggt667s bilde

ggt667

Det kommer vel helt an på hvilken fjernstyringsmekanisme som benyttes?
RDCP? X11? VNC? ARD?

Ma3

Åpner nytt prosjekt med Cocoa Application som vist.
Finner MainMenu.xib, men får då opp et vindu med masse valg.
Blant disse mulighetene finner eg "window", som er et tomt vindu som vist over.
Tolka dette som det vinduet du viser i forklaringa.
MEN; kan ikkje finne "library". Såg "MacBjorn" hadde et lignende problem, men eg klarte ikkje å finne samme løsning. Har du nokken ideer om kva eg skal gjere?

Ellers er det fantastisk at du lager sånne artikler! :D

  • Skriv ut artikkel
  • Abonner med RSS

Alt om iPad, iPhone og iOS

Nettradio i iTunes

Nettradio i iTunes
130 norske radiokanaler.
Få de mest populære norske, svenske og danske radiokanalene inn i en egen spilleliste i iTunes.
Oppdatert 13. mai