Let oss skrive en RubyMotion App: Part 1
49
Del
7
Del
Dette Cyber Monday Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
Hva du skal lage
RubyMotion er et rammeverk som lar deg bygge iOS-applikasjoner i Ruby. Det gir deg alle fordelene av Ruby språket, men fordi koden er kompilert til maskinkode, får du all den rå ytelse for utvikling i Objective-C. RubyMotion lar deg bruke iOS SDK direkte, noe som betyr at du har tilgang til alle de nyeste funksjonene i plattformen. Du kan ta med Objective-C-kode inn i prosjektet og RubyMotion fungerer selv med CocoaPods.
I denne opplæringen, vil du bygge et maleri program fra bunnen av. Jeg skal vise deg hvordan du kan innlemme Interface Builder i arbeidsflyten, og hvordan du kan teste din søknad skal. Hvis du ikke har noen tidligere iOS eller Ruby erfaring, vil jeg anbefale deg å lære mer om dem først. Den Tuts + Ruby for Nybegynnere og læring iOS SDK Development fra Scratch guider er et flott sted å starte.
1. Prosjektet Setup
Før du kan begynne koding, må du ha RubyMotion installert og satt opp. For detaljer om hvordan du gjør dette, sjekk ut Forutsetninger delen av RubyMotion Komme i gang
Når du har gjort det, åpne opp terminal og opprette et nytt RubyMotion prosjekt ved å kjøre.
Bevegelse skape paintcd maling
Dette skaper en male katalog og flere filer:
.gitignore:
Denne filen forteller Git hvilke filer som skal ignorere. Fordi RubyMotion genererer bygge filer når den kjører, er denne filen nyttig for å holde din generert bygge filer ut av kildekontroll
Gemfile
.
Denne filen inneholder programmets avhengig .
Rakefile:
RubyMotion bruker Rake for å bygge og drive din søknad. Rakefile
konfigurerer din søknad og laster sine avhengigheter. Du kan se alle de oppgavene som er tilgjengelig for din søknad ved å kjøre rake -T fra kommandolinjen
app /app_delegate.rb.
Søknad delegat er inngangsporten til søknaden din. Når iOS ferdig lasting søknaden din inn i minnet, er programmet delegat varslet.
RubyMotion genererer også en spec /main_spec.rb
fil. Jeg skal vise deg hvordan du kan teste din søknad litt senere i denne opplæringen. For nå kan du slette denne filen ved å kjøre rm spec /main_spec.rb fra kommandolinjen.
Installer programmets avhengigheter ved å kjøre bundle installere fulgt av bunt exec rake å starte applikasjonen.
Woohoo! En svart skjerm. Du vil gjøre det mer interessant i et minutt.
2. First Endre
Selv om det er fint å ha en løpende app, er en svart skjerm litt kjedelig. La oss legge til litt farge.
Som innfødt iOS SDK, RubyMotion ikke tvinge deg til å organisere filene på en bestemt måte. Men det er nyttig å lage noen mapper i app katalog for å holde prosjektet organisert. Kjør følgende kommandoer fra kommandolinjen for å lage en katalog for dine modeller, synspunkter og kontrollere.
Mkdir app /modelsmkdir app /viewsmkdir app /kontrollere
Neste, ta en titt på innsiden av app /app_delegate .rb
file:
klasse AppDelegate def program (søknad, didFinishLaunchingWithOptions: launchOptions) sant Sluttslutt
Hvis du er kjent med iOS utvikling, vil du legge merke til denne metoden tilhører UIApplicationDelegate protokollen, som gir flere kroker i søknaden livssyklus. Merk at AppDelegate klassen ikke erklære at den implementerer UIApplicationDelegate protokollen. Ruby er avhengig av duck typing som den ikke støtter protokoller. Dette betyr at det ikke bryr seg om din klasse sier det implementerer en protokoll, det bare bryr seg om det implementerer de riktige metodene
Definisjonen av søknaden:. DidFinishLaunchingWithOptions: metode inne i AppDelegate klassen kan se litt rart . I Objective-C, vil denne metoden være skrevet slik: Anmeldelser - (BOOL) program: (UIApplication *) applikasjons didFinishLaunchingWithOptions: (NSDictionary *) launchOptions;
Fordi Objective-C metodenavn kan deles inn i flere deler implementerer Ruby dem på en unik måte. Den første delen av programmet: didFinishLaunchingWithOptions: er hva som ville være den metoden navn i MR. Resten av fremgangsmåten signaturen skrives som søkeord argumenter. I RubyMotion, applikasjons: didFinishLaunchingWithOptions: er skrevet slik:
def program (søknad, didFinishLaunchingWithOptions: launchOptions). End
La oss gjennomføre denne metoden
klassen AppDelegate def program (søknad, didFinishLaunchingWithOptions: launchOptions)window = UIWindow.alloc.initWithFrame (UIScreen.mainScreen.bounds) @ window.makeKeyAndVisible @ window.rootViewController = UIViewController.alloc.initWithNibName (null, pakke: null) true Sluttslutt
De to første linjene i søknaden: didFinishLaunchingWithOptions: Metode opprette et nytt vindu objekt og gjør det nøkkelen vinduet av søknaden. Hvorfor erwindow en instansvariabel? RubyMotion vil sanering vinduet med mindre vi lagre den. Den siste linjen i metoden setter vinduet rot view controller til en ny, tom view controller.
Kjør programmet for å gjøre alt fortsatt fungerer.
Hmm. Programmet kjører, men skjermen er fortsatt svart. Hvordan vet du koden fungerer? Du kan gjøre en rask tilregnelighet sjekk ved å legge følgende til bunnen av søknaden: didFinishLaunchingWithOptions :, før sant. Sørg for å fjerne denne før du går videre.
@ Window.rootViewController.view.backgroundColor = UIColor.yellowColor
3. Testing
Ingen søknaden er komplett uten en solid pakke med tester. Testing kan du være trygg på koden din fungerer og det lar deg gjøre endringer uten å bekymre deg for å bryte eksisterende kode.
RubyMotion skip med en port av Bacon testing biblioteket. Hvis du er kjent med Rspec, vil Bacon føler veldig kjent.
For å komme i gang, speile app katalog strukturen i spec katalog ved å kjøre følgende kommandoer fra kommandolinjen.
mkdir spec /modelsmkdir spec /viewsmkdir spec /kontrollere
Deretter oppretter den AppDelegate spesifikasjon fil på spec /app_delegate_spec.rb
. Ved konvensjonen, kildefilene er speil i spec katalogen og har _spec
lagt til på slutten av filnavnet.
Start denne klassen ved å definere et beskrive blokk som forteller leseren hva din fil er testing
beskrive AppDelegate doend
Deretter legge til en andre beskrive blokk i den første til å vise at du ønsker å teste programmet. didFinishLaunchingWithOptions. metode
beskrive AppDelegate vet beskrive "#application: didFinishLaunchingWithOptions:" gjøre Sluttslutt
La du merke til det # i begynnelsen av metoden signatur? Ved konvensjonen, instansmetoder begynne med hasj og klassemetoder begynne med en periode
Deretter legger du til en spec bruker en det blokk
beskrive AppDelegate gjør beskrive.. "#application: DidFinishLaunchingWithOptions:" gjør det " skaper vinduet "gjør UIApplication.sharedApplication.windows.size.should == en slutt Sluttslutt
En av de beste tingene med Bacon-og andre BDD test rammeverk-er at spesifikasjonene er veldig klar på hva de tester. I dette tilfellet, du gjør at programmet: didFinishLaunchingWithOptions: metoden skaper et vindu.
Din spec trenger ikke å kalle programmet: didFinishLaunchingWithOptions: metode direkte. Det kalles automatisk når Bacon lanserer søknaden din.
Kjør programmets specs ved å kjøre bunt exec rake spec fra kommandolinjen. Du vil nå se slik ut:
1 spesifikasjoner (1 krav), 0 fiaskoer, 0 feil
Dette forteller deg at Bacon kjørte en test og ikke fant noen feil. Hvis en av dine specs mislykkes, vil du se en fiasko og Bacon vil skrive ut en detaljert beskrivelse av problemet.
De ovennevnte fungerer, men du skal bruke UIApplication.sharedApplication for alle dine spesifikasjoner. Ville det ikke vært fint om du kunne ta dette objektet gang og bruke det i alle specs? . Du kan med en før blokk
beskrive AppDelegate vet beskrive "#application: didFinishLaunchingWithOptions:" gjøre før doapplication = UIApplication.sharedApplication avslutte det "skaper vinduet" gjør @ application.windows.size.should == en ende Sluttslutt
Nå kan du enkelt legge til resten av programmets specs
beskrive AppDelegate vet beskrive. "#application: didFinishLaunchingWithOptions:" do før doapplication = UIApplication.sharedApplication avslutte det "skaper vinduet" gjørapplication. windows.size.should == en slutt det "gjør vinduet nøkkelen" gjør @ application.windows.first.isKeyWindow.should.be.true avslutte det "setter root view controller" gjør @ application.windows.first.rootViewController. should.be.instance_of UIViewController slutten Sluttslutt
Kjør disse til å sørge for at alt fungerer før du går videre.
4. Legge til brukergrensesnitt
Det er flere måter å lage brukergrensesnittet ved hjelp RubyMotion. Min personlige favoritt er å bruke Interface Builder
med IB perle. Åpne opp Gemfile og tilsett IB perle
kilde. 'Https: //rubygems.org'gem' rake'gem 'ib'
Kjør bunt installere fra kommandolinjen installerer perle. Hvis du bruker Git, legge ib.xcodeproj til .gitignore
fil.
Interface Builder er en del av Xcode. Lansere Interface Builder ved å kjøre bunt exec rake ib: open. Dette skaper en Xcode prosjekt skreddersydd til søknaden din. Opprett en ny filer brukergrensesnitt ved å velge New > Fil ...
fra Xcode Fil
meny og velg Storyboard
fra User Interface
kategori til venstre. Klikk Neste
to ganger for å fullføre dette trinnet.
Lagre dreieboken i ressurser katalog som main.storyboard
. Åpne dreieboken i Xcode og drar en ny View Controller
inn i den fra Object Library
til høyre. Sett Storyboard ID
felt av kontrolleren til PaintingController.
Dra en etikett til visningen kontrolleren syn fra objektbiblioteket på høyre og sette tekst til Hello.
Deretter åpner opp app /app_delegate Deretter kjører programmets tester igjen med bundle exec rake spec for å sørge for at de fortsatt passere. Legg merke til hvordan du ikke trenger å endre noen av dem? Gode spesifikasjoner teste oppførselen av koden, ikke gjennomføringen. Dette betyr at du bør være i stand til å endre hvordan Hva du har bygget så langt er flott, men ville det ikke være fint hvis din app faktisk gjorde noe? I denne seksjonen vil du legge kontrollene for å bytte farge på pensel. Opprette to nye filer, en controller og sin spec, ved å kjøre følgende kommandoer. Implementere PaintingController skjelett sammen med sin spec. Anmeldelser klasse PaintingController < UIViewControllerenddescribe PaintingController gjøre tester PaintingController,: storyboard = > 'main',: id = > 'PaintingController'end RubyMotion håndterer kontrolleren specs på en spesiell måte. Den tester PaintingController,: storyboard = > 'main',: id = > 'PaintingController' linje på spec filen forteller RubyMotion å bruke kontrolleren med en dreiebok ID PaintingController i Hovedanmeldelser storyboard. Du kan bruke kontrolleren variabel for å teste den. Deretter må du legge til uttak til kontrolleren. Disse lar deg koble objekter til kontrolleren i Interface Builder forlenge IB legger flere metoder til kontrolleren, inkludert uttak. Du har lagt til fem utsalgssteder, en for hver knapp. Bildene for knappene er inkludert i kildefilene for denne opplæringen. Last ned bildene og kopiere dem inn i ressurser katalog. Du må regenerere Xcode prosjekt for å tillate Interface Builder for å plukke opp de endringene vi har gjort. Den enkleste måten å gjøre dette på er ved å lukke Xcode og kjører bunt exec rake ib: åpen, noe som vil gjenåpne prosjektet Velg visningen kontrolleren og endre sin klasse PaintingController Åpne <.. b> spec /app_delegate_spec.rb Hotell og modifisere den siste spec for å se etter den PaintingController klassen. Disse knappene er litt kjedelig. Velg den første knappen, endre typen til Custom i attributter Inspektør Sett State Config rullegardinmenyen til Valgte og endre bakgrunnsbildet til button_black_selected.png. I Størrelse Inspector Gjenta denne prosessen for de andre knappene. Det neste trinnet er å koble knappene opp til visningen kontrollerens uttak vi erklært tidligere. Hold nede Ctrl Til slutt velger den første knappen og klikk på Valgt Nå er en god tid for å legge til et par nyttige specs til spec /painting_controller_spec.rb Disse specs sikre uttak er riktig tilkoblet i Interface Builder. Som alltid er det en god idé å kjøre dem før du fortsetter å sørge for at de alle pass. Deretter vil du implementere select_color metoden i PaintingController. Når denne metoden kalles, er den knappen som ble tappet valgt og den tidligere valgte knappen er deaktivert Legg specs til spec /kontrollere /painting_controller_spec.rb Kjør programmet og sørge for at knappen valg fungerer. Når du trykker på en knapp, bør det øke i størrelse. Selv om dette er kult, hva du egentlig ønsker er for en farge som velges når det bankes på knappen. Dette er lett å oppnå med noen få tillegg. sugarcube er et sett med iOS utvidelser for RubyMotion som gjør flere oppgaver, som å lage farger, enklere. Legg perle 'sugarcube "til din Gemfile og kjøre bunt installere. Deretter legger du krever "sugarcube-farge" i Rakefile Perle gjør det enkelt å lage farger ved hjelp av sin hex-kode. I PaintingController klassen, legge inn følgende kode under utdeling av uttakene: Deretter refactor rekken av knappene i select_color inn i et privat hjelpemetode: Til slutt legger du en ny metode under select_color som returnerer den valgte farge . Denne metoden griper indeksen for den valgte knappen og velger den fargen som tilsvarer det. Of course, denne metoden ville ikke være komplett uten tester Kjør programmet igjen for å kontrollere at alt fungerer som forventet Du har dekket mye bakken i denne opplæringen. Du har lært å sette opp og kjøre en RubyMotion program, har du jobbet med Interface Builder, og du har bygget et brukergrensesnitt. I den andre delen av denne opplæringen, vil du dykke dypere inn i Model-View-Controller mønster på iOS og din søknad organisasjon. Du vil også legge et maleri utsikt og skrive kode som gjør det mulig for brukeren å tegne. Følg med.
Hotell og erstatte den siste linjen av programmet: didFinishLaunchingWithOptions: med følgende:
dreiebok = UIStoryboard.storyboardWithName ("main", bunt: null ) @ window.rootViewController = storyboard.instantiateInitialViewController
koden er implementert og dine spesifikasjoner skal fortsatt fungere. Kjør din søknad til å prøvekjøre den nye brukergrensesnittet.
5. Knapper
Berøring app /kontrollere /painting_controller.rbtouch spec /kontrollere /painting_controller_spec.rb
klasse PaintingController <.; UIViewController forlenge IB utløp: black_button utløp: purple_button utløp: green_button utløp: blue_button utløp: white_button def select_color (sender) Sluttslutt
det "setter root view controller" do @ application.windows.first.rootViewController.should.be.instance_of PaintingControllerend < p> Legg fem knapper til visningen kontrolleren syn ved å dra knappeobjekter på utsikten fra objektbiblioteket til høyre.
på høyre og ta tittelen. Vær sikker på at Standard staten er valgt i staten Config drop-down menyen og sette bakgrunnsbildet til button_black.png. Sett Tint
eiendom av knappen for å gjennomsiktig.
, endre bredden og høyden på knappen til 50.
tasten på tastaturet og dra fra visningen kontrolleren til den første knappen. En meny vil komme opp når du slipper musen. Velg black_button fra menyen. Deretter holder du nede Ctrl
tasten og dra fra knappen til visningen kontrolleren og velg select_color metode fra menyen som dukker opp. Gjenta disse to trinnene for de andre knappene.
avkrysnings under Ctrl
i Egenskaper Inspektør
beskrive PaintingController gjøre tester PaintingController,:. dreiebok = > 'main',: id = > 'PaintingController' beskrive "#black_button" do it "er koblet i dreieboken" gjør controller.black_button.should.not.be.nil end end beskrive "#purple_button" do it "er koblet i dreieboken" gjør controller.purple_button. should.not.be.nil end end beskrive "#green_button" do it "er koblet i dreieboken" gjør controller.green_button.should.not.be.nil end end beskrive "#blue_button" do it "er koblet i dreieboken "gjør controller.blue_button.should.not.be.nil end end beskrive" #white_button "do it" er koblet i dreieboken "gjør controller.white_button.should.not.be.nil slutten Sluttslutt
def select_color (sender) [black_button, purple_button, green_button, blue_button, white_button] .each gjøre |. Knapp | button.selected = false slutten sender.selected = trueend
.
beskrive "#select_color" do før gjøre controller.select_color (controller.green_button ) avslutte det "opphever de andre fargene" gjøre controller.black_button.state.should == UIControlStateNormal controller.purple_button.state.should == UIControlStateNormal controller.blue_button.state.should == UIControlStateNormal controller.white_button.state.should == UIControlStateNormal avslutte det "velger farge" gjøre controller.green_button.state.should == UIControlStateSelected Sluttslutt
ovenfor Motion :: Prosjekt :: App.setup.
FARGER = ["# 333333" .uicolor, "# 7059ac" .uicolor, "# 196e76" .uicolor, "# 80a9cc" .uicolor "#fafafa" .uicolor]
def select_color (sender) buttons.each gjøre | knapp | button.selected = false slutten sender.selected = truecolor = FARGER [sender.tag] endprivatedef knappene [black_button, purple_button, green_button, blue_button, white_button] end
def selected_color FARGER [buttons.find_index {| knapp | button.state == UIControlStateSelected}] end
beskrive "#selected_color" do før gjøre controller.select_color (controller.green_button) avslutte det "returnerer riktig farge" gjør controller.selected_color.should == PaintingController.: .: FARGER [2] Sluttslutt
Konklusjon