RubyMotion est un framework qui vous permet de créer des applications iOS en Ruby. Il vous offre tous les avantages du langage Ruby, mais comme votre code est compilé en code machine, vous bénéficiez de toutes les performances brutes du développement en Objective-C. RubyMotion vous permet d'utiliser le SDK iOS directement, ce qui signifie que vous avez accès à toutes les dernières fonctionnalités de la plate-forme. Vous pouvez inclure du code Objective-C dans votre projet et RubyMotion fonctionne même avec CocoaPods..
Dans ce tutoriel, vous allez créer une application de peinture à partir de zéro. Je vais vous montrer comment incorporer Interface Builder dans votre flux de travail et comment tester correctement votre application. Si vous n'avez aucune expérience préalable avec iOS ou Ruby, je vous recommanderais d'en apprendre plus sur celles-ci en premier. Les guides Tuts + Ruby for Newbies et Learning iOS SDK Development from Scratch constituent un excellent point de départ..
Avant de pouvoir commencer à coder, vous devez installer et configurer RubyMotion. Pour plus d'informations sur cette opération, consultez la section Prérequis du guide de démarrage de RubyMotion..
Cela fait, ouvrez votre terminal et créez un nouveau projet RubyMotion en lançant:
motion create paint cd paint
Cela crée un peindre répertoire et plusieurs fichiers:
rake -T
depuis la ligne de commande.RubyMotion génère également un spec / main_spec.rb fichier. Je vais vous montrer comment tester votre application un peu plus tard dans ce tutoriel. Pour l'instant, vous pouvez supprimer ce fichier en exécutant rm spec / main_spec.rb
depuis la ligne de commande.
Installez les dépendances de votre application en lançant installation groupée
suivi par bundle exec rake
pour commencer votre application.
Woohoo! Un écran noir Tu vas le rendre plus intéressant dans une minute.
Même s'il est agréable d'avoir une application en cours d'exécution, un écran noir est un peu ennuyeux. Ajoutons un peu de couleur.
Comme le SDK iOS natif, RubyMotion ne vous oblige pas à organiser vos fichiers de manière spécifique. Cependant, il est utile de créer quelques dossiers dans le répertoire. app répertoire pour garder votre projet organisé. Exécutez les commandes suivantes à partir de la ligne de commande pour créer un répertoire pour vos modèles, vues et contrôleurs..
mkdir app / modèles mkdir app / vues mkdir app / contrôleurs
Ensuite, jetez un oeil à l'intérieur du app / app_delegate.rb fichier:
Classe AppDelegate def application (application, didFinishLaunchingWithOptions: launchOptions) true end end
Si vous connaissez le développement iOS, vous remarquerez que cette méthode appartient à la UIApplicationDelegate
protocole, qui fournit plusieurs points d'ancrage dans le cycle de vie de l'application. Notez que le AppDéléguer
la classe ne déclare pas qu'elle implémente la UIApplicationDelegate
protocole. Ruby s'appuie sur le dactylographie car il ne prend pas en charge les protocoles. Cela signifie qu'il ne s'inquiète pas de savoir si votre classe dit implémenter un protocole, cela ne le concerne que si elle implémente les méthodes correctes.
La définition de la application: didFinishLaunchingWithOptions:
méthode à l'intérieur du AppDéléguer
la classe peut sembler un peu étrange. En Objective-C, cette méthode s’écrirait comme ceci:
- (BOOL) application: (UIApplication *) application didFinishLaunchingWithOptions: (NSDictionary *) launchOptions;
Comme les noms de méthodes Objective-C peuvent être divisés en plusieurs parties, Ruby les implémente de manière unique. La première partie de application: didFinishLaunchingWithOptions:
est ce que serait le nom de la méthode en IRM. Le reste de la signature de la méthode est écrit comme des arguments de mots clés. Dans RubyMotion, application: didFinishLaunchingWithOptions:
est écrit comme ceci:
def application (application, didFinishLaunchingWithOptions: launchOptions) fin
Implémentons cette méthode.
classe AppDelegate def application (application, didFinishLaunchingWithOptions: launchOptions) @window = UIWindow.alloc.initWithFrame (UIScreen.mainScreen.bounds) à l’aune du système
Les deux premières lignes du application: didFinishLaunchingWithOptions:
method crée un nouvel objet window et en fait la fenêtre de clé de l'application. Pourquoi est-ce @la fenêtre
une variable d'instance? RubyMotion va ramasser la fenêtre à moins que nous la stockions. La dernière ligne de la méthode définit le contrôleur de vue racine de la fenêtre sur un nouveau contrôleur de vue vide..
Exécutez l'application pour que tout fonctionne encore.
Hmm. L'application s'exécute mais l'écran est toujours noir. Comment savez-vous que votre code fonctionne? Vous pouvez effectuer un contrôle de santé rapide en ajoutant ce qui suit au bas de la application: didFinishLaunchingWithOptions:
, avant vrai
. Assurez-vous de l'enlever avant de passer à autre chose.
@ window.rootViewController.view.backgroundColor = UIColor.yellowColor
Aucune application n'est complète sans une suite solide de tests. Les tests vous permettent de vous assurer que votre code fonctionne et vous permettent d'apporter des modifications sans craindre de casser le code existant..
RubyMotion est livré avec un port de la bibliothèque de tests Bacon. Si vous connaissez Rspec, Bacon se sentira très familier.
Pour commencer, reflétez le app structure de répertoire dans le spec répertoire en exécutant les commandes suivantes à partir de la ligne de commande.
mkdir spec / modèles mkdir spec / vues mkdir spec / contrôleurs
Ensuite, créez le AppDéléguer
Fichier de spécification de spec / app_delegate_spec.rb. Par convention, les fichiers source sont des miroirs dans le répertoire spec et ont _spec ajouté à la fin de leur nom de fichier.
Commencez cette classe en définissant un décrire
bloc qui indique au lecteur ce que votre fichier teste.
décrire AppDelegate do end
Ensuite, ajoutez une seconde décrire
bloquer dans le premier pour montrer que vous voulez tester le application: didFinishLaunchingWithOptions:
méthode.
décris AppDelegate décris "#application: didFinishLaunchingWithOptions:" do end end
Avez-vous remarqué le #
au début de la signature de la méthode? Par convention, les méthodes d'instance commencent par un hachage et les méthodes de classe commencent par un point.
Ensuite, ajoutez une spécification en utilisant un il
bloc.
décris AppDelegate décris "#application: didFinishLaunchingWithOptions:" fais-le "crée la fenêtre" do UIApplication.sharedApplication.windows.size.should == 1 end end end
Une des meilleures choses à propos de Bacon et des autres frameworks de test BDD est que les spécifications sont très claires sur ce qu’ils testent. Dans ce cas, vous vous assurez que le application: didFinishLaunchingWithOptions:
méthode crée une fenêtre.
Votre spec n'a pas à appeler le application: didFinishLaunchingWithOptions:
méthode directement. Cela s'appelle automatiquement lorsque Bacon lance votre application.
Exécutez les spécifications de votre application en exécutant bundle exec spécification
à partir de la ligne de commande. Vous devriez voir la sortie comme ceci:
1 spécifications (1 exigences), 0 échecs, 0 erreurs
Cela vous indique que Bacon a exécuté un test et n'a trouvé aucune erreur. Si l'une de vos spécifications échoue, vous verrez 1 échec
et Bacon imprimera une description détaillée du problème.
Ce qui précède fonctionne, mais vous utiliserez UIApplication.sharedApplication
pour toutes vos spécifications. Ce ne serait pas bien si vous pouviez saisir cet objet une fois et l'utiliser dans toutes les spécifications? Vous pouvez avec un avant
bloc.
décris AppDelegate décris "#application: didFinishLaunchingWithOptions:" faire avant de faire @application = UIApplication.sharedApplication end it "crée la fenêtre" do @ application.windows.size.should == 1 end end end
Maintenant, vous pouvez facilement ajouter le reste des spécifications de l'application.
décris AppDelegate décris "#application: didFinishLaunchingWithOptions:" faire avant de faire @application = UIApplication.sharedApplication end it "crée la fenêtre" do @ application.windows.ssh.should == 1 end it "crée la fenêtre" do @application " .windows.first.isKeyWindow.should.be.true end it "définit le contrôleur de vue racine" do @ application.windows.first.rootViewController.should.be.instance_of de UIViewController
Exécutez-les pour vous assurer que tout fonctionne avant de continuer.
Il existe plusieurs façons de créer l'interface utilisateur à l'aide de RubyMotion. Mon préféré est d'utiliser Interface Builder avec le bijou IB. Ouvrez votre Gemfile et ajoutez le joyau IB.
source 'https://rubygems.org' gem 'rake' gem 'ib'
Courir installation groupée
à partir de la ligne de commande pour installer la gemme. Si vous utilisez Git, ajoutez ib.xcodeproj
à ton .gitignore fichier.
Interface Builder fait partie de Xcode. Lancer Interface Builder en lançant bundle exec rake ib: ouvert
. Cela crée un projet Xcode adapté à votre application. Créez un nouveau fichier d'interface utilisateur en sélectionnant Nouveau> Fichier… de Xcode Fichier menu et sélectionnez Storyboard du Interface utilisateur catégorie à gauche. Cliquez sur Suivant deux fois pour compléter cette étape.
Enregistrez le storyboard dans le Ressources répertoire en tant que tableau principal. Ouvrez le storyboard dans Xcode et faites glisser un nouveau Contrôleur de vue en dedans de la Bibliothèque d'objets sur la droite. Met le Identifiant de Storyboard champ du contrôleur à PeintureContrôleur
.
Faites glisser une étiquette dans la vue du contrôleur de vue depuis le Bibliothèque d'objets à droite et mettre son texte à Bonjour
.
Ensuite, ouvrez app / app_delegateet remplacez la dernière ligne de application: didFinishLaunchingWithOptions:
avec ce qui suit:
storyboard = UIStoryboard.storyboardWithName ("main", bundle: nil) @ window.rootViewController = storyboard.instantiateInitialViewController
Ensuite, relancez les tests de votre application avec bundle exec spécification
pour s'assurer qu'ils passent encore. Remarquez comment vous n'avez pas eu à en changer? Les bonnes spécifications testent le comportement du code, pas sa mise en œuvre. Cela signifie que vous devriez pouvoir changer Comment votre code est implémenté et vos spécifications devraient toujours fonctionner. Exécutez votre application pour tester votre nouvelle interface utilisateur.
Ce que vous avez construit jusqu'à présent est excellent, mais ne serait-il pas agréable si votre application a réellement fait quelque chose? Dans cette section, vous allez ajouter les commandes permettant de changer la couleur du pinceau. Créez deux nouveaux fichiers, un contrôleur et ses spécifications, en exécutant les commandes suivantes.
appuyez sur app / controllers / painting_controller.rb appuyez sur spec / controllers / painting_controller_spec.rb
Mettre en œuvre le PeintureContrôleur
squelette avec sa spec.
classe PaintingController < UIViewController end
décrire PaintingController effectue des tests PaintingController,: storyboard => 'main',: id => 'PaintingController' end
RubyMotion traite les spécifications du contrôleur de manière particulière. le tests PaintingController,: storyboard => 'main',: id => 'PaintingController'
la ligne du fichier de spécification indique à RubyMotion d’utiliser le contrôleur avec un ID de storyboard PeintureContrôleur
dans le principale storyboard. Vous pouvez utiliser le manette
variable pour le tester.
Ensuite, vous devrez ajouter des sorties à votre contrôleur. Celles-ci vous permettent de connecter des objets à votre contrôleur dans Interface Builder..
classe 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
étendre IB
ajoute plusieurs méthodes à votre contrôleur, y compris sortie
. Vous avez ajouté cinq sorties, une pour chaque bouton..
Les images des boutons sont incluses dans les fichiers source de ce didacticiel. Téléchargez les images et copiez-les dans le Ressources annuaire. Vous devez régénérer votre projet Xcode pour permettre à Interface Builder de prendre en compte les modifications apportées. Le moyen le plus simple de le faire est de fermer Xcode et d’exécuter bundle exec rake ib: ouvert
, qui va rouvrir le projet.
Sélectionnez le contrôleur de vue et changez sa classe en PeintureContrôleur
.
Ouvrir spec / app_delegate_spec.rb et modifier la dernière spécification pour vérifier la PeintureContrôleur
classe.
il "définit le contrôleur de vue racine" do @ application.windows.first.rootViewController.should.be.instance_of PaintingController end
Ajoutez cinq boutons à la vue du contrôleur de vue en faisant glisser Bouton objets sur la vue depuis le Bibliothèque d'objets sur la droite.
Ces boutons sont un peu fades. Sélectionnez le premier bouton, changez son type en Douane
dans le Inspecteur d'attributs à droite et supprimer son titre. Assurez-vous que Défaut
l'état est sélectionné dans le Config d'état menu déroulant et définir l'image d'arrière-plan sur button_black.png
. Met le Teinte propriété du bouton à transparent.
Met le Config d'état menu déroulant à Choisi
et changez l’image d’arrière-plan en button_black_selected.png
.
dans le Inspecteur de taille, changer la largeur et la hauteur du bouton en 50
.
Répétez cette procédure pour les autres boutons.
L'étape suivante consiste à relier les boutons aux prises du contrôleur de vue que nous avons déclarées précédemment. Maintenez la Contrôle touche de votre clavier et faites glisser du contrôleur de vue vers le premier bouton. Un menu apparaîtra lorsque vous relâchez votre souris. Sélectionner black_button
du menu. Ensuite, maintenez le Contrôle faites glisser la souris du bouton vers le contrôleur de vue et choisissez le sélectionnez la couleur
méthode du menu qui apparaît. Répétez ces deux étapes pour les autres boutons.
Enfin, sélectionnez le premier bouton et cliquez sur le bouton Choisi case à cocher sous Contrôle dans le Inspecteur d'attributs.
Le moment est venu d'ajouter quelques spécifications utiles à spec / painting_controller_spec.rb.
décrire PaintingController fait des tests PaintingController,: storyboard => 'main',: id => 'PaintingController' décrire "#black_button" do it "est connecté au storyboard" faire controller.black_button.should.not.be.nil end end decrire "#purple_button" do it "est connecté au storyboard" do controller.purple_button.shot.not.be.nil end end decrire "#green_button" do it "est connecté au storyboard" do controller.green_button.should.not. be.nil end end décrire "#blue_button" do it "est connecté au storyboard" do controller.blue_button.shot.not.be.nil end end decrire "#white_button" do it "est connecté au storyboard" do controller. white_button.should.not.be.nil fin fin fin
Ces spécifications garantissent que les prises sont correctement connectées dans Interface Builder. Comme toujours, c'est une bonne idée de les exécuter avant de continuer pour s'assurer qu'ils réussissent tous..
Ensuite, vous allez implémenter le sélectionnez la couleur
méthode en PeintureContrôleur
. Lorsque cette méthode est appelée, le bouton tapé est sélectionné et le bouton précédemment sélectionné est désélectionné..
def select_color (expéditeur) [black_button, purple_button, green_button, blue_button, white_button] .each do | button | button.selected = false end expéditeur.selected = true end
Ajouter les spécifications à spec / controllers / painting_controller_spec.rb.
décrivent "#select_color" à faire avant de controller.select_color (controller.green_button) et de "désélectionne les autres couleurs" de 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 "sélectionne la couleur" do controller.green_button.state.should == UIControlStateSelected end end
Exécutez l'application et assurez-vous que la sélection du bouton fonctionne. Lorsque vous appuyez sur un bouton, sa taille devrait augmenter. Bien que ce soit cool, ce que vous voulez vraiment, c'est qu'une couleur soit sélectionnée lorsque vous appuyez sur le bouton. Ceci est facile à accomplir avec quelques ajouts.
Sugarcube est un ensemble d'extensions iOS pour RubyMotion qui simplifient plusieurs tâches, telles que la création de couleurs. Ajouter gem 'sucre'
à votre Gemfile et courir installation groupée
. Puis ajouter nécessite une "couleur sucre"
à ton Rakefile au dessus de Motion :: Projet :: App.setup
.
La gemme facilite la création de couleurs en utilisant leur code hexadécimal. dans le PeintureContrôleur
classe, ajoutez l'extrait de code suivant sous la déclaration des points de vente:
COLORS = ["# 333333" .uicolor, "# 7059ac" .uicolor, "# 196e76" .uicolor, "# 80a9cc" .uicolor, "#fafafa" .uicolor]
Ensuite, refactoriser le tableau de boutons dans sélectionnez la couleur
dans une méthode d'aide privée:
def select_color (expéditeur) buttons.each do | button | button.selected = false et sender.selected = true @color = COLORS [sender.tag] et des boutons de définition privés [black_button, purple_button, green_button, blue_button, white_button] end
Enfin, ajoutez une nouvelle méthode ci-dessous sélectionnez la couleur
qui retourne la couleur sélectionnée.
def selected_color COLORS [buttons.find_index | button | button.state == UIControlStateSelected] end
Cette méthode saisit l’index du bouton sélectionné et sélectionne la couleur qui lui correspond. Bien sûr, cette méthode ne serait pas complète sans tests.
decrire "#selected_color" faire avant de controller.select_color (controller.green_button) end it "retourne la couleur correcte" do controller.selected_color.should == PaintingController :: COLORS [2] end end
Exécutez à nouveau votre application pour vous assurer que tout fonctionne comme prévu..
Vous avez couvert beaucoup de terrain dans ce tutoriel. Vous avez appris à configurer et à exécuter une application RubyMotion, vous avez travaillé avec Interface Builder et vous avez construit une interface utilisateur..
Dans la deuxième partie de ce didacticiel, vous allez approfondir le modèle Model-View-Controller sur iOS et l'organisation de votre application. Vous allez également ajouter une vue en peinture et écrire le code qui permet à l'utilisateur de dessiner. Restez à l'écoute.