Pelkoa ja inhoa kehitysympäristössä

Applella on valtava ja periaatteessa ihan ihmisystävälliseen sävyyn laadittu perehdytysaineisto iPhonen ohjelmistokehitykseen täällä. Lataamassani Developer-kansiossa näyttää olevan muunmuassa ohjelma nimeltä Interface Builder, jolla pystyy tekemään ihan oikean iPhone-softan näköisiä dummynäkymiä pelkästään raahailemalla navigointielementtejä paikasta toiseen. Xcode, Applen softaprojektien hallintaohjelma ja lähdekoodieditori näyttäisi ihan järkevältä. Dev Centerissä on ladattavissa hyvin dokumentoituja esimerkkiohjelmia melkein aiheesta kuin aiheesta. Jotenkin punainen lanka ei vaan löydy – kokonaiskuva Cocoa-ohjelmoinnista vilkkuu koko ajan jossakin näkökentän rajoilla mutta katoaa aina kun siihen yrittää kohdistaa katsetta.

Otetaan nyt vaikka ”Hello World” – klassinen ohjelmanpätkä, jonka olemassaolon ainoa tarkoitus on julistaa: ”Hei! Ohjelmointi on helppoa ja kivaa, ala sinäkin harrastamaan ohjelmointia!”.

Kuusnelosella naputeltiin:

10 PRINT "HELLO WORLD!"

C:llä jotain tyyliin:

int main() {printf ("Hello World");}

Ai niin, enpä muuten ole vielä kertaakaan maininnut Cocoan bestistä, siis varsinaista kieltä, jolla iPhone-ympäristössä pääasiassa koodataan. Se on Objective-C, monenlaisilla herkuilla kuorrutettu C++ -kieli.

iPhonen Hello World -applikaatio löytyy valmiina iOS Developer Libraryn Sample Code-osiosta, kätevää! Avataas… AAAARGH! Äkkiseltään laskettuna 22 eri tiedostoa, jotta ruutuun saa kirjoitettua tervehdyksen. Okei, on siinä planeetan kuva taustalla, tekstikenttä, johon saa kirjoittaa itse ja label, jossa valmis tervehdys näytetään. Alkujärkytyksen jälkeen helpottaa hieman – suurin osa tiedostoista näyttääkin olevan melko vakiomuotoisia kuvaketiedostoja, ohjelman speksiluetteloita ja muuta peruskauraa. Varsinainen toiminta näyttäisi olevan näissä ”.h” ja ”.m” -päätteisissä tiedostoissa… siis ”header” ja ”method”, kaiketi.

Kuva 3.0. Hello World -projektikansio avattuna Xcodella

Kuva 3.1. Kirjoittaja tutkimassa Hello World -sovelluksen lähdekoodia

Avaan tutuimmalta kuulostavan tiedoston eli ”main.m”: vesiperä. Siellä on vain muutama rivi koodia, joka näyttää liittyvän jotenkin muistinhallintaan, ja palautusarvona (kenelle? Steve Jobsille?) annetaan UIApplicationMain-niminen olio – eli ohjelma itse, tai ainakin joku haamu siitä? Hämärää, mutta Dev Centerin tutoriaalit vahvistavat: main-metodin muokkaaminen ei ole iPhone-hommissa se juttu. Jätän ymmärtämisen tuonnemmaksi ja yritän nyt vain etsiä sitä hemmetin ”Hello Worldia”.

Siispä seuraavien kandidaattien kimppuun: MyViewController.h ja .m. ”Näkymänhallintaa”, se kuulostaa oikealta. Avaan ensin header-tiedoston, sillä sieltähän saa nopeasti selkeän yleiskuvan, mistä on kysymys, eikös vaan?

