Sur la route d'Oxiane digressions diverses

LeBlog OXiane

10 jan
2012

iOS & Modal Partial Curl & SQLite

Pour poursuivre avec mon précédent billet (ici), j’ai eu l’envie de tester SQLite avec iOS.

Qu’est-ce que SQLite ?

En gros, c’est une base de données légère intégrée au programme stockée dans un fichier.

Plus d’informations sur le site officiel et sur wikipedia.

L’intérêt est donc d’avoir peu de données à mettre dans notre base embarquée car une app trop lourde est souvent rédhibitoire pour une installation sur iPhone.

Je conseillerai de ne pas dépasser les 100 ko pour rester cohérent.

Comment fait-on alors ?

Et bien par chance, SQLite est déjà installée sous Mac !

Pour vérifier, tapez dans le terminal :

sqlite3 -version

Nous allons donc créer une base de données tuto.db avec une table Objet ayant pour champs num et forme, toujours dans le terminal :

sqlite3 tuto.db

puis

sqlite> CREATE TABLE Objet(num integer primary key, forme varchar(25));
sqlite> INSERT INTO Objet(num, forme) VALUES(1,cercle);
sqlite> INSERT INTO Objet(num, forme) VALUES(1,carre);
sqlite> INSERT INTO Objet(num, forme) VALUES(1,triangle);

Si vous voulez encore vous amusez avec SQLite, tapez .help pour afficher les commandes sinon tapez .quit ou .exit.

Et voilà, nous avons un joli fichier tuto.db à l’endroit où vous avez ouvert le terminal (généralement votre répertoire personnel).

Ouvrez votre projet PageTrick (cf lien plus haut) et glissez/déposez-y votre fichier.
Ajoutez-y également la bibliothèque libsqlite3.0.dylib :
- cliquez sur votre projet dans le menu contextuel
- cliquez sur Targets puis sur Build Phases
- cliquez sur le + du sous-menu Link Binaries With Library
- dans la barre de recherche tapez libsqlite
- déroulez les résultats vous devriez avoir libsqlite3.0.dylib (ne vous trompez pas il y en a deux, l’autre c’est libsqlite3.dylib)
- c’est bon !

Génial et maintenant comment s’en sert-on ? C’est à ce moment que l’on doit faire un choix, en effet SQLite étant une bibliothèque écrite en C, il va falloir insérer des appels de fonction C dans notre joli code Objective-C… pas glop (personnellement) MAIS on peut utiliser un petit framework (2 classes) créer par Th30z et disponible sur GitHub.

Dézippez l’archive et glissez/déposez Sqlite.h et Sqlite.m dans votre projet.

Attention si vous êtes dans un projet avec ARC (Automatic Reference Counting) activé – il faut modifier un peu le Sqlite.m mais c’est trois fois rien :
- supprimez tous les autorelease, retain, release qui traînent
- remplacez la ligne 32 par :

return (__bridge NSString *)uuidStringRef;

Plus de détails sur ce cast sur clang.llvm.org.

Maintenant vous pouvez utiliser l’objet Sqlite dans votre code.

Dans votre storyboard, déposer un UITableViewController et faîtes un segue depuis un bouton « clickSQLite » (le sosie du bouton « click » du PageTrickController) vers lui et n’oubliez pas de donner un identifiant au segue.

Voici ce que vous devriez avoir modulo les préférences esthétiques de chacun :

Créez une nouvelle classe (UIViewController class) héritant de UITableViewController et appelez la TablePageCurlController par exemple.

Ensuite on reprend le même principe de délégation vu dans mon billet précédent sauf que l’on va créer un fichier pour le protocole genre PageCurlDelegate.h :

#import <UIKit/UIKit.h>
@protocol PageCurlDelegate -(void)dismissWithData:(NSString *)data;
@end
#import <UIKit/UIKit.h>;
#import "PageCurlDelegate.h";

@interface TablePageCurlController : UITableViewController
@property(nonatomic, weak) id<PageCurlDelegate> delegate;
@property(nonatomic) NSInteger nbRow;
@property(nonatomic, strong) NSArray *objects;
@end

on n’oublie pas de synthétiser !

