Proces izrade Apple Watch app
Deo 1: Big picture
Kreiranje aplikacija za ᴡᴀᴛᴄʜ je interesantno iskustvo, sa više aspekata. Retke su situacije da budete u poziciji da učestvujete u “rađanju” jedne potpuno nove platforme. Jedan takav momenat je bilo predstavljanje iPhone SDK 2008-e kada su svi postojeći Mac developeri imali veliku startnu prednost nad ostalima. Imati iole upotrebljivu aplikaciju na App Storeu u vreme kada je na istom bilo nekoliko stotina ili par hiljada aplikacija je finansijski bila fantastična stvar.
ᴡᴀᴛᴄʜ je sličan momenat, pogotovo od kada je na Spring Forward eventu objavljeno da će watch apps imati svoj zaseban App Store u okviru Apple Watch app, koja postoji od iOS 8.2. To je sjajna vest za developere jer se praktično počinje od nule, uz znantno manju konkurenciju nego na glavnom Storeu.
Ovaj članak je namenjen iOS developerima koji bi voleli da se poigraju kreiranjem watch aplikacija ali nisu imali prilike da protegnu prste. Prvi deo — koji sada čitate — je big picture pogled na koncepte i potrebne alate. Drugi deo će biti više tehnički orijentisan sa primerima konkretnog koda.
Ideja vodilja je da vam uštedimo nekoliko dana čitanja dokumentacije i blog postova i da vas odmah uputimo na pravu stazu, bez mnogo lutanja. Svi saveti su bazirani na iskustvu kreiranja watch aplikacije za moju najpopularniju iOS app - Run 5k.
Native aplikacije za sat nije moguće kreirati sa WatchKit-om 1.0, to će biti moguće u narednoj instanci. Stoga je potrebno da imate postojeću iPhone aplikaciju koja nešto korisno već radi a watch app predstavlja samo još jednu ekstenziju te aplikacije, slično Today widgetima ili Action ekstenzijama.
ᴡᴀᴛᴄʜ ne može raditi samostalno već zavisi od prisustva uparenog iPhonea. Podržani modeli su iPhone 5 i noviji. Iz samo Appleu znanih razloga, nijedan model iPada nije podržan.
Kakve aplikacije kreirati
Na desetine tekstova je napisano na ovu temu proteklih nekoliko meseci i nemam posebnu želju da ih sumiram. ᴡᴀᴛᴄʜ je samo još jedna korisna sprava ali joj namenu i mesto u svom životu morate odrediti sami. I kao korisnik i kao developer.
Smatram da sve iOS aplikacije koje već imaju Today widget prosto moraju da imaju i watch app. Bilo da widgete koristite za notifikacije ili kao daljinski pregled / upravljač, sat je u svakom pogledu bolja lokacija za bilo koju od tih aktivnosti.
Lakše je objasniti na primeru: moja Run 5k app ima Today widget koji je dostupan i kada je iPhone zaključan. To onome ko trči omogućava da jednostavno u toku treninga proveri koliko je ostalo do kraja, koja je aktuelna brzina, koliko je daljine pređeno itd. Takođe može da pauzira ili nastavi trčanje, čime se widget pretvara u daljinski upravljač. Da bi to radilo, napisao sam kôd kojim iOS app ekstenzija dobija potrebne podatke i osluškuje da li ekstenzija zahteva neku od definisanih akcija.
Watch app koju sam kreirao radi isto to ali bez potrebe da se telefon juri po džepu ili torbici. Prostim pokretom ruke se dobije isti set informacija i mogućnosti.
Ako vam je potrebno još inspiracije zavirite u WatchAware showcase i pogledajte šta su drugi već najavili i pripremili.
Razvojni alati
Osnova je svakako Mac računar sa OS X Yosemite. Xcode 6.2 je minimum i on donosi sa sobom podršku za iOS 8.2 i odgovarajući SDK.
Kako u ovom trenutku sata nema u slobodnoj prodaji, kompletan razvoj se odvija u iOS Simulatoru. Kada startujete watch app, Xcode će startovati i iPhone i Watch simulator.
Simulator za sat je rudimentaran i prikazuje samo čist ekran sata, bez tzv. chrome (okvira, narukvice itd) koji postoji na realnom satu. Apple na više mesta naglašava da dizajn aplikacije treba da ide od ivice od ivice. To predstavlja priličan mentalni problem dizajnerima čija će prva reakcija biti da ubace neku marginu oko sadržaja na ekranu i time bespotrebno izgube zlata vrednih 10pt ili više.
Što nema kod Applea, ima kod divnih ljudi dobre volje. Troy Gaul iz Iconfactory-ja je kreirao jednostavnu app — Bezel — koja iscrta fizički izgled sata i u realnom vremenu “krade” ekran simulatora i iscrtava unutar sebe. Time dobijate realniji prikaz kako app izgleda na satu.
Max Rudberg je kreirao i set dodatnih maski za Bezel koje možete iskoristiti umesto predefinisane. Jedino što sreću kvari je što ne možete kliktati unutar Bezela već morate u Simulatoru.
Gledati app na ekranu Maca daje pogrešan utisak koliko je fizički taj ekran zaista veliki. Video sam dosta dizajnerskih promašaja sa premalim ili preblizu postavljenim touch targetima. Tip: nemojte inspiraciju tražiti na Dribbbleu.
Obzirom da sat ima retina ekran, preporučujem sledeći trik: kupite xScope za Mac (zlata vredna app) i xScope Mirror za iOS i moći ćete projektovati Bezel direktno na vaš iPhone. U meniju Bezela podesite da se koristi 200% prikaz ako imate non-retina Mac ekran. Time ćete dobiti 1:1 fizičku repliku sata na iPhone.
Druga opcija koju možete probati jeste WatchSim Danny Keogana. Uz pomoćni Mac server app, ovo bi trebalo da omogući da se simulator vidi na iPhoneu i da u stvari možete i da koristite watch app na telefonu. To bi svakako bila naprednija opcija jer možete direktno testirati da li su touch targeti dovoljno dobro postavljeni. Ja nisam probao obzirom da već imam xScope ali sam svakako zainteresovan da čujem utiske.
Kada za par meseci uspete da kupite sat, sve će biti jednostavnije. Međutim, cilj je imati watch app prvog dana prodaje i ovo je najbolji setup koji sada možete postaviti.
Dizajn
Apple je uložio mnogo truda da veoma precizno definiše UI smernice za obe veličine sata. Naime, 38mm i 42mm sat nemaju istu rezoluciju, za razliku od iPada gde i 9.7in i 7.9in model imaju istu rezoluciju i aplikacije su identične.
Kod sata, ne samo da se rezolucije razlikuju već se neznatno razlikuju i debljine linija u ikonama, veličine samih ikona, vrednosti margina između ivice ekrana i teksta, veličine teksta itd. Potpuno je fascinantno sa koliko pažnje je sve ovo kreirano, što je možda najbolje ilustrovati sa par primera iz zvaničnog Apple Watch Resources paketa koji je Apple pripremio:
Ja se bavim iOS razvojem od prvog SDK i nikada do sada nisam video da je Apple imao ovako spreman paket uputstava, dokumentacije i direktno upotrebljivog materijala na samom početku. Sve to govori koliko dugo i sa koliko pažnje se ovom projektu pristupilo.
Za detalje, svakako pročitajte zvanični HIG vodič.
Sat ima retina ekran stoga kada se priča o rezoluciji treba razmišljati u pt-ima. 38mm sat ima 136x170 pt, 42mm sat ima 156x190 tačaka. I to je to.
Kreirati nešto upotrebljivo i korisno na toliko malom prostoru je uzbudljiv izazov.
Watch app ikonica
Kada sam već spomenuo ikone, toplo preporučujem da pročitate članak Michaela Flarupa o kreiranju app ikona za ᴡᴀᴛᴄʜ. Vredi znati i naučiti kako sve to funkcioniše a zatim možete iskoristiti Michaelov .psd fajl koji – zahvaljujući skriptabilnosti Photoshopa – automatski kreira ikonu u svim potrebnim dimenzijama. Vaše je samo da spremite maksimalnu veličinu od 1024x1024px.
Ili upotrebite iOS 8 app icon template koji je kreirao Max Rudberg i koji takođe podržava ᴡᴀᴛᴄʜ.
Savet: na ikonici za sat, ostavite apsolutni minimum potrebnih detalja da aplikacija bude prepoznatljiva. U slučaju Run 5k sam izbacio segmentne prstenove oko “5k” koji postoje na iOS app ikoni. Razlog je prost – kada se ikona smanji na 36pt (ili još manje) prstenovi postanu neprepoznatljivi i izgleda kao da je ekran na tom delu umrljan.
Iskoristite spomenuti xScope Mirror i proverite kako ikona izgleda na iPhoneu i procenite sami šta je dovoljan minimum.
3 podvrste Watch aplikacija
Sem glavne watch app, WatchKit ima još dve podvrste: Glance i Notification. Obe su opcione i dali ćete ih kreirati zavisi od vaše app:
Preporučujem da izaberete sve opcije i pustite Xcode da vam iskreira sve što treba za razvoj. Lakše je kasnije izbaciti ono što vam ne treba za app nego dodavati ručno i eventualno propustiti neko od podešavanja.
UI elementi za sve podvrste se nalaze u istom storyboardu kao i glavna watch app i predstavljaju dodatne “ulazne” tačke.
Za svaku imate poseban WKInterfaceController
i pišete odgovarajući kod.
Na svakom koraku razvoja se vidi koliko se Apple trudi da uniformiše User Experience, što ću ilustrovati na primeru Glancea koji se sastoji od dva striktno odvojena dela ekrana: zaglavlje i telo. Interface Builder nudi veliki broj predefinisanih šablona i za gornji i donji segment; evo primera kako to izgleda za gornji segment:
Iako se to ne vidi, ovo nije sve - ova lista je skrolabilna i opcija ima još dosta. Ako izabere neki od ovih šablona, elemente na ekranu ne možete gotovo nikako menjati - veličina teksta, parametri slike, broj vidljivih karaktera i max broj linija – sve to je zakucano i praktično jedino možete menjati boju teksta.
Ako vam to ne odgovara, izaberite prvi šablon sa spiska koji ima samo jednu grupu i onda unutar nje dodajte šta god želite.
Ovime završavam prvi deo priče. Za par dana sledi drugi deo sa više tehničkih detalja i primera.
Deo drugi: tehnikalije
Drugi deo priče je, kako sam već najavio, znatno više tehnički orijentisan. Pretpostavljam da će ovaj deo čitati iOS programeri koji su se zagrejali podešavanjem okruženja i spremni su da se upuste u pisanje konkretnog koda.
Za početak, jedna značajna sitnica vezana za debug. Ako ste pogledali Run 5k preview video vidi se da iOS i watch app rade u paraleli. Dok tako nešto pravite realna je potreba da debugujete i jednu i drugu app. Međutim, kada pokrenete Watch app Build & Run šemu, Xcode će “videti” samo watch app. Da biste mogli da postavljate breakpointe i unutar iOS app, morate se naknadno prikačiti na odgovarajući proces za iOS app.
Arhitektura aplikacije
U ovom trenutku watch “app” je u suštini nova vrsta iOS 8 ekstenzije za postojeću iPhone app. To je zapravo sjajna stvar jer ako već imate Today widget za svoju iOS app, onda pretpostavljam da već imate rešeno pitanje komunikacije između glavne iOS app i ekstenzije. Konceptualno, Watch i Today ekstenzije su maltene identične i barem pola posla ste već završili.
Mapa dozvoljenih komunikacija između celina izgleda ovako:
Sva zanimljiva komunikacija ide isključivo na relaciji watch ekstenzija prema iOS app i obrnuto. Iz watch ekstenzije je moguće jednosmerno slati podatke ka watch app ali ne i obrnuto.
Watch app, ono što se vidi na satu, nije ništa drugo do remote display. Vi ama baš ništa ne radite direktno na satu niti sa sata možete pročitati ikakvu informaciju. Watch app takođe nema nikakvu komunikaciju sa internetom niti (za sada) pristup bilo kakvom senzoru koji sat ima. Oni koji su već videli demoe 3rd party aplikacija će primetiti da tu nešto ne štima — gotovo sve demonstrirane aplikacije imaju mogućnost da izvrše neku akciju, tipa odgovore na SMS, aktiviraju alarm ili na primeru moje app - pokrenu ili pauziraju trening sesiju.
Kako onda to radi?
Interface Builder FTW
Ko do sada nije koristio storyboards u iOS aplikacijama — kao autor ovog članka — prvo što će istražiti jeste: da li se UI može kreirati bez njih? Tough luck – ne može.
Watch app se sastoji isključivo od jednog jedinog storyboarda i gomile slika. Taj storyboard sadrži jednu ili više ulaznih tačaka, tj. viewova koji se inicijalno prikazuju kada se storyboard učita.
Evo sada ključnog dela odgovora na prethodno pitanje, ilustrovanog kombinacijom screenshotova iz Xcodea:
Viewovi i kontrole su arhivirani u storyboardu u watch app bundleu koji se pri instalaciji iOS aplikacije iskopira na upareni sat. Međutim, watch app ne sadrži nikakav kod. Svi kontroleri i sve kontrole se nalaze u watch ekstenziji! Zato sam na početku teksta rekao da je watch app ništa drugo do remote display a sav posao se i dalje radi na iPhoneu.
Kada dodirnete dugme prikazano na satu, WatchKit će preko Bluetootha okinuti method u watch ekstenziji. Kada hoćete da na labeli prikazanoj na satu ispišete neki tekst, iz watch ekstenzije izvršite setText:
metod i WatchKit će opet preko Bluetootha poslati taj tekst na sat i onda će OS na satu to iscrtati.
Ono što nije moguće je da pročitate tekst koji je trenutno prikazan u labeli. Ako vam to treba, morate sami čuvati stanje u watch ekstenziji. Pogledajte WKInterfaceLabel.h
header: ne postoji property text
, kao za UILabel
, već samo method setText:
. Zbog toga ne možete da napišete
1
|
|
već mora
1
|
|
Animirani GIF FTW!
Kada sam prethodno napisao “gomile slika”, to bukvalno mislim — u Run 5k app ih imam 400 i kusur. Obzirom da imam jedan tanji i jedan deblji progres bar, za svaki sam pripremio 100 slika — po jedna za svaku stotinku od 0,00 do 1,00. I onda sve to x2, zbog različite rezolucije satova.
Ne postoji pouzdana mogućnost da znate na kojoj rezoluciji sata se aplikacija iscrtava, no to srećom nije ni neophodno: image assets u Interface Builderu u Xcode 6.2 podržava definisanje slika za obe veličine sata:
Na isti način definišete i seriju slika. Format imena fajla je proizvoljan, dovoljno je samo da na kraju imena budu sukcesivni brojevi:
Par bitnih sitnica ovde, da vam ne pojedu sate debugovanja kao meni: WatchKit nikako ne voli da koristite vodeće nule za brojač niti voli prekide u sekvenci. Ja sam u seriji od 100 slika greškom izostavio xx-14
sliku i koju god vrednost progress-a da sam stavio iscrtalo bi se do 13-e i tu stane. Naravno da sam proverio sve druge stvari i čupao kosu satima dok na kraju slučajno nisam uočio u Finderu da za folder ispiše 99 files umesto 100 i onda skapirao gde je problem. To je taj glamur programerskog posla.
Ako ste pomislili da je kreiranje .xcassets
fajla sa slike mukotrpan ručni posao - u pravu ste. Zbog toga sam sebi napravio iOS app koja mi omogućava da kreiram proizvoljne veličine ovih progress barova, a app onda automatski generiše sve potrebne slike za obe veličine sata te ih upakuje u .xcassets
format. WatchRingGenerator je open source i možete ga preuzeti sa GitHuba i izmeniti kako vam već treba.
Nakon ovoga, animiranje progress bara se radi ovako:
1 2 3 4 5 |
|
Komunikacija
Craig Hockenberry je odmah po objavljivanju prve bete WatchKita napisao:
Bluetooth Low Energy must be really low power: the design of WKInterfaceObject means it’s going to be ON a lot. Every interaction with the watch has the potential to move actions and data between your pocket and wrist using the radio.
Iz prethodnih primera je jasno zašto to kaže. Bluetooth radio stalno nešto prenosi i troši bateriju. Pritom, činjenica je da taj transfer mora trajati neko vreme. Što više optimizujete tu komunikaciju, to će vaša watch app bolje i brže raditi. Tehnički gledano, slike za progress barove sam mogao da kreiram u watch ekstenziji i da ih ispucavam ka satu koristeći ovaj method:
1 2 |
|
Obratite pažnju na razliku: setImageNamed:
kaže WatchKitu da potraži sliku sa tim imenom negde u watch app bundleu i prikaže je unutar WKInterfaceImage
viewa. setImage:
šalje binarni fajl slike iz ekstenzije ka satu. Jasno je da nema šanse da postignete 60fps prikaz na satu na taj način jer se u prvom slučaju prenosi 10-ak bajtova teksta dok u drugom treba preneti fajl od oko XX*1200 bajtova, gde je XX vrednost progress bara – ako je recimo 0.7, onda treba preneti 70 * 1200 bajtova. U prvom slučaju je to i dalje 10 bajtova + poziv startAnimating…
metoda.
Do sada se sigurno već pitate — zar nije bilo jednostavnije da se CoreAnimation omogući na satu umesto ovog zezanja sa slikama? Što reče Craig - BTLE mora da zaista malo troši, toliko da se isplati imati veći storage na satu i drndati BT radio umesto da S1 čip ovo sve iscrtava sam.
Pitaj, da ti odgovorim
WatchKit je doneo jedan lep novi class method kojim ekstenzija može u bilo kom trenutku da kontaktira iOS app i da (asinhrono) dobije odgovor:
1 2 3 4 |
|
Metod radi bez obzira da li je iOS app aktivna u vreme poziva ili ne. Ako nije, iOS će startovati app u background režimu. Sa strane iOS app, UIApplicationDelegate
mora implementirati ovaj metod:
1 2 3 4 |
|
Gde se ovo koristi u praksi?
Opet na primeru: Run 5k može da meri daljinu i brzinu koristeći GPS (Core Location) ali na 5s i novijim iPhoneima može da iskoristi i pedometer (Core Motion). Aplikacija na satu omogućava da se pokrene nova trening sesija ali ne zna koje opcije su dozvoljene u samoj iOS app. Stoga koristim gore spomenute metode da to saznam:
1 2 3 4 5 6 7 8 9 |
|
Kao što možete videti, imate potpunu slobodu da sami definišete šta su userInfo
(pitanje ekstenzija → iOS app) i replyInfo
(odgovor iOS app → ekstenzija).
Na osnovu toga mogu prikazati samo GPS ili GPS + Pedometer u meniju koji se prikaže kada korisnik inicira force-touch.
Real-time komunikacija
Spomenuti metod je međutim spor i praktično neupotrebljiv ukoliko watch app treba kontinuirano osvežavati podacima iz iOS app.
Kada trening krene, iOS app odbrojava minute, meri pređenu daljinu i trenutnu brzinu i (opciono) ritam srca. Watch app bi sve to trebalo da prikaže u realnom vremenu. Ili barem što realnijem.
Preporučena metoda od strane Appleovih dev evangelista je da se iskoristi Darwin Notification Center, tj socket to socket komunikacija. To je low-level C API i kao takav bi blago rečeno bio mučan za korišćenje.
Na sreću, tu su opet dobri ljudi iOS sveta. Conrad Stoll je kreirao MMWormhole biblioteku koja omogućava jednostavan messaging system između iOS app i ekstenzija (bilo kojih, ne samo watch). Interno ova biblioteka se bazira na Darwin NC i koristi se veoma jednostavno, samo ispratite dokumentaciju sa Github stranice.
Handoff
Handoff je lepa i korisna tehnološka novotarija koju su doneli iOS 8 i Yosemite. Apple je uglavnom reklamira i objašnjava koristeći email. Počnete da pišete email na telefonu, pa shvatite da biste radije na Macu ili iPadu i onda spustite iPhone, dodirnete odgovarujuću ikonu na lock screenu i automagično nastavite kucanje gde ste stali.
U slučaju WatchKita, Handoff omogućava transparentni prelaz iz Glance ili Notification ka glavnoj watch app. Na primer, ako korisnik moje app već gleda u Glance na kome piše da je sledeća trening sesija Week 2 / Run 3 onda, kada dodirne ekran i time inicira prelazak u app, Glance tu informaciju prenese u app i time uštedim jedan openParentApplication…/handleWatchKitExtensionRequest…
Bluetooth ciklus.
Takva sitna unapređenja omogućavaju da se watch app momentalno aktivira i korisniku deluje brža.
Gledano kroz kod, Handoff se trivijalno implementira. Na izvornom delu pozovite ovaj metod kad god se promeni stanje za koje watch app treba znati:
1 2 3 |
|
U ovom slučaju type
može biti bilo šta kao i webpageURL
, jedino što me zanima je userInfo
.
Watch app, kao destinacija, implementira ovaj metod:
1
|
|
i proverava šta je prosleđeno unutar userInfo
. Još jedna sitnica koja vas može saplesti: kada se koristi Handoff, handleUserActivity:
je mesto na kome se radi inicijalizacija kontrolera, awakeWithContext:
se uopšte ne poziva.
WatchKit Layout
Na kraju želim da kažem par reči o layout sistemu koji je Apple izabrao za sam UI. Blago rečeno sam zbunjen izborom jer ne liči ni na šta drugo što se koristi što na iOS-u što na Macu. Nema starijeg springs & struts sistema, niti ima AutoLayouta.
Najviše podseća na početke HTML-a, kada ste samo mogli da elemente slažete jedan pored drugog ili jedan ispod drugog, pa dokle imate mesta. Kad mesta ponestane, pređe se u novi red i tako iznova.
Nijedna UI kontrola se ne može preklopiti sa nekom drugom, sa izuzetkom WKInterfaceGroup
čiji bi pandan u HTML-u bio div
element. Tako možete praviti grupu unutar grupe unutar grupe…bez kraja. Unutar grupa, elementi se mogu centrirati (i horizontalno i vertikalno) ili uravnati levo/desno odnosno gore/dole. Grupe i druge kontrole mogu biti fiksirane veličine ili relativnih dimenzija u odnosu na grupu u kojoj se nalaze.
I to je to.
Uzeću kao primer osnovni ekran Run 5k watch app, koji se ispostavio kao ubedljivo najteži za implementaciju.
Imam prilično kompleksnu grupu labela gde su neke uravnate po levoj ivici, neke po desnoj, neke po gornoj ivici teksta a neke po donjoj. I pri tom oko cele te grupe imam dva centrirana progress bara. Ovakav izgled je nemoguće kreirati koristeći WKInterfaceLabel
kontrole.
Jedini način da se ovo uradi jeste ovako:
Ove dve grupe su zaslužne za iscrtavanje progress barova. WKInterfaceGroup
ima metod setBackgroundImageNamed:
i ta slika takođe može biti animirana korišćenjem startAnimatingWithImagesInRange:duration:repeatCount:
metoda.
Image
na dnu hijerarhije je zaslužan za ispis šume teksta u sredini. U Watch ekstenziji generišem sliku koristeći CoreGraphics, tj. UIGraphicsBeginImageContextWithOptions(…)
gde bukvalno iscrtam sav taj tekst uz mnogo pipavog računanja veličine teksta sa datim fontom, merenja ascendera i descendera za svaki željeni font itd. I onda putem spomenutog setImage:
metoda pošaljem tu sliku na sat.
Da postoji AutoLayout i da je moguće slobodno pozicionirati kontrole, sve to bi bilo gotovo za nekih pola sata. Ovako sam potrošio dobrih tri dana dok nisam sve udenuo kako sam zamislio.
Nakon svega, jedino sam se mogao zapitati: aman Apple, zašto? Jedino objašnjenje koje mogu da smislim je da S1 system on a chip u satu prosto ne može u ovom trenutku podržati kompleksnost Auto Layouta odnosno da su ti proračuni previše zahtevni za dati hardver. S druge strane, procene su da je S1 u suštini minijaturizovani A5 čip (iz iPad 2, prvi iPad mini)…ko zna.
Kako god bilo, nadam se da će u budućnosti biti nečeg boljeg jer će se inače mnogi Objective-C / Swift developeri upoznati sa lepotama (šic!) ugnježdenih tabela i divova od čega web developeri beže već 20 godina.
Požurite
Nadam se da vam je ovaj brzi let kroz kreiranje watch aplikacija bio koristan. Kreiranje je relativno jednostavno i nema mnogo toga da se radi, sem da se igrate sa UI-em i kreirate nešto dopadljivo i korisno.
Run 5k watch app sam kreirao za nekih desetak dana, gde sam 7 dana potrošio na UI a preostalih par dana na finese komunikacije sa iOS app.
Obzirom da će sat krenuti u prodaju 24. aprila, imate šanse da budete prisutni sa svojom aplikacijom prvog dana prodaje. Ako krenete danas.
Savet za kraj: Apple je nedavno objavio svoju listu preporuka za kreiranje ovih aplikacija što prirodno predstavlja obavezno štivo.