Hmmm… skipataan alun lakitekstit. Aluksi importoidaan UIKit – sopii minulle, käyttöliittymä on ihan hyvä juttu. Sitten tehdään @interface-määrittely, jossa on tuttuja asioita (string), loogisen oloisia asioita (UITextField *textField) ja sitten ihan taikasienikamaa (<UITextFieldDelegate>, IBOutlet). Seuraavaksi määritellään kaikki uudestaan, mutta @property -tagien avustuksella, joita muuten täsmennetään vielä mm. termillä ”nonatomic” – epäatominen? Niinpä tietysti… puuh… onneksi lopussa ennen @end-määrittelyä on vielä yksi tutunnäköinen elementti:  – (void)updateString; – sehän on ihan selvästi funktio! Ei kun siis metodi, sori kaikille, olen uusi täällä.

MyViewController.m-tiedostossa pitäisi kaiken järjen mukaan vihdoin päästä moikkaamaan sitä maapalloa. Katsotaas… importoidaan headeri, käy järkeen, sitten tulee toteutusosio eli @implementation. Sitten jotakin @synthesize-tageja joilla viitataan headerista tuttuihin muuttujiin (vai instanssejako nuo nyt sitten olivat). Ei mitään käsitystä mitä tuo @property -> @synthesize tekee, mutta jonkunsortin parivaljakko se kuitenkin lienee.