@synthesize delegate = _delegate, nbRow = _nbRow, objects = _objects;

on complète les méthodes de notre contrôleur :

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return _nbRow;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  static NSString *CellIdentifier = @"myCell";
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if(!cell){
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
  }

  NSDictionary * objet = [_objects objectAtIndex:indexPath.row];
  id num = [objet objectForKey:@"num"];
  if([num isKindOfClass:[NSNumber class]]){
    if([num intValue] == indexPath.row+1){
      cell.textLabel.text = [objet objectForKey:@"forme"];
    }
  }
  return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  [self.delegate dismissWithData:[tableView cellForRowAtIndexPath:indexPath].textLabel.text];
}

puis dans PageTrickController, on ajoute une propriété tablePage de type TablePageCurlController et on modifie :

// (dans l'interface) ajout dont je parlais
@property(nonatomic, strong) TablePageCurlController * tablePage;

// (dans l'implémentation)
-(void)dismissWithData:(NSString *)data{

  NSLog(@"%@", data);

  [_page dismissModalViewControllerAnimated:YES];
  _page = nil;
  [_tablePage dismissModalViewControllerAnimated:YES];
  _tablePage = nil;
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
  if([segue.identifier isEqualToString:@"tableModalCurl"]){
    _tablePage = segue.destinationViewController;
    _tablePage.delegate = self;

    //création de l'objet Sqlite
    Sqlite *sqlite = [[Sqlite alloc] init];

    //récupération de la base de données
    NSString *dbPath = [[NSBundle mainBundle] pathForResource:@"obj" ofType:@"db"];

    //ouverture de la connexion vers la base
    if(![sqlite open:dbPath]) return;
      NSArray *objs = [sqlite executeQuery:@"SELECT * FROM Objet"];

      //fermeture de la connexion
      [sqlite close];
     _tablePage.nbRow = objs.count;
     _tablePage.objects = objs;

    }else if([segue.identifier isEqualToString:@"modalCurl"]){
      _page = segue.destinationViewController;
      _page.delegate = self;
    }
  }
}

Alors heureux ?
« Aaaargh mais nan, on ne voit pas la tableView !!!! »

Ah oui, c’est vrai la tableView est en partie masquée par l’animation et du coup c’est moche.
Rajoutez ceci dans le viewDidAppear de votre TablePageCurlController :

-(void)viewDidAppear:(BOOL)animated { 

  [super viewDidAppear:animated];
  [self.tableView setContentOffset:CGPointMake(0, -self.tableView.frame.size.height/4) animated:YES];
  //[self.tableView reloadData]; // pas nécessaire : si vous avez des soucis de sélection
  //[self.view setNeedDisplay]; // pas nécessaire : faîtes plutôt un clean du projet d'abord
}

Et voilà deux belles animations pour le prix d’une !

Manuel François

tHeFeaTuReDMaN

  • Pingback: Sur la route d'Oxiane » Blog Archive » iOS & Core Data » Sur la route d'Oxiane

  • jjab

    good tutoriel, mais j’ai une question j’ai un projet qui contient un uitableview , je veux le lier avec storyboard, comment faire pour ajouter ce storyboard et lier ceci avec tablview, c’est à dire cliquer sur un bouton depuis storyboard m’amene a mon tableview

  • Manuel FRANCOIS

    Salut jjab,

    ta phrase est assez bizarre (aurais-tu utilisé google traduction ?) mais je crois que j’ai saisi la question.
    Si j’ai bien compris :
    - tu as une classe X qui hérite de UITableView et tu voudrais la lier à une storyboard

    Pour cela il suffit juste, dans ton storyboard, de déposer un UITableViewController puis de faire apparaître l’inspecteur d’identité (voir mon billet précédent ici : http://blog.oxiane.com/2011/12/29/ios-modal-partial-curl/ vers le milieu, je me cite : »- retournez dans le storyboard et changer la classe du nouveau UIViewController en PageCurlController (par exemple) dans l’inspecteur d’identité »).

    Tu choisis la classe X dans l’inspecteur et voilà !

    Si tu as d’autres questions n’hésites pas !

    @+