RubyMotion is een raamwerk waarmee je iOS-applicaties in Ruby kunt bouwen. Het geeft je alle voordelen van de Ruby-taal, maar omdat je code is gecompileerd naar machine-code, krijg je alle onbewerkte prestaties van ontwikkelen in Objective-C. Met RubyMotion kun je de iOS SDK direct gebruiken, wat betekent dat je toegang hebt tot alle nieuwste functies van het platform. U kunt de Objective-C-code opnemen in uw project en RubyMotion werkt zelfs met CocoaPods.
In deze zelfstudie maakt u een geheel nieuwe tekenapplicatie. Ik zal u laten zien hoe u Interface Builder kunt integreren in uw workflow en hoe u uw applicatie goed kunt testen. Als je geen eerdere iOS- of Ruby-ervaring hebt, raad ik je aan hier eerst meer over te leren. De Tuts + Ruby voor nieuwkomers en het leren ontwikkelen van iOS SDK van Scratch-gidsen is een geweldige plek om te beginnen.
Voordat u kunt beginnen met coderen, moet u RubyMotion hebben geïnstalleerd en ingesteld. Raadpleeg het gedeelte Vereisten van de handleiding Aan de slag RubyMotion voor meer informatie over hoe u dit kunt doen.
Zodra je dat hebt gedaan, open je je terminal en maak je een nieuw RubyMotion-project door te draaien:
beweging maakt verf cd-verf
Dit creëert een verf map en verschillende bestanden:
hark -T
vanaf de opdrachtregel.RubyMotion genereert ook een spec / main_spec.rb het dossier. Ik zal je laten zien hoe je je aanvraag iets later kunt testen in deze tutorial. Voor nu kun je dit bestand verwijderen door het uit te voeren rm spec / main_spec.rb
vanaf de opdrachtregel.
De afhankelijkheden van uw toepassing installeren door ze uit te voeren bundel installeren
gevolgd door bundel exec rake
om uw toepassing te starten.
Woohoo! Een zwart scherm. Je zult het binnen een minuut interessanter maken.
Hoewel het leuk is om een draaiende app te hebben, is een zwart scherm een beetje saai. Laten we een beetje kleur toevoegen.
Net als de native iOS SDK dwingt RubyMotion je niet om je bestanden op een specifieke manier in te delen. Het is echter handig om een paar mappen in de map te maken app map om uw project georganiseerd te houden. Voer de volgende opdrachten uit vanaf de opdrachtregel om een map te maken voor uw modellen, weergaven en controllers.
mkdir app / models mkdir app / views mkdir app / controllers
Neem vervolgens een kijkje in de app / app_delegate.rb het dossier:
class AppDelegate def application (application, didFinishLaunchingWithOptions: launchOptions) true end end
Als u bekend bent met de ontwikkeling van iOS, merkt u dat deze methode behoort tot de UIApplicationDelegate
protocol, dat verschillende haken biedt in de levenscyclus van de toepassing. Merk op dat de AppDelegate
class verklaart niet dat het de UIApplicationDelegate
protocol. Ruby vertrouwt op eendtypen omdat het geen protocollen ondersteunt. Dit betekent dat het niet uitmaakt of jouw klas zegt dat het een protocol implementeert, het maakt alleen maar uit of het de juiste methoden implementeert.
De definitie van de toepassing: didFinishLaunchingWithOptions:
methode binnen de AppDelegate
klas ziet er misschien een beetje vreemd uit. In Objective-C zou deze methode als volgt zijn geschreven:
- (BOOL) applicatie: (UIApplication *) applicatie didFinishLaunchingWithOptions: (NSDictionary *) launchOptions;
Omdat objectieve-C-methode-namen kunnen worden opgesplitst in verschillende delen, implementeert Ruby ze op een unieke manier. Het eerste deel van toepassing: didFinishLaunchingWithOptions:
is wat de methode naam in MRI zou zijn. De rest van de methodehandtekening is geschreven als trefwoordargumenten. In RubyMotion, toepassing: didFinishLaunchingWithOptions:
is zo geschreven:
def applicatie (application, didFinishLaunchingWithOptions: launchOptions) end
Laten we deze methode implementeren.
class AppDelegate def applicatie (application, didFinishLaunchingWithOptions: launchOptions) @window = UIWindow.alloc.initWithFrame (UIScreen.mainScreen.bounds) @ window.makeKeyAndVisible @ window.rootViewController = UIViewController.alloc.initWithNibName (nihil, bundel: nihil) true end end
De eerste twee regels van de toepassing: didFinishLaunchingWithOptions:
methode maak een nieuw vensterobject en maakt dit het belangrijkste venster van de toepassing. Waarom is @venster
een instantievariabele? RubyMotion zal het venster slordig verzamelen, tenzij we het opslaan. De laatste regel van de methode stelt de root view-controller van het venster in op een nieuwe, lege view-controller.
Start de applicatie om alles nog steeds te laten werken.
Hmm. De toepassing wordt uitgevoerd, maar het scherm is nog steeds zwart. Hoe weet je dat je code werkt? U kunt een snelle sanity-check uitvoeren door het volgende aan de onderkant toe te voegen toepassing: didFinishLaunchingWithOptions:
, voor waar
. Zorg ervoor dat u dit verwijdert voordat u verdergaat.
@ window.rootViewController.view.backgroundColor = UIColor.yellowColor
Geen enkele toepassing is compleet zonder een solide reeks tests. Met testen kunt u erop vertrouwen dat uw code werkt en kunt u wijzigingen aanbrengen zonder dat u zich zorgen hoeft te maken over het verbreken van bestaande code.
RubyMotion wordt geleverd met een poort van de Bacon-testbibliotheek. Als je bekend bent met Rspec, voelt Bacon heel vertrouwd aan.
Om te beginnen, spiegelt u het app mappenstructuur in de spec map door de volgende opdrachten uit te voeren vanaf de opdrachtregel.
mkdir spec / models mkdir spec / views mkdir spec / controllers
Maak vervolgens de AppDelegate
specificatiebestand op spec / app_delegate_spec.rb. Volgens afspraak zijn bronbestanden mirrors in de spec directory en hebben _spec toegevoegd aan het einde van hun bestandsnaam.
Begin deze klasse door a te definiëren beschrijven
blok dat de lezer vertelt wat uw bestand aan het testen is.
beschrijf AppDelegate do end
Voeg vervolgens een seconde toe beschrijven
blok binnen de eerste om te laten zien dat je de wilt testen toepassing: didFinishLaunchingWithOptions:
methode.
beschrijven AppDelegate do beschrijven "#application: didFinishLaunchingWithOptions:" do end end
Heb je de #
aan het begin van de methodehandtekening? Volgens afspraak beginnen instantiemethoden met een hash en class-methoden beginnen met een punt.
Voeg vervolgens een specificatie toe met een het
blok.
beschrijven AppDelegate do beschrijven "#application: didFinishLaunchingWithOptions:" do it "maakt het venster" do UIApplication.sharedApplication.windows.size.should == 1 end end end
Een van de beste dingen aan Bacon-en andere BDD-testraamwerken is dat de specificaties heel duidelijk zijn over wat ze testen. In dit geval zorgt u ervoor dat het toepassing: didFinishLaunchingWithOptions:
methode maakt een venster.
Uw spec hoeft de. Niet te bellen toepassing: didFinishLaunchingWithOptions:
methode direct. Het wordt automatisch gebeld wanneer Bacon uw toepassing start.
Voer de specificaties van uw toepassing uit door te draaien bundel exec rake spec
vanaf de opdrachtregel. Je zou de uitvoer als volgt moeten zien:
1 specificaties (1 vereisten), 0 storingen, 0 fouten
Dit geeft aan dat Bacon één test heeft uitgevoerd en geen fouten heeft gevonden. Als een van uw specs faalt, zult u zien 1 mislukking
en Bacon zal een gedetailleerde beschrijving van het probleem afdrukken.
Het bovenstaande werkt, maar je zult gebruiken UIApplication.sharedApplication
voor al uw specs. Zou het niet fijn zijn als je dit object een keer zou pakken en het zou gebruiken in alle specs? Je kunt met een voor
blok.
beschrijven AppDelegate do beschrijven "#application: didFinishLaunchingWithOptions:" doe voordat doe @application = UIApplication.sharedApplication end it "maakt het venster" do @ application.windows.size.should == 1 end end end
Nu kunt u eenvoudig de specificaties van de rest van de toepassing toevoegen.
beschrijf AppDelegate do beschrijven "#application: didFinishLaunchingWithOptions:" doe voordat doe @application = UIApplication.sharedApplication end the "create the window" do @ application.windows.size.should == 1 end it "makes the window key" do @application .windows.first.isKeyWindow.should.be.true end it "stelt de root view controller in" do @ application.windows.first.rootViewController.should.be.instance_of UIViewController end end end
Voer deze uit om te controleren of alles werkt voordat u verdergaat.
Er zijn verschillende manieren om de gebruikersinterface te maken met behulp van RubyMotion. Mijn persoonlijke favoriet is om te gebruiken Interface Builder met de IB-edelsteen. Open je Gemfile en voeg het IB-juweel toe.
bron 'https://rubygems.org' gem 'rake' gem 'ib'
Rennen bundel installeren
vanaf de opdrachtregel om het juweel te installeren. Als je Git gebruikt, voeg je toe ib.xcodeproj
aan jouw .gitignore het dossier.
Interface Builder is een onderdeel van Xcode. Start Interface Builder door te starten bundel exec rake ib: open
. Hiermee wordt een Xcode-project gemaakt dat is afgestemd op uw toepassing. Maak een nieuwe gebruikersinterface-bestanden door te selecteren Nieuw> Bestand ... van Xcode's het dossier menu en selecteer storyboard van de Gebruikersomgeving categorie aan de linkerkant. Klik volgende tweemaal om deze stap te voltooien.
Sla het storyboard op in de middelen directory als main.storyboard. Open het storyboard in Xcode en sleep een nieuw Bekijk Controller erin van de Objectbibliotheek aan de rechterkant. Stel de Storyboard-ID veld van de controller naar PaintingController
.
Sleep een label vanuit de weergave in de weergave van de view controller Objectbibliotheek aan de rechterkant en stel de tekst in Hallo
.
Open vervolgens app / app_delegateen vervang de laatste regel van toepassing: didFinishLaunchingWithOptions:
met het volgende:
storyboard = UIStoryboard.storyboardWithName ("main", bundle: nil) @ window.rootViewController = storyboard.instantiateInitialViewController
Voer vervolgens de tests van uw toepassing opnieuw uit met bundel exec rake spec
om ervoor te zorgen dat ze nog steeds passen. Merk op hoe je geen van hen hoeft te veranderen? Goede specificaties testen het gedrag van de code, niet de implementatie. Dit betekent dat je zou moeten kunnen veranderen hoe uw code is geïmplementeerd en uw specificaties moeten nog steeds werken. Voer uw applicatie uit om uw nieuwe gebruikersinterface te testen.
Wat je tot nu toe hebt gebouwd is geweldig, maar zou het niet leuk zijn als je app daadwerkelijk iets heeft gedaan? In dit gedeelte voegt u de bedieningselementen toe om de kleur van de kwast te wijzigen. Maak twee nieuwe bestanden, een controller en zijn spec, door de volgende opdrachten uit te voeren.
touch app / controllers / painting_controller.rb aanraakspecificatie / controllers / painting_controller_spec.rb
Implementeer de PaintingController
zijn skelet samen met zijn spec.
klasse PaintingController < UIViewController end
beschrijf PaintingController do tests PaintingController,: storyboard => 'main',: id => 'PaintingController' end
RubyMotion verwerkt controller-specificaties op een speciale manier. De test PaintingController,: storyboard => 'main',: id => 'PaintingController'
regel van het spec-bestand vertelt RubyMotion om de controller te gebruiken met een storyboard-ID van PaintingController
in de hoofd storyboard. U kunt de controleur
variabele om het te testen.
Vervolgens moet u stopcontacten aan uw controller toevoegen. Hiermee kunt u objecten verbinden met uw controller in 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
verlengen IB
voegt verschillende methoden toe aan uw controller, inclusief stopcontact
. Je hebt vijf verkooppunten toegevoegd, één voor elke knop.
De afbeeldingen voor de knoppen zijn opgenomen in de bronbestanden van deze zelfstudie. Download de afbeeldingen en kopieer ze naar de middelen directory. U moet uw Xcode-project opnieuw genereren om Interface Builder in staat te stellen de wijzigingen op te nemen die we hebben aangebracht. De gemakkelijkste manier om dit te doen is door Xcode te sluiten en te draaien bundel exec rake ib: open
, waarmee het project opnieuw wordt geopend.
Selecteer de view controller en verander zijn class in PaintingController
.
Open spec / app_delegate_spec.rb en wijzig de laatste spec om te controleren op de PaintingController
klasse.
het "stelt de rootview-controller in" do @ application.windows.first.rootViewController.should.be.instance_of PaintingController end
Voeg vijf knoppen toe aan de weergave van de weergave-controller door te slepen Knop objecten op het uitzicht vanaf de Objectbibliotheek aan de rechterkant.
Deze knoppen zijn een beetje saai. Selecteer de eerste knop, verander het type in gewoonte
in de Kenmerken Inspector aan de rechterkant en verwijder de titel. Zorg ervoor dat de Standaard
staat is geselecteerd in de Staat Config vervolgkeuzemenu en stel de achtergrondafbeelding in op button_black.png
. Stel de Tint eigendom van de knop om transparant te maken.
Stel de Staat Config vervolgkeuzemenu naar Gekozen
en verander de achtergrondafbeelding in button_black_selected.png
.
In de Size Inspector, verander de breedte en hoogte van de knop in 50
.
Herhaal dit proces voor de andere knoppen.
De volgende stap is om de knoppen aan de verkooppunten van de view controller te hangen die we eerder hebben verklaard. Houd de toets ingedrukt Controle toets op uw toetsenbord en sleep van de weergavecontroller naar de eerste knop. Er verschijnt een menu wanneer u uw muis loslaat. kiezen black_button
van het menu. Houd vervolgens de knop ingedrukt Controle toets en sleep van de knop naar de view controller en kies de selecteer kleur
methode uit het menu dat verschijnt. Herhaal deze twee stappen voor de andere knoppen.
Selecteer ten slotte de eerste knop en klik op de Gekozen selectievakje onder Controle in de Kenmerken Inspector.
Dit is een goed moment om een paar nuttige specificaties toe te voegen spec / painting_controller_spec.rb.
beschrijf PaintingController do tests PaintingController,: storyboard => 'main',: id => 'PaintingController' beschrijven "#black_button" doen "is verbonden in het storyboard" do controller.black_button.should.not.be.nil end end beschrijven "#purple_button" do it "is verbonden in het storyboard" do controller.purple_button.should.not.be.nil end end omschrijven "#green_button" doen "is verbonden in het storyboard" do controller.green_button.should.not. be.nil end-end beschrijven "#blue_button" doen "verbonden in het storyboard" doen controller.blue_button.hould.not.be.nee einde beschrijven "#white_button" doen "verbonden in de storyboard" doen controller. white_button.should.not.be.nil end end end
Deze specificaties zorgen ervoor dat de stopcontacten correct zijn aangesloten in Interface Builder. Zoals altijd is het een goed idee om ze uit te voeren voordat u doorgaat om ervoor te zorgen dat ze allemaal slagen.
Vervolgens implementeer je de selecteer kleur
methode in PaintingController
. Wanneer deze methode wordt aangeroepen, wordt de knop die werd getikt geselecteerd en wordt de eerder geselecteerde knop gedeselecteerd.
def select_color (afzender) [black_button, purple_button, green_button, blue_button, white_button]. each do | button | button.selected = false end sender.selected = true end
Voeg de specificaties toe aan spec / controllers / painting_controller_spec.rb.
beschrijf "#select_color" doe het eerder doe controller.select_color (controller.green_button) einde het "deselecteert de andere kleuren" do controller.black_button.state.should == UIControlStateNormal controller.purple_button.state.should == UIControlStateNormal controller.blue_button.state .should == UIControlStateNormal controller.white_button.state.should == UIControlStateNormal end it "selecteert de kleur" do controller.green_button.state.should == UIControlStateSelected end end
Start de applicatie en controleer of de knopselectie werkt. Wanneer u op een knop tikt, moet deze groter worden. Hoewel dit cool is, wil je echt dat een kleur wordt geselecteerd wanneer op de knop wordt getikt. Dit is gemakkelijk te bereiken met een paar toevoegingen.
Sugarcube is een verzameling iOS-extensies voor RubyMotion die verschillende taken, zoals het maken van kleuren, eenvoudiger maken. Toevoegen gem 'sugarcube'
naar je Gemfile en rennen bundel installeren
. Dan toevoegen vereisen "sugarcube-color"
aan jouw Rakefile bovenstaande Motion :: Project :: App.setup
.
De edelsteen maakt het gemakkelijk om kleuren te maken met behulp van hun hex-code. In de PaintingController
klasse, voeg het volgende codefragment toe onder de verklaring van de winkels:
KLEUREN = ["# 333333" .uicolor, "# 7059ac" .uicolor, "# 196e76" .uicolor, "# 80a9cc" .uicolor, "#fafafa" .uicolor]
Werk vervolgens de reeks knoppen bij selecteer kleur
in een privéhulpmethode:
def select_color (zender) buttons.each do | button | button.selected = false end sender.selected = true @color = COLOURS [sender.tag] einde private def-knoppen [black_button, purple_button, green_button, blue_button, white_button] end
Voeg ten slotte hieronder een nieuwe methode toe selecteer kleur
die de geselecteerde kleur retourneert.
def selected_color KLEUREN [buttons.find_index | button | button.state == UIControlStateSelected] end
Deze methode grijpt de index van de geselecteerde knop en selecteert de kleur die daarmee overeenkomt. Natuurlijk zou deze methode niet volledig zijn zonder tests.
beschrijf "#selected_color" doe voordat je controller.select_color (controller.green_button) doet eindigen "geeft de juiste kleur terug" do controller.selected_color.should == PaintingController :: COLORS [2] end end
Voer uw toepassing opnieuw uit om te controleren of alles werkt zoals verwacht.
Je hebt veel aandacht besteed aan deze tutorial. U hebt geleerd hoe u een RubyMotion-toepassing opzet en uitvoert, dat u met Interface Builder hebt gewerkt en dat u een gebruikersinterface hebt gebouwd.
In het tweede deel van deze zelfstudie gaat u dieper in op het patroon Model-View-Controller op iOS en de organisatie van uw toepassing. Je voegt ook een schilderijweergave toe en schrijft de code waarmee de gebruiker kan tekenen. Blijf kijken.