Sitten se metodi. Mutta täällähän lukee ekana ”- (void) viewDidLoad {”… eihän tällaista määritelty headerissa. No, joka tapauksessa tätä metodia on nimestä päätellen tarkoitus käyttää heti näkymän ladattua – jonkinlainen alustusmetodi siis. Pitääpä katsoa koodia eteenpäin, niin nähdään missä tätä metodia kutsutaan, eikös vaan? (Te oikeat Cocoa-kehittäjät siellä, pidetään se naama ihan vaan peruslukemilla).

Sitten on määritelty se updateString-metodi, helppo nakki: stringiin tallennetaan tekstikentän sisältö ja labeliin sitten stringin sisältö. Sitten joku virtuaalinäppikseen liittyvä säätö ja sitten jotain hyvin mielenkiintoista:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{...

Tämä selvästi liittyy kosketusnäytön tarkkailuun. Metodista löytyi kuitenkin vain kolme riviä koodia, jotka eivät tunnu liittyvän sen enempää touches- kuin event-olioonkaan. Tällä kuulemma piilotetaan virtuaalinäppis, kun käyttäjä koskettaa tekstikentän ulkopuolista näyttöpintaa: [textField resignFirstResponder]; Selvä, uskotaan. Sitten perutaan tekstikentän sisältö näin:  textField.text = self.string; Ihan järkeenkäypää. Sitten on vielä kolmas rivi, jota ei selitetä mitenkään eikä myöskään avaudu millään tasolla. [super touchesBegan:touches withEvent:event]; Esimiehelle tässä varmaan soitellaan, mutta millä asialla, miksi, ja kuka se on – beats me.

No niin, kohta varmaan päästään varsinaiseen pääkoodiin, siis siihen main looppiin, josta kaikkia näitä hienoja metodeja kutsutaan yksi toisensa perään ja sitten aloitetaan alusta. Niinhän? Niinhän?

- (void)dealloc {
  // muistin hallintaa ja instanssien nollaamista
}

… ja sitten:

@end

Muutaman hyödyttömän skrollausnapin pyöräytyksen jälkeen alistun tosiasioiden edessä. Siinä se oli, enempää ei tule. Ei mitään alkupistettä, ainakaan sellaista jota olisin pystynyt hahmottamaan. Ei mitään main loopia, joka pitäisi homman kasassa. Eihän näistä metodeista suurinta osaa edes kutsuttu missään! Eikä missään lukenut, että ”Hello, World!” Jumalauta, tämä alkaa jo olla vähän liikaa…

Tunnelmat alkavat olla sen verran ankeat, että skipataan suosiolla muutama viikko vimmaista dokumenttien plaraamista ja tutoriaalien copy/paste-tyylillä läpikäyntiä ilman ymmärryksen häivääkään, ja siirrytään suoraan nykyhetkeen. Tässä välissä on nimittäin ehtinyt tapahtua pari oivallusta, jotka ovat vihdoin johtaneet jopa jonkinlaiseen näppituntumaan Cocoa-ympäristöstä.

1. Minä mitään main loopia tartte!

iPhone on puhelin. Kyllä, näin on. Se taas tarkoittaa sitä, että sen täytyy pystyä vastaanottamaan puheluita ja viestejä ja hoitamaan monenlaisia muita askareita myös silloin kun MINUN hieno applikaationi pyörii. Ja se taas tarkoittaa, että se turhaan koodista etsimäni Main Event Loop (toki se on olemassa, ei tässä sentään mitään barbaareja olla) on tietenkin iOS:n hallussa. Tämä taas vaatii takatukka-aikakauden koodarilta ison myönnytyksen: minulla ei ole mitään keinoa tai syytäkään päästä muokkaamaan pääloopia itse – en sitä paitsi halua käräjille siitä, että tuleva hittiapplikaationi estää hätänumeroon soittamisen ja johdattaa koulubussillisen luokkaretkeläisiä surman suuhun.

Mistä siis korvaushoito tähän main loopin himoon? Eventeistä, siis tapahtumista. Kun käyttäjä sipaisee näyttöä, iOS rekisteröi tapahtuman. Kun puhelinta heilutellaan, kiihtyvyyssensori lähettää tästä tiedon ja iOS poimii taas uuden tapahtuman. Kun kuulokkeiden kaukosäätimestä lisätään volaa – tapahtuma. Jos muisti alkaa täyttyä – tapahtuma. Ja itselleni vaikeimmin oivallettava juttu oli tämä: sinun hommasi ei ole tehdä metodia joka tarkkailisi näitä tapahtumia. Sen sijaan iOS kutsuu, tiettyä komentoketjua seuraten, näitä varta vasten tapahtumiin reagointia varten laadittuja, vakiomuotoisesti nimettyjä metodeja. Nämä kutsut päätyvät automaattisesti myös sinun ohjelmallesi, ja sinun tehtäväsi onkin – oman ohjelmasi osalta – kirjoittaa näihin tapahtumiin reagointimetodit uusiksi siltä osin kun ohjelmasi toiminta sitä edellyttää. Siksi esimerkiksi tuota touchesBegan-metodia ei ollut määritelty tuolla MyViewController-headerissa – se on jo määritelty paljon syvemmällä Cocoan ytimessä, UIKit-frameworkin UIResponder-luokassa. Tämä tapa uudelleenmääritellä tiettyjä vakiotyyppisiä metodeja on ymmärtääkseni yleisemmälläkin tasolla erittäin oleellinen osa Cocoa-filosofiaa.

Mutta yksi perustarve on vielä tyydyttämättä. Kun pitäisi päästä tekemään jotain jokaisella main loopin kierroksella, vaikkapa laskemaan avaruusaluksen uusi sijainti tai laavalampun uudet värit. Tämä ei ymmärtääkseni ole mahdollista, ainakaan jailbreikkaamatta iPhoneasi. Eventit rientävät kuitenkin apuun tässäkin asiassa. On nimittäin vielä yksi tärkeä tapahtumatyyppi, jota ei ole käsitelty: ajastintapahtumat. Kaikessa yksinkertaisuudessaan, tehdään jotain aina kun iPhonen sisäinen kello on edennyt vaikka 5 millisekuntia. Tähänkin hommaan on Cocoassa omat valmiiksi pedatut metodinsa, ja niitä kannattaa käyttää.

2. Ihan sama mistä se alkaa!

Se vanhan koulun koodaajalle hirmuisen tärkeä ajatus, että mikä tässä ohjelmassa on se ihka ensimmäinen komento, ei ole Cocoa-ohjelmoinnissa kovin oleellinen. Se main.m se kai lopulta on, sitä iOS ymmärtääkseni kutsuu kun applikaation kuvaketta tupsauttaa, ja se tosiaan palauttaa iOSille applikaatioinstanssin, johon koko softa on kääritty. Mutta sillä tiedolla ei ole kummoistakaan merkitystä toimivan iPhone-ohjelman rakentamisessa. Sitä tärkeämpään asemaan nousee tuo aiemmin mainittu metodien uudelleenmäärittely -toimintatapa. Sillä kun nimittäin pääsee käsiksi kaikennäköisiin muihinkin tärkeisiin hetkiin applikaation elämässä, kuten siihen kun ohjelman eka näkymä on latautunut loppuun (jolloin voisi esimerkiksi alustaa muuttujia).

3. Kaikkea ei tarvitse tehdä itse

iPhone-kehittäjä: et ole Rambo! Sinun ei tarvitse lahdata kaikkia pahiksia yksin. Olet pikemminkin Rusty Robottipoika, jonka tärkein tehtävä on päästä Ison Hepun (iOS) kyytiin – kun pidät tiukasti kiinni etkä ala ryttyilemään isommallesi, olet aika lailla turvassa.

Eli käytännöllisemmin: kun alat suunnittelemaan jotain toiminnallisuutta uuteen softaasi, älä turhaan tuhlaa aikaasi miettimällä, miten tämän asian ratkaisisit – katso sen sijaan ensi töiksesi iOS  Frameworks -listauksesta missä määrin ja miten Cocoa on jo ratkaissut asian, ja miten sitä ratkaisua tulisi jalostaa, jotta käsillä oleva ongelma ratkeaisi.

Valtavasti maastoa on vielä kartoittamatta, mutta nyt ainakin kartta on jo oikeinpäin kädessä. Seuraavaan kertaan!

Kuva 3.3. iPhone-sovelluskehittäjä ja iOS yhteiskuvassa

Kuva 3.2. Selvästikään ei iPhone-kehittäjä

4 Responses to Pelkoa ja inhoa kehitysympäristössä

  1. Jaakko kirjoitti:

    Vastaavat lähtökohdat, check
    Samat ambitiot, check
    Tämähän on ihan helkkarin valaisevaa.

    Aina välillä on käynyt mielessä että tarvitsisin sellaisen ja tällaisen softan puhelimeeni.

    Seuraa ajatusketju:
    löytyykö vastaavaa storesta -> eipä tietenkään
    voisikohan sellaisen toteuttaa itse -> ehkä, jos kävisi läpi tuskallisen prosessin palauttaa mieleen ammoisina aikoina opittuja ja unohdettuja ohjelmointitaitoja ja kävisi pelotta suuren tuntemattoman kimppuun
    kiinnostaisiko se jotain muutakin -> tuskin, mutta eihän sitä koskaan tiedä
    onko asia panostuksen arvoinen -> nääh, tuskinpa
    Ja niin asia on jäänyt.

    Blogin alku valaa uskoa että iOS on opiskeltavissa ”ei niin koodari”-aivoillakin.

    Tänks!

  2. ollyoxalls kirjoitti:

    Jottei pelko tuhoaisi aloittelevien iPhone-kehittäjien sielua, mainittakoon, että konsoliin tulostava ”hello, world” -koodi ei ole paljon C-kielen vastaavaa hankalampi.


    #import
    int main (int argc, const char * argv[]) {
    NSLog(@"Hello, world");
    return 0;
    }

  3. Tiekki kirjoitti:

    Täällä kans yks joka tuskailee, eikun siis näyttii tästä cocoan opettelusta. Java taustalla ja ihmeelliseltä tää maailma välillä tuntuu.

    Hyvä tää blogi ku on jo nyt auttanut itseäni oivaltamaan jotain uutta. Kyllä se tästä. Ja kyllä niitä killer-appseja vielä tulee…🙂

Vastaa

Täytä tietosi alle tai klikkaa kuvaketta kirjautuaksesi sisään:

WordPress.com-logo

Olet kommentoimassa WordPress.com -tilin nimissä. Log Out / Muuta )

Twitter-kuva

Olet kommentoimassa Twitter -tilin nimissä. Log Out / Muuta )

Facebook-kuva

Olet kommentoimassa Facebook -tilin nimissä. Log Out / Muuta )

Google+ photo

Olet kommentoimassa Google+ -tilin nimissä. Log Out / Muuta )

Muodostetaan yhteyttä palveluun %s

%d bloggers like this: