Schreiben wir eine RubyMotion-App Teil 1

Was Sie erstellen werden

RubyMotion ist ein Framework, mit dem Sie iOS-Anwendungen in Ruby erstellen können. Es bietet Ihnen alle Vorteile der Ruby-Sprache. Da Ihr Code jedoch in Maschinencode kompiliert wird, profitieren Sie von der reinen Leistung der Entwicklung in Objective-C. Mit RubyMotion können Sie das iOS-SDK direkt verwenden, dh Sie haben Zugriff auf alle neuesten Funktionen der Plattform. Sie können Objective-C-Code in Ihr Projekt integrieren, und RubyMotion arbeitet sogar mit CocoaPods.

In diesem Lernprogramm erstellen Sie eine Malanwendung von Grund auf. Ich zeige Ihnen, wie Sie den Interface Builder in Ihren Workflow integrieren und Ihre Anwendung richtig testen. Wenn Sie noch keine Erfahrung mit iOS oder Ruby haben, würde ich Ihnen empfehlen, zuerst mehr darüber zu erfahren. Die Tuts + Ruby für Neulinge und das Lernen von iOS-SDK-Entwicklung von Scratch-Handbüchern sind ein großartiger Ausgangspunkt.

1. Projekteinrichtung

Bevor Sie mit der Codierung beginnen können, müssen Sie RubyMotion installiert und eingerichtet haben. Einzelheiten dazu finden Sie im Abschnitt Voraussetzungen des RubyMotion-Handbuchs Erste Schritte.

Wenn Sie das getan haben, öffnen Sie Ihr Terminal und erstellen Sie ein neues RubyMotion-Projekt, indem Sie Folgendes ausführen:

Bewegung erstellen Farbe CD-Farbe

Dies schafft eine Farbe Verzeichnis und mehrere Dateien:

  • .gitignore: Diese Datei teilt Git mit, welche Dateien ignoriert werden sollen. Da RubyMotion während der Ausführung Build-Dateien generiert, ist diese Datei hilfreich, um die generierten Build-Dateien außerhalb der Quellcodeverwaltung zu halten.
  • Gemfile: Diese Datei enthält die Abhängigkeiten Ihrer Anwendung.
  • Rakefile: RubyMotion verwendet Rake, um Ihre Anwendung zu erstellen und auszuführen. Das Rakefile Konfiguriert Ihre Anwendung und lädt ihre Abhängigkeiten. Sie können alle für Ihre Anwendung verfügbaren Aufgaben anzeigen, indem Sie sie ausführen Rechen -T von der Kommandozeile aus.
  • app / app_delegate.rb: Der Anwendungsdelegat ist der Einstiegspunkt in Ihre Anwendung. Wenn iOS Ihre Anwendung in den Speicher geladen hat, wird der Anwendungsdelegierte benachrichtigt.

RubyMotion generiert auch eine spec / main_spec.rb Datei. Ich werde Ihnen später in diesem Tutorial zeigen, wie Sie Ihre Anwendung testen können. Im Moment können Sie diese Datei durch Ausführen löschen rm spec / main_spec.rb von der Kommandozeile aus.

Installieren Sie die Abhängigkeiten Ihrer Anwendung, indem Sie sie ausführen Bundle installieren gefolgt von Bündel Exec Rake um Ihre Bewerbung zu starten.

Woohoo! Ein schwarzer Bildschirm. Sie machen es in einer Minute interessanter.

2. Erste Änderung

Obwohl es schön ist, eine App zu haben, ist ein schwarzer Bildschirm etwas langweilig. Lassen Sie uns ein wenig Farbe hinzufügen.

Wie das native iOS-SDK zwingt RubyMotion Sie nicht dazu, Ihre Dateien auf bestimmte Weise zu organisieren. Es ist jedoch nützlich, einige Ordner im Ordner zu erstellen App Verzeichnis, um Ihr Projekt zu organisieren. Führen Sie die folgenden Befehle über die Befehlszeile aus, um ein Verzeichnis für Ihre Modelle, Ansichten und Controller zu erstellen.

mkdir app / models mkdir app / ansichten mkdir app / controller

Als nächstes werfen Sie einen Blick in die app / app_delegate.rb Datei:

Klasse AppDelegate def Anwendung (Anwendung, didFinishLaunchingWithOptions: launchOptions) true Ende

