RubyMotion er et rammeverk som lar deg bygge iOS-applikasjoner i Ruby. Det gir deg alle fordelene med Ruby-språket, men fordi koden din er kompilert til maskinkode, får du all den raske ytelsen til å utvikle seg i Objective-C. RubyMotion lar deg bruke iOS SDK direkte, noe som betyr at du har tilgang til alle de nyeste funksjonene på plattformen. Du kan inkludere Mål-C-kode i prosjektet ditt, og RubyMotion fungerer også med CocoaPods.
I denne opplæringen vil du bygge et maleri program fra bunnen av. Jeg skal vise deg hvordan du integrerer grensesnittbygger i arbeidsflyten din og hvordan du skal teste programmet på riktig måte. Hvis du ikke har noen tidligere iOS- eller Ruby-opplevelse, vil jeg anbefale at du lærer mer om de første. Tuts + Ruby for Newbies og Learning iOS SDK Development from Scratch guider er et flott sted å starte.
Før du kan starte kodingen, må du ha RubyMotion installert og satt opp. For detaljer om hvordan du gjør dette, se delen Forutsetninger i RubyMotion Komme i gang-veiledningen.
Når du har gjort det, åpner du terminalen din og oppretter et nytt RubyMotion-prosjekt ved å kjøre:
bevegelse skape maling cd-maling
Dette skaper en maling katalog og flere filer:
rake -T
fra kommandolinjen.RubyMotion genererer også a spec / main_spec.rb fil. Jeg skal vise deg hvordan du kan teste programmet ditt 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 bunt installasjon
etterfulgt av bundle exec rake
å starte søknaden din.
Woohoo! En svart skjerm. Du vil gjøre det mer interessant om et minutt.
Selv om det er fint å ha en løpende app, er en svart skjerm litt kjedelig. La oss legge til en liten farge.
Som den native iOS SDK, tvinger RubyMotion deg ikke til å organisere filene dine på en bestemt måte. Det er imidlertid nyttig å lage noen få mapper i app katalog for å holde prosjektet ditt organisert. Kjør følgende kommandoer fra kommandolinjen for å lage en katalog for modeller, visninger og kontroller.
mkdir app / models mkdir app / visninger mkdir app / controllers
Deretter ta en titt inne i app / app_delegate.rb fil:
klasse AppDelegate def søknad (søknad, didFinishLaunchingWithOptions: launchOptions) true end end
Hvis du er kjent med iOS-utviklingen, vil du legge merke til at denne metoden tilhører UIApplicationDelegate
protokollen, som gir flere kroker inn i applikasjonens livssyklus. Legg merke til at AppDelegate
Klassen erklærer ikke at den implementerer UIApplicationDelegate
protokoll. Ruby er avhengig av å skrive ender som det ikke støtter protokoller. Dette betyr at det ikke bryr seg om klassen din sier at det implementerer en protokoll, det bryr seg bare om det implementerer de riktige metodene.
Definisjonen av applikasjons: didFinishLaunchingWithOptions:
metode inne i AppDelegate
klassen kan se litt rart ut. I Mål-C vil denne metoden bli skrevet slik:
- (BOOL) søknad: (UIApplication *) søknad didFinishLaunchingWithOptions: (NSDictionary *) launchOptions;
Fordi Objective-C-metodenavnene kan deles i flere deler, implementerer Ruby dem på en unik måte. Den første delen av applikasjons: didFinishLaunchingWithOptions:
er det som ville være metodenavnet i MR. Resten av metoden signaturen er skrevet som søkeord argumenter. I RubyMotion, applikasjons: didFinishLaunchingWithOptions:
er skrevet slik:
def søknad (søknad, didFinishLaunchingWithOptions: launchOptions) avslutte
La oss implementere denne metoden.
klasse AppDelegate def søknad (program, didFinishLaunchingWithOptions: launchOptions) @window = UIWindow.alloc.initWithFrame (UIScreen.mainScreen.bounds) @ window.makeKeyAndVisible @ window.rootViewController = UIViewController.alloc.initWithNibName (null, bunt: null) sann ende
De to første linjene i applikasjons: didFinishLaunchingWithOptions:
Metode oppretter et nytt vindu objekt og gjør det til hovedvinduet av programmet. Hvorfor er @vindu
en instansvariabel? RubyMotion vil søppel samle vinduet med mindre vi lagrer det. Den siste linjen i metoden setter vinduets rotasjonsvisningskontroller til en ny, tom visningskontroller.
Kjør programmet for å få alt som fortsatt fungerer.
Hmm. Programmet kjører, men skjermen er fortsatt svart. Hvordan vet du at koden din fungerer? Du kan gjøre en rask sunnhetskontroll ved å legge til følgende nederst på siden applikasjons: didFinishLaunchingWithOptions:
, før ekte
. Pass på at du fjerner dette før du går videre.
@ window.rootViewController.view.backgroundColor = UIColor.yellowColor
Ingen søknad er fullført uten en solid pakke tester. Testing kan du være trygg på at koden din fungerer, og det lar deg gjøre endringer uten å bekymre deg for å bryte eksisterende kode.
RubyMotion leveres med en port i Bacon testing biblioteket. Hvis du er kjent med Rspec, vil Bacon føle seg veldig kjent.
For å komme i gang, speil på app katalogstruktur i spec katalog ved å kjøre følgende kommandoer fra kommandolinjen.
mkdir spec / models mkdir spec / visninger mkdir spec / controllers
Deretter lager du AppDelegate
s spesifikasjonsfil på spec / app_delegate_spec.rb. Ved konvensjon er kildefiler speil i spesifikasjonsmappen og har _spec vedlagt til slutten av filnavnet.
Start denne klassen ved å definere en beskrive
blokkere som forteller leseren hva filen din tester.
beskriv AppDelegate gjør slutten
Deretter legger du til et sekund beskrive
blokkere innenfor den første som viser at du vil teste applikasjons: didFinishLaunchingWithOptions:
metode.
beskriv AppDelegate gjør beskrivelsen "#application: didFinishLaunchingWithOptions:" gjør slutten
La du merke til #
i begynnelsen av metoden signatur? Ved konvensjon begynner eksempelmetoder med hash og klassemetoder som begynner med en periode.
Deretter legger du til en spesifikasjon ved hjelp av en den
blokkere.
beskriv AppDelegate gjør beskrivelsen "#application: didFinishLaunchingWithOptions:" gjør det "skaper vinduet" do UIApplication.sharedApplication.windows.size.should == 1 slutten av enden
En av de beste tingene med Bacon-og andre BDD-testrammer-er at spesifikasjonene er veldig klare om hva de tester. I dette tilfellet sørger du for at applikasjons: didFinishLaunchingWithOptions:
Metoden skaper et vindu.
Din spesifikasjon trenger ikke å ringe applikasjons: didFinishLaunchingWithOptions:
metode direkte. Den kalles automatisk når Bacon starter søknaden din.
Kjør programmets spesifikasjoner ved å kjøre bundle exec rake spec
fra kommandolinjen. Du bør se utgang slik:
1 spesifikasjoner (1 krav), 0 feil, 0 feil
Dette forteller deg at Bacon løp en test og fant ingen feil. Hvis en av dine spesifikasjoner mislykkes, vil du se 1 feil
og Bacon vil skrive ut en detaljert beskrivelse av problemet.
Ovennevnte arbeider, men du skal bruke UIApplication.sharedApplication
for alle dine spesifikasjoner. Ville det ikke vært fint hvis du kunne gripe dette objektet en gang og bruke det i alle spesifikasjonene? Du kan med en før
blokkere.
beskriv AppDelegate gjør beskjed "#application: didFinishLaunchingWithOptions:" gjør før du gjør @application = UIApplication.sharedApplication avslutte det "oppretter vinduet" do @ application.windows.size.should == 1 slutten av enden
Nå kan du enkelt legge til resten av programmets spesifikasjoner.
beskriv AppDelegate gjør beskrive "#application: didFinishLaunchingWithOptions:" gjør før du gjør @application = UIApplication.sharedApplication avslutte det "oppretter vinduet" gjør @ application.windows.size.should == 1 avslutte det "gjør vinduetasten" gjør @applikasjon .windows.first.isKeyWindow.should.be.true avslutte det "setter rotvinkontrolleren" gjør @ application.windows.first.rootViewController.should.be.instance_of UIViewController endeendens ende
Kjør disse for å sikre at alt fungerer før du går videre.
Det er flere måter å opprette brukergrensesnittet ved hjelp av RubyMotion. Min personlige favoritt er å bruke Grensesnittbygger med IB-perlen. Åpne din Gemfile og legg til IB-perlen.
kilde 'https://rubygems.org' perle 'rake' perle 'ib'
Løpe bunt installasjon
fra kommandolinjen for å installere perlen. Hvis du bruker Git, legg til ib.xcodeproj
til din .gitignore fil.
Interface Builder er en del av Xcode. Start grensesnittbyggeren ved å kjøre bunt exec rake ib: åpen
. Dette skaper et Xcode-prosjekt skreddersydd for søknaden din. Opprett en ny brukergrensesnittfiler ved å velge Ny> Fil ... fra Xcode er Fil menyen og velg Storyboard fra Brukergrensesnitt kategori til venstre. Klikk neste to ganger for å fullføre dette trinnet.
Lagre storyboardet i ressurser katalog som main.storyboard. Åpne storyboardet i Xcode og dra et nytt Vis kontrolleren inn i den fra Objektbibliotek til høyre. Sett Storyboard ID feltet til kontrolleren til PaintingController
.
Dra en etikett til visningskontrollens visning fra Objektbibliotek til høyre og sett teksten til Hallo
.
Deretter åpner du opp app / app_delegateog erstatt den siste linjen av applikasjons: didFinishLaunchingWithOptions:
med følgende:
storyboard = UIStoryboard.storyboardWithName ("main", bundle: nil) @ window.rootViewController = storyboard.instantiateInitialViewController
Kjør deretter programtestene dine igjen med bundle exec rake spec
for å sørge for at de fortsatt passerer. Legg merke til hvordan du ikke måtte endre noen av dem? Gode spesifikasjoner teste oppførselen til koden, ikke dens implementering. Dette betyr at du bør kunne endre hvordan Koden din er implementert og dine spesifikasjoner skal fortsatt fungere. Kjør din applikasjon for å teste ditt nye brukergrensesnitt.
Det du har bygget så langt er bra, men ville det ikke vært fint hvis appen din faktisk gjorde noe? I denne delen legger du til kontrollene for å bytte fargen på penselen. Opprett to nye filer, en kontroller og dens spesifikasjoner, ved å kjøre følgende kommandoer.
berør app / controllers / painting_controller.rb touch spec / controllers / painting_controller_spec.rb
Gjennomfør PaintingController
s skjelett sammen med sin spec.
klasse PaintingController < UIViewController end
beskriv PaintingController gjør tester PaintingController,: storyboard => 'main',: id => 'PaintingController' slutten
RubyMotion håndterer kontrollerens spesifikasjoner på en spesiell måte. De tester PaintingController,: storyboard => 'main',: id => 'PaintingController'
linje av spesifikasjonsfilen forteller RubyMotion å bruke kontrolleren med et storyboard ID på PaintingController
i hoved- storyboard. Du kan bruke kontrolleren
variabel for å teste den.
Deretter må du legge til utsalgssteder for kontrolleren din. Disse lar deg koble objekter til kontrolleren din i Interface Builder.
klasse PaintingController < UIViewController extend IB outlet :black_button outlet :purple_button outlet :green_button outlet :blue_button outlet :white_button def select_color(sender) end end
utvide IB
legger til flere metoder for kontrolleren din, inkludert stikkontakt
. Du har lagt til fem uttak, en for hver knapp.
Bildene for knappene er inkludert i kildefilene i denne opplæringen. Last ned bildene og kopier dem til ressurser katalogen. Du må regenerere Xcode-prosjektet ditt slik at grensesnittbyggeren kan hente de endringene vi har gjort. Den enkleste måten å gjøre dette på er å lukke Xcode og kjører bunt exec rake ib: åpen
, som vil gjenåpne prosjektet.
Velg visningsregulatoren og endre klassen til PaintingController
.
Åpen spec / app_delegate_spec.rb og endre siste spesifikasjon for å sjekke for PaintingController
klasse.
det "setter rot view view controller" gjør @ application.windows.first.rootViewController.should.be.instance_of PaintingController end
Legg til fem knapper i visningsregulatorens visning ved å dra Knapp objekter på utsikten fra Objektbibliotek til høyre.
Disse knappene er litt kjedelige. Velg den første knappen, endre dens type til Tilpasset
i Attributtsinspektør til høyre og fjern tittelen. Pass på at Misligholde
tilstand er valgt i State Config rullegardinmenyen og sett bakgrunnsbildet til button_black.png
. Sett Tint Egenskapen til knappen for gjennomsiktig.
Sett State Config rullegardinmenyen til valgt
og endre bakgrunnsbildet til button_black_selected.png
.
I Størrelsesinspektør, endre bredden og høyden på knappen til 50
.
Gjenta denne prosessen for de andre knappene.
Det neste trinnet er å hekte knappene opp til utsiktsregulatorens utsalgssteder som vi erklærte tidligere. Hold nede Styre tasten på tastaturet ditt, og dra fra visningsregulatoren til den første knappen. En meny vil dukke opp når du slipper musen. Å velge black_button
fra menyen. Deretter holder du nede Styre tast og dra av knappen til visningsregulatoren og velg select_color
metode fra menyen som dukker opp. Gjenta disse to trinnene for de andre knappene.
Til slutt velger du den første knappen og klikker på valgt boksen under Styre i Attributtsinspektør.
Nå er det en god tid å legge til noen nyttige spesifikasjoner til spec / painting_controller_spec.rb.
Beskriv PaintingController gjør tester PaintingController,: storyboard => 'main',: id => 'PaintingController' beskriver "#black_button" gjør det "er koblet til i storyboardet" do controller.black_button.should.not.be.nil slutten enden beskrive "#purple_button" gjør det "er tilkoblet i storyboardet" do controller.purple_button.should.not.be.nil slutten beskriver "#green_button" gjør det "er koblet i storyboardet" do controller.green_button.should.not. be.nil end-end beskriver "#blue_button" gjør det "er tilkoblet i storyboardet" do controller.blue_button.should.not.be.nil slutten beskriver "#white_button" gjør det "er koblet i storyboard" gjør kontrolleren. white_button.should.not.be.nil slutten slutten
Disse spesifikasjonene sikrer at uttakene er riktig tilkoblet i Interface Builder. Som alltid er det en god ide å kjøre dem før du fortsetter å sørge for at de alle passerer.
Deretter skal du implementere select_color
metode i PaintingController
. Når denne metoden kalles, er knappen som ble tappet valgt, og den tidligere valgte knappen er ikke valgt.
def select_color (avsender) [black_button, purple_button, green_button, blue_button, white_button] .each do | button | button.selected = false end sender.selected = true end
Legg til spesifikasjonene til spec / kontrollere / painting_controller_spec.rb.
beskriv "#select_color" gjør før gjør controller.select_color (controller.green_button) avslutte det "fjerner de andre fargene" gjør 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ør controller.green_button.state.should == UIControlStateSelected end end
Kjør programmet og kontroller at knappvalget fungerer. Når du trykker på en knapp, bør den øke i størrelse. Mens dette er kult, er det virkelig en farge som skal velges når knappen er tappet. Dette er lett å oppnå med noen tilføyelser.
Sugarcube er et sett med iOS-utvidelser for RubyMotion som gjør flere oppgaver, som å skape farger, enklere. Legg til perle 'sukkerrør'
til Gemfile og løp bunt installasjon
. Legg så til krever "sukkerrør-farge"
til din Rakefile ovenfor Motion :: Prosjekt :: App.setup
.
Perlen gjør det enkelt å lage farger med heksekoden. I PaintingController
klasse, legg til følgende kodestykke under utsagnsstedet:
COLOURS = ["# 333333" .uicolor, "# 7059ac" .uicolor, "# 196e76" .uicolor, "# 80a9cc" .uicolor, "#fafafa" .uicolor]
Deretter refactor rekke knapper i select_color
inn i en privat hjelpemetode:
def select_color (sender) buttons.each do | button | button.selected = false end sender.selected = true @color = COLORS [sender.tag] avslutter private def knapper [black_button, purple_button, green_button, blue_button, white_button] avslutte
Til slutt legg til en ny metode nedenfor select_color
som returnerer den valgte fargen.
def selected_color COLORS [buttons.find_index | button | button.state == UIControlStateSelected] slutten
Denne metoden tar tak i indeksen for den valgte knappen og velger fargen som tilsvarer den. Selvfølgelig ville denne metoden ikke være komplett uten tester.
beskriv "#selected_color" gjør før gjør controller.select_color (controller.green_button) avslutte det "returnerer riktig farge" gjør controller.selected_color.should == PaintingController :: FARGER [2] endeenden
Kjør din søknad igjen for å sikre at alt fungerer som forventet.
Du har dekket mye bakken i denne opplæringen. Du har lært hvordan du konfigurerer og kjører et RubyMotion-program, du har jobbet med Interface Builder, og du har bygget et brukergrensesnitt.
I den andre delen av denne veiledningen vil du dykke dypere inn i modell-View-Controller-mønsteret på iOS og programmets organisasjon. Du vil også legge til et målvisning og skrive koden som tillater brukeren å tegne. Følg med.