LoopBack + iOS, Getting started (read Data)!
Un petit Tuto rapide, depuis un moment je souhaitais reprendre le Dev iOS. Cela fait 3 4 ans que je ne m'y étais pas replongé réellement. Depuis, les technologies ont évolué, le Dev iOS et la publiciation d'applications ont été simplifiés, Swift est arrivé, NodeJS et AngularJS ...
Nous allons donc tenter de rassembler un peu tout ca. Réaliser un serveur NodeJS, qui sera interrogé par une application iOS Objtective-C (exemple en swift disponible sur Github). L'application iOS prendra en compte l'Universal Storyboard.
I/ Un serveur NodeJs
Pour commencer, il s'agit ici de créer un serveur NodeJS fournissant une API que l'application pourra interroger. Nous parlons de web service REST API. Plusieurs packages NPM permette de réaliser facilement ce genre de choses.
Je n'en ai pas testé d'autres pour le moment.
Ces packages permettent en quelques lignes de commande de générer une base d'application NodeJS MongoDB (ou autre). L'architecture, les modèles, les controllers ... toutes sortes de templates pourront être faits en quelques secondes. Bien que l'on aime parfois tout faire à la main ;)! C'est parfois pratique et cela permet un certain gain de temps.
Ici, nous utiliserons LoopBack.
Installer LoopBack
Npm doit être installé sur votre machine. Il faut commencer par installer LoopBack, cela peut prendre un certain temps :
npm install -g strongloop
Après un bon moment tout sera installé. Pour ceux qui ne sont pas assez patients, voici la justification du temps d'installation :
├── sl-blip@1.0.0
├── which@1.0.9
├── ini@1.3.3
├── async@0.9.0
├── read@1.0.5 (mute-stream@0.0.4)
├── nopt@3.0.1 (abbrev@1.0.5)
├── colors@1.0.3
├── debug@2.1.3 (ms@0.7.0)
├── optimist@0.6.1 (wordwrap@0.0.2, minimist@0.0.10)
├── nodefly-register@0.3.3
├── strong-start@1.0.3 (osenv@0.1.0, posix-getopt@1.1.0, lodash@3.7.0)
├── is2@0.0.13 (deep-is@0.1.2)
├── json-file-plus@2.0.0 (is@2.0.2, node.extend@1.1.3, promiseback@2.0.1)
├── fs.extra@1.2.1 (mkdirp@0.3.5, fs-extra@0.6.4, walk@2.2.1)
├── strong-build@1.0.3 (posix-getopt@1.1.0, shelljs@0.3.0, json-file-plus@1.0.7, lodash@2.4.1, vasync@1.6.3)
├── prompt@0.2.14 (revalidator@0.1.8, pkginfo@0.3.0, winston@0.8.3, utile@0.2.1)
├── strong-agent@1.4.0 (semver@2.2.1, strong-license@1.0.2)
├── strong-registry@1.1.4 (osenv@0.0.3, semver@2.3.2, bluebird@1.2.4, commander@2.8.0, rimraf@2.3.2, inquirer@0.4.1)
├── strong-deploy@1.2.0 (strong-url-defaults@1.0.0, posix-getopt@1.1.0, shelljs@0.3.0, concat-stream@1.4.8, strong-tunnel@1.1.1)
├── node-inspector@0.7.4 (opener@1.3.0, debug@0.8.1, async@0.8.0, yargs@1.2.6, strong-data-uri@0.1.1, rc@0.3.5, glob@3.2.11, ws@0.4.32, express@4.0.0)
├── loopback-sdk-angular-cli@1.1.4 (semver@2.3.2, loopback-sdk-angular@1.3.7, docular@0.6.6, express@3.20.2)
├── strong-mesh-models@5.0.3 (user-home@1.1.1, sprintf@0.1.5, osenv@0.1.0, strong-url-defaults@1.0.0, posix-getopt@1.1.0, serve-favicon@2.2.0, concat-stream@1.4.8, compression@1.4.3, errorhandler@1.3.5, lodash@3.7.0, strong-tunnel@1.1.1, loopback-boot@2.7.0, request@2.55.0, loopback-datasource-juggler@2.25.1, minkelite@1.0.0, loopback-explorer@1.7.2, loopback@2.16.3, strong-npm-ls@1.0.5)
├── strong-pm@3.1.9 (uid-number@0.0.5, chownr@0.0.1, osenv@0.1.0, npm-path@1.0.1, strong-url-defaults@1.0.0, posix-getopt@1.1.0, extsprintf@1.3.0, mkdirp@0.5.0, passwd-user@1.1.1, bl@0.9.4, concat-stream@1.4.8, serve-favicon@2.2.0, strong-service-install@1.1.2, errorhandler@1.3.5, compression@1.4.3, strong-control-channel@1.1.2, express@4.12.3, lodash@2.4.1, tar@1.0.3, strong-tunnel@1.1.1, strong-fork-cicada@1.1.2, http-auth@2.2.5, strong-npm-ls@1.0.5)
├── strong-supervisor@1.5.1 (dotenv@0.2.8, posix-getopt@1.1.0, heapdump@0.3.5, strong-fork-syslog@1.2.3, strong-control-channel@1.1.2, strong-cluster-control@2.0.1, strong-log-transformer@1.0.1, strong-statsd@2.0.2, strong-trace@1.2.0, strong-npm-ls@1.0.5)
├── generator-loopback@1.9.0 (inflection@1.7.0, chalk@0.5.1, yosay@1.0.3, request@2.55.0, loopback-swagger@2.0.0, yeoman-generator@0.18.10, loopback-workspace@3.10.1)
└── strong-arc@1.1.0 (opener@1.4.1, cookie-parser@1.3.4, split@0.3.3, serve-favicon@2.2.0, errorhandler@1.2.4, http-proxy@1.10.1, fs-extra@0.14.0, ws@0.4.32, request@2.55.0, loopback-boot@2.7.0, loopback-datasource-juggler@2.25.1, express-jsxtransform@1.1.0, express@4.8.8, loopback@2.16.3, loopback-workspace@3.10.1, strong-pm@1.7.3, strong-mesh-client@1.4.0)
Créer son projet
Une fois cela fait, nous allons créer l'application Node.
slc loopback
[?] Enter a directory name where to create the project: waos-NodeIos
[?] What's the name of your application? waos-NodeIos
Nous allons maintenant créer un model de données nommé person
, et lui ajouter deux propriétés, firstname
and mail
cd waos-NodeIos
slc loopback:model
? Enter the model name: person
? Select the data-source to attach person to: db (memory)
? Select model's base class: PersistedModel
? Expose person via the REST API? Yes
? Custom plural form (used to build REST URL): people
Let's add some person properties now.
Enter an empty property name when done.
? Property name: firstname
invoke loopback:property
? Property type: string
? Required? Yes
Let's add another person property.
Enter an empty property name when done.
? Property name: mail
invoke loopback:property
? Property type: string
? Required? Yes
Let's add another person property.
Enter an empty property name when done.
? Property name:
Maintenant, lancer le serveur
node .
ou
slc run
Votre api doit être disponible sur le port 3000 de votre machine. Afin de le vérifier, rendez vous à l'adresse suivant : http://localhost:3000
vous devriez avoir un message de ce genre : {"started":"2015-04-18T20:34:31.489Z","uptime":616.44}
Vous pouvez alors accéder à l'explorer de loopback : http://localhost:3000/explorer
Insérer des données
De base, l'insertion avec LoopBack n'est pas persistante. Si nous souhaitons que nos POST, sur l'API soient conservés, même après un redémarrage de l'application, nous devons le préciser. Plusieurs solutions s'offrent à nous. En voici une, MongoDB.
-
MongoDB, il doit donc être installé sur votre machine.
Installons le connecteur :
npm install loopback-connector-mongodb --save
modifions le fichier adéquat :
waos-NodeIos/server/datasources.json
{ "db": { "name": "db", "connector": "mongodb" } }
Une fois la persistance des données mise en place, nous pouvons en insérer. Il faut se rendre sur l'explorer, http://localhost:3000/explorer .
A cette adresse est disponible l'ensemble des méthodes de votre API, auxquels il est possible de faire appel.
Soit pour notre model Person :
Plutôt couwl non ? ;)
Bien nous allons simplement utilister la méthode post / people
. Il suffit de cliquer dessus, et d'insérer une donnée comme ceci :
Cliquer alors sur Try i out!
. Si tout se passe bien vous aurez une réponse en 200
. Vous pourrez vérifier que l'insertion a fonctionné en allant faire un tour du coté de get / people
.
Tout est terminé, votre API tourne, nous pouvons donc passer à l'application IOS :).
Github server node (LoopBack)
Vous pouvez retrouver le code du serveur sur Github ici :).
II/ L'application iOS
Du coté de l'application iOS, nous n'allons pas rentrer dans le détail du code, libre a chacun d'approfondir. Seul les sections les plus importantes sont présentées ci-dessous.
Présentation du code
Importer LoopBack
#import <LoopBack/LoopBack.h>
Déclarations
@interface ViewController ()
@property (strong, nonatomic) LBRESTAdapter *adapter;
@property (strong, nonatomic) NSMutableArray *tableData;
@property (weak, nonatomic) IBOutlet UITableView *myTable;
@end
Initialiser la connexion à l'API
- (LBRESTAdapter *) adapter
{
if( !_adapter)
_adapter = [LBRESTAdapter adapterWithURL:[NSURL URLWithString:@"http://localhost:3000/api"]];
return _adapter;
}
Reqêter sur l'API
/*************************************************/
// Functions
/*************************************************/
- (void) getSomething {
void (^loadSuccessBlock)(NSArray *) = ^(NSArray *models) {
NSLog( @"selfSuccessBlock %lu", models.count);
NSLog(@"Success on Static Method result: %@", models);
[self.tableData removeAllObjects ];
for (int i = 0; i < models.count; i++) {
LBModel *modelInstance = (LBModel*)[models objectAtIndex:i];
[self.tableData addObject:modelInstance ];
}
[self.myTable reloadData];
};
void (^loadErrorBlock)(NSError *) = ^(NSError *error) {
NSLog( @"Error %@", error.description);
};
LBModelRepository *prototype = [ [self adapter] repositoryWithModelName:@"Something"];
[prototype allWithSuccess: loadSuccessBlock failure: loadErrorBlock];
};
Afficher les données
- (NSMutableArray *) tableData
{
if ( !_tableData) _tableData = [[NSMutableArray alloc] init];
return _tableData;
};
/*************************************************/
// Main
/*************************************************/
// Table View
/**************************************/
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = @"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
LBModel *model = (LBModel *)[self.tableData objectAtIndex:indexPath.row];
cell.textLabel.text = [[NSString alloc] initWithFormat:@"%@ - %@", [model objectForKeyedSubscript:@"firstname"] ,[model objectForKeyedSubscript:@"mail"] ];
return cell;
}
Github client iOS
Vous pouvez retrouver le code du client Objective-C
sur Github ici :).
Version Swift
ici :)
En espérant en avoir aidé certains dans leurs projets iOS. J'essayerais de maintenir les projets GitHub à jour avec les Maj Apple.
Edit (26/04/2015) Ce Tuto appartient à la série suivante :
- Tuto : LoopBack + iOS, Getting started (read Data)!
- Article : LoopBack + iOS, Insert Data !
- Article : iOS 8 : Swift, Getting Started
- Article : LoopBack + iOS, passons au Swift !