Wenn Sie mit der iOS-Entwicklung vertraut sind, werden Sie feststellen, dass diese Methode zu der von UIApplicationDelegate Protokoll, das mehrere Haken in den Anwendungslebenszyklus gibt. Notiere dass der AppDelegate Klasse erklärt nicht, dass sie das implementiert UIApplicationDelegate Protokoll. Ruby setzt auf das Eingeben von Enten, da es keine Protokolle unterstützt. Dies bedeutet, dass es Ihnen egal ist, ob Ihre Klasse angibt, dass sie ein Protokoll implementiert, sondern dass nur die richtigen Methoden implementiert werden.

Die Definition der Anwendung: didFinishLaunchingWithOptions: Methode innerhalb der AppDelegate Klasse sieht vielleicht ein bisschen seltsam aus. In Objective-C würde diese Methode folgendermaßen aussehen:

- (BOOL) Anwendung: (UIApplication *) Anwendung didFinishLaunchingWithOptions: (NSDictionary *) launchOptions;

Da Objective-C-Methodennamen in mehrere Teile aufgeteilt werden können, implementiert Ruby sie auf einzigartige Weise. Der erste Teil von Anwendung: didFinishLaunchingWithOptions: Dies ist der Methodenname in der MRI. Der Rest der Methodensignatur wird wie Schlüsselwortargumente geschrieben. In RubyMotion, Anwendung: didFinishLaunchingWithOptions: ist so geschrieben:

def application (Anwendung, didFinishLaunchingWithOptions: launchOptions) enden 

Lassen Sie uns diese Methode implementieren.

Klasse AppDelegate def-Anwendung (Anwendung, didFinishLaunchingWithOptions: launchOptions) @window = UIWindow.alloc.initWithFrame (UIScreen.mainScreen.bounds) @ ​​window.makeKeyAndVisible @ window.rootViewController = UIVContController.alloc.initWabl

Die ersten beiden Zeilen des Anwendung: didFinishLaunchingWithOptions: Erstellen Sie ein neues Fensterobjekt und machen Sie es zum Schlüsselfenster der Anwendung. Warum ist @Fenster eine Instanzvariable? RubyMotion sammelt das Fenster nicht ein, es sei denn, wir speichern es. In der letzten Zeile der Methode wird der Root-View-Controller des Fensters auf einen neuen, leeren View-Controller festgelegt.

Führen Sie die Anwendung aus, damit alles noch funktioniert.

Hmm. Die Anwendung wird ausgeführt, aber der Bildschirm ist immer noch schwarz. Woher wissen Sie, dass Ihr Code funktioniert? Sie können eine Schnelligkeitsprüfung durchführen, indem Sie unten auf der Seite Folgendes hinzufügen Anwendung: didFinishLaunchingWithOptions:, Vor wahr. Stellen Sie sicher, dass Sie diese entfernen, bevor Sie fortfahren.

@ window.rootViewController.view.backgroundColor = UIColor.yellowColor

3. Testen

Keine Anwendung ist ohne eine solide Testreihe abgeschlossen. Beim Testen können Sie sich darauf verlassen, dass Ihr Code funktioniert, und Sie können Änderungen vornehmen, ohne sich über das Brechen des vorhandenen Codes Gedanken machen zu müssen.

RubyMotion wird mit einem Port der Bacon-Testbibliothek geliefert. Wenn Sie mit Rspec vertraut sind, wird sich Bacon sehr wohl fühlen.

Um zu beginnen, spiegeln Sie die App Verzeichnisstruktur in der spez Verzeichnis durch Ausführen der folgenden Befehle von der Befehlszeile aus.

mkdir spec / models mkdir spec / ansichten mkdir spec / controller

Als nächstes erstellen Sie die AppDelegateSpezifikationsdatei bei spec / app_delegate_spec.rb. In der Regel sind Quelldateien Spiegelungen im Spec-Verzeichnis und haben es _spec an das Ende ihres Dateinamens angehängt.

Starten Sie diese Klasse, indem Sie a definieren beschreiben Block, der dem Leser mitteilt, was Ihre Datei testet.

Beschreibe AppDelegate do end 

Als nächstes fügen Sie eine Sekunde hinzu beschreiben Block innerhalb des ersten, um zu zeigen, dass Sie das testen möchten Anwendung: didFinishLaunchingWithOptions: Methode.

beschreiben AppDelegate do beschreiben "#application: didFinishLaunchingWithOptions:" do end end

Haben Sie das bemerkt? # am Anfang der Methodensignatur? Normalerweise beginnen Instanzmethoden mit einem Hash und Klassenmethoden mit einem Punkt.

Als nächstes fügen Sie eine Spezifikation mit ein es Block.

beschreiben AppDelegate do beschreiben "#application: didFinishLaunchingWithOptions:" do it "erstellt das Fenster" do UIApplication.sharedApplication.windows.size.should == 1 end end end

Eine der besten Eigenschaften von Bacon - und anderen BDD-Test-Frameworks - ist, dass die Spezifikationen sehr genau sind, was sie testen. In diesem Fall stellen Sie sicher, dass Anwendung: didFinishLaunchingWithOptions: Methode erstellt ein Fenster.

Ihre Spezifikation muss nicht anrufen Anwendung: didFinishLaunchingWithOptions: Methode direkt. Es wird automatisch aufgerufen, wenn Bacon Ihre Anwendung startet.

Führen Sie die Spezifikationen Ihrer Anwendung aus, indem Sie sie ausführen Bündel Exec Rake Spec von der Kommandozeile aus. Sie sollten die Ausgabe so sehen:

1 Spezifikationen (1 Anforderungen), 0 Fehler, 0 Fehler 

Dies sagt Ihnen, dass Bacon einen Test durchgeführt hat und keine Fehler gefunden hat. Wenn eine Ihrer Angaben fehlschlägt, werden Sie sehen 1 Fehler und Bacon druckt eine detaillierte Beschreibung des Problems aus.

Das obige funktioniert, aber Sie werden es verwenden UIApplication.sharedApplication für alle Ihre Angaben. Wäre es nicht schön, wenn Sie dieses Objekt einmal packen und in allen Spezifikationen verwenden könnten? Sie können mit einem Vor Block.

AppDelegate beschreiben do beschreiben "#application: didFinishLaunchingWithOptions:" do before do @application = UIApplication.sharedApplication end es "erstellt das Fenster" do @ application.windows.size.should == 1 end end end

Jetzt können Sie den Rest der Anwendungsspezifikationen einfach hinzufügen.

AppDelegate beschreiben do beschreiben "#application: didFinishLaunchingWithOptions:" do before do @application = UIApplication.sharedApplication Endet es "erstellt das Fenster" do @ application.windows.size.should == 1 end it "macht den Fensterschlüssel" @application .windows.first.isKeyWindow.should.be.true endet damit "legt den Root-View-Controller fest" do @ application.windows.first.rootViewController.should.be.instance_of des UIViewController-Endes end

Führen Sie diese aus, um sicherzustellen, dass alles funktioniert, bevor Sie fortfahren.

4. Hinzufügen der Benutzeroberfläche

Es gibt verschiedene Möglichkeiten, die Benutzeroberfläche mit RubyMotion zu erstellen. Mein persönlicher Favorit ist zu verwenden Interface Builder mit dem IB gem. Öffne dein Gemfile und füge den IB-Edelstein hinzu.

Quelle 'https://rubygems.org' gem 'Rechen' 'ib'

Lauf Bundle installieren von der Kommandozeile aus, um den Edelstein zu installieren. Wenn Sie Git verwenden, fügen Sie hinzu ib.xcodeproj zu deinem .Gitignore Datei.

Interface Builder ist ein Teil von Xcode. Starten Sie den Interface Builder durch Ausführen Bündel Exec Rake ib: offen. Dadurch wird ein auf Ihre Anwendung zugeschnittenes Xcode-Projekt erstellt. Erstellen Sie eine neue Benutzeroberflächendatei, indem Sie auswählen Neu> Datei… von Xcode's Datei Menü und wählen Sie Storyboard von dem Benutzeroberfläche Kategorie links. Klicken Nächster zweimal, um diesen Schritt abzuschließen.

Speichern Sie das Storyboard in der Ressourcen Verzeichnis als main.storyboard. Öffnen Sie das Storyboard in Xcode und ziehen Sie ein neues Controller anzeigen hinein aus dem Objektbibliothek zur Rechten. Stellen Sie das ein Storyboard-ID Feld der Steuerung an PaintingController.

Ziehen Sie eine Beschriftung in die Ansicht des Ansichtscontrollers Objektbibliothek auf der rechten Seite und setzen Sie den Text auf Hallo.

Als nächstes aufmachen app / app_delegateund ersetzen Sie die letzte Zeile von Anwendung: didFinishLaunchingWithOptions: mit den folgenden:

storyboard = UIStoryboard.storyboardWithName ("main", Bundle: nil) @ window.rootViewController = storyboard.instantiateInitialViewController

Führen Sie anschließend die Tests Ihrer Anwendung erneut mit aus Bündel Exec Rake Spec um sicher zu gehen, dass sie noch passieren Beachten Sie, wie Sie keinen von ihnen ändern mussten? Gute Spezifikationen testen das Verhalten des Codes, nicht seine Implementierung. Das heißt, Sie sollten sich ändern können Wie Ihr Code ist implementiert und Ihre Angaben sollten weiterhin funktionieren. Führen Sie Ihre Anwendung aus, um die neue Benutzeroberfläche zu testen.

5. Tasten

Was Sie bisher gebaut haben, ist großartig, aber wäre es nicht schön, wenn Ihre App tatsächlich etwas tut? In diesem Abschnitt fügen Sie die Steuerelemente zum Wechseln der Farbe des Pinsels hinzu. Erstellen Sie zwei neue Dateien, einen Controller und dessen Spezifikationen, indem Sie die folgenden Befehle ausführen.

Berühren Sie app / controller / painting_controller.rb berühren Sie spec / controller / painting_controller_spec.rb

Implementieren Sie die PaintingController's Skelett zusammen mit seiner Spezifikation.

Klasse PaintingController < UIViewController end
PaintController beschreiben testet PaintController,: Storyboard => 'main',: id => 'PaintController' beenden

RubyMotion behandelt Controller-Spezifikationen auf besondere Weise. Das testet PaintingController,: Storyboard => 'main',: id => 'PaintingController' In der Zeile der Spezifikationsdatei wird RubyMotion angewiesen, den Controller mit einer Storyboard-ID von zu verwenden PaintingController in dem Main Storyboard Du kannst den ... benutzen Regler Variable, um es zu testen.

Als Nächstes müssen Sie Ihrem Controller Outlets hinzufügen. Damit können Sie Objekte im Interface Builder mit Ihrem Controller verbinden.

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

IB erweitern fügt Ihrem Controller mehrere Methoden hinzu, einschließlich Auslauf. Sie haben fünf Ausgänge hinzugefügt, einen für jede Schaltfläche.

Die Bilder für die Schaltflächen sind in den Quelldateien dieses Lernprogramms enthalten. Laden Sie die Bilder herunter und kopieren Sie sie in die Ressourcen Verzeichnis. Sie müssen Ihr Xcode-Projekt neu generieren, damit Interface Builder die vorgenommenen Änderungen übernehmen kann. Am einfachsten geht das, indem Sie Xcode schließen und ausführen Bündel Exec Rake ib: offen, was das Projekt wieder öffnen wird.

Wählen Sie den View-Controller aus und ändern Sie seine Klasse in PaintingController.

Öffnen spec / app_delegate_spec.rb und ändern Sie die letzte Spezifikation, um nach dem zu suchen PaintingController Klasse.

es "setzt den Root-View-Controller" do @ application.windows.first.rootViewController.should.be.instance_of PaintingController end

Fügen Sie der Ansichts-Controller-Ansicht durch Ziehen fünf Schaltflächen hinzu Taste Objekte auf die Ansicht aus der Objektbibliothek zur Rechten.

Diese Tasten sind etwas langweilig. Wählen Sie die erste Schaltfläche aus und ändern Sie den Typ in Brauch in dem Attribute-Inspektor auf der rechten Seite und entfernen Sie den Titel. Seien Sie sicher das Standard Zustand ist im ausgewählt Status Konfig Dropdown-Menü und stellen Sie das Hintergrundbild auf button_black.png. Stellen Sie das ein Farbton Eigenschaft der Schaltfläche auf transparent.

Stellen Sie das ein Status Konfig Dropdown-Menü zu Ausgewählt und ändern Sie das Hintergrundbild in button_black_selected.png.

In dem Größeninspektor, Ändern Sie die Breite und Höhe der Schaltfläche in 50.

Wiederholen Sie diesen Vorgang für die anderen Tasten.

Der nächste Schritt besteht darin, die Tasten mit den Ausgängen des View-Controllers zu verbinden, die wir zuvor erklärt haben. Halten Sie die Steuerung Taste auf Ihrer Tastatur und ziehen Sie vom View Controller auf die erste Schaltfläche. Ein Menü wird geöffnet, wenn Sie Ihre Maus loslassen. Wählen black_button aus dem menü. Halten Sie als nächstes die Steuerung Taste und ziehen Sie von der Schaltfläche in den Ansichts-Controller und wählen Sie die Wähle Farbe Methode aus dem Menü, das erscheint. Wiederholen Sie diese beiden Schritte für die anderen Tasten.

Wählen Sie schließlich die erste Schaltfläche aus und klicken Sie auf die Schaltfläche Ausgewählt Ankreuzfeld unter Steuerung in dem Attribute-Inspektor.

Jetzt ist ein guter Zeitpunkt, um ein paar hilfreiche Daten hinzuzufügen spec / painting_controller_spec.rb.

PaintController beschreiben: PaintboardController testen: Storyboard => 'main',: id => 'PaintController' beschreiben "#black_button" do it "ist im Storyboard verbunden" do controller.black_button.should.not.be.nil end end beschreiben "#purple_button" do it "ist im Storyboard verbunden" do controller.purple_button.should.not.be.nil end end beschreiben "#green_button" do it "ist im Storyboard verbunden" do controller.green_button.should.not. be.nil end end beschreiben "#blue_button" do it "ist im Storyboard verbunden" do controller.blue_button.should.not.be.nil end end beschreiben "#white_button" do it "ist im Storyboard" do controller verbunden. white_button.should.not.be.nil end end end

Diese Angaben stellen sicher, dass die Ausgänge ordnungsgemäß im Interface Builder angeschlossen sind. Wie immer ist es eine gute Idee, sie auszuführen, bevor Sie fortfahren, um sicherzustellen, dass alle erfolgreich sind.

Als Nächstes implementieren Sie die Wähle Farbe Methode in PaintingController. Wenn diese Methode aufgerufen wird, wird die Schaltfläche ausgewählt, auf die geklickt wurde, und die zuvor ausgewählte Schaltfläche wird deaktiviert.

def select_color (Absender) [black_button, purple_button, green_button, blue_button, white_button] button.selected = false ende sender.selected = true ende

Fügen Sie die Spezifikationen hinzu spec / controller / painting_controller_spec.rb.

Beschreibe "#select_color", bevor der Controller.select_color (Controller.green_button) beendet wird, und es werden die anderen Farben "abgewählt" .should == UIControlStateNormal controller.white_button.state.should == UIControlStateNormal end "wählt die Farbe aus" do controller.green_button.state.should == UIControlStateSelected end end 

Führen Sie die Anwendung aus und stellen Sie sicher, dass die Tastenauswahl funktioniert. Wenn Sie auf eine Schaltfläche tippen, sollte sie größer werden. Dies ist zwar cool, aber Sie möchten wirklich eine Farbe auswählen, wenn Sie auf die Schaltfläche tippen. Dies ist mit wenigen Ergänzungen leicht zu bewerkstelligen.

Sugarcube ist eine Gruppe von iOS-Erweiterungen für RubyMotion, die verschiedene Aufgaben, wie das Erstellen von Farben, vereinfacht. Hinzufügen Juwel 'Zuckerwürfel' zu deinem Gemfile und laufe Bundle installieren. Dann füge hinzu benötigen "Zuckerwürfel-Farbe" zu deinem Rakefile über Motion :: Project :: App.setup.

Der Edelstein macht es einfach, Farben mithilfe des Hex-Codes zu erstellen. In dem PaintingController Klasse, fügen Sie das folgende Code-Snippet unterhalb der Deklaration der Auslässe hinzu:

FARBEN = ["# 333333" .uicolor, "# 7059ac" .uicolor, "# 196e76" .uicolor, "# 80a9cc" .uicolor, "#fafafa" .uicolor] 

Als Nächstes ändern Sie das Array von Schaltflächen in Wähle Farbe in eine private Helfer-Methode:

def select_color (Sender) buttons.each do | button | button.selected = false end sender.selected = true @color = COLORS [sender.tag] private Endschaltflächen [black_button, purple_button, green_button, blue_button, white_button] ende 

Fügen Sie schließlich eine neue Methode hinzu Wähle Farbe das gibt die ausgewählte Farbe zurück.

def selected_color FARBEN [buttons.find_index | button | button.state == UIControlStateSelected] end 

Diese Methode erfasst den Index der ausgewählten Schaltfläche und wählt die dazugehörige Farbe aus. Natürlich wäre diese Methode ohne Tests nicht vollständig.

Beschreibe "#selected_color", bevor do.control.select_color (controller.green_button) beendet wird. es gibt "die richtige Farbe zurück". do.control.selected_color.should == PaintingController :: COLORS [2] end end 

Führen Sie Ihre Anwendung erneut aus, um sicherzustellen, dass alles wie erwartet funktioniert.

Fazit

In diesem Lernprogramm haben Sie eine Menge Bodenbeläge behandelt. Sie haben gelernt, wie Sie eine RubyMotion-Anwendung einrichten und ausführen, Sie haben mit Interface Builder gearbeitet und eine Benutzeroberfläche erstellt.

Im zweiten Teil dieses Tutorials werden Sie tiefer in das Model-View-Controller-Muster unter iOS und in der Organisation Ihrer Anwendung eingewiesen. Sie fügen auch eine Malansicht hinzu und schreiben den Code, mit dem der Benutzer zeichnen kann. Bleib dran.