Aller au contenu


Photo

accès variables de connexion[réglé]


  • Please log in to reply
64 réponses à ce sujet

#41 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 888 messages
  • LocationPlestin-les-Grèves (22)

Posté 30 janvier 2017 - 10:50

Dans le développement d'un logiciel, tu profiterais plus de le faire pas après pas.

 

D'abord, nous avons commencé à construire la struct singleton qui emballera toute la fonctionnalité SQLite.

 

Avant d'écrire le code qui parlera avec le framework, il faut vérifier si l'emballage marche comme prévu. on peut renvoyé les données de test avant de toucher la vrai fonctionnalité de SQLite.swift.

 

Est-ce que tu as testé que, si on mettait le mauvais chemin vers un fichier, que le code réagisse correctement, en renvoyant nil pour le singleton ? Et pour un bon chemin, qu'il renvoie une référence valide ?



#42 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 30 janvier 2017 - 10:55

alors comme je te disais, là, j'ai des erreurs à la compilation, j'en ai trouvé une ou deux (de petites erreurs de nom d'objet du Framework)

mais si tu vois mes annotations (dans le code) tu verras que la méthode fetchTableMetadata me pose soucis, ainsi que son appel dans le ViewController.



#43 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 888 messages
  • LocationPlestin-les-Grèves (22)

Posté 30 janvier 2017 - 11:03

Désolée ; erreur de copier/coller.

    // On affiche "juste" si la connexion est ok ou pas:
    // j'ai plusieurs erreurs sur cette méthode et je ne comprends pas le "rethrows" ? :
    'rethrows' function must take a throwing function argument
   
    mutating func fetchTableMetadata() rethrows
    {
        guard let dbQueue = self.dbQueue else
        {
            throw ConnexionError.dbQueueError
        }
        
        // ...
    }

... devrait être :

    mutating func fetchTableMetadata() throws
    {
        guard let dbQueue = self.dbQueue else
        {
            throw ConnexionError.dbQueueError
        }
        
        // ...
    }

Et :

// là encore j'ai une erreur et je ne comprends pas, dans le sens ou connexion n'est jamais utilisé :
        guard let connexion = ConnexionSQLite.sharedInstance else
        {
            print("nil connexion")
            
            return
        }
        
        print("bonne connexion")

Là, ce n'est pas une erreur ; tout simplement un avertissement que l'on n'a pas encore utiliser en cas d'avoir une bonne connexion.



#44 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 888 messages
  • LocationPlestin-les-Grèves (22)

Posté 30 janvier 2017 - 11:11

En plus, pourquoi "dbQueue" ? C'est désormais "connexion" n'est-ce pas ?



#45 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 30 janvier 2017 - 11:16

je pensais que le "rethrows" étant important, par rapport à un "throws" que je connais bien... 

 

bref, tout fonctionne très bien maintenant, juste 2 warning pour cause de 2 variables non (encore) utilisé.

 

et oui, tout à fait pour le moment je ne fais que de me connecter :)

donc, j'ai bien le message console 

bonne connexion

et dans les annotations de mon code, je me suis planté ! 

// pour le moment je ne me sert pas de cette fonction ! :)    
mutating func fetchTableMetadata()throws
    {
        guard let connexion = self.connexion else
        {
            throw ConnexionError.dbQueueError
        }
        
        // ...
    }


#46 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 888 messages
  • LocationPlestin-les-Grèves (22)

Posté 30 janvier 2017 - 11:40

:clap:  :clap:  :clap:

 

Prochain pas...

 

Auparavant, tu avais du code pour récupérer les métadonnées ;

    {
      let tables = try dbQueue.inDatabase
      {
        db in
        
        try Row.fetchAll(db, "SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'")
      }
      
      for row in tables
      {
        let table: String = row.value(named: "name")

        let tables_data = try dbQueue.inDatabase
        {
          db in
          
          try Row.fetchAll(db, "SELECT * FROM \(table)")
        }
        
        self.resultSet = tables_data
      }
    }
    catch
    {
      print(error)
    }

Si je ne me trompes pas, tu itères sur les noms des tables, et à l'intérieur de cette boucle, tu récupères les données par les colonnes là dedans. Mais tu ne stockes pas les noms des tables. Du coup, tu auras, seulement, une list des colonnes sans aucune relation avec leurs table.

 

Je crois que, à la place d'une liste des métadonnées des colonnes tu devrais avoir un dictionnaire avec, pour les clés, les noms des tables et, pour les valeurs, les listes des métadonnées.

 

Du coup :

  private var _resultSet: [String : [Row]]?
  
  internal private(set) var resultSet: [String : [Row]]?
  {
    get
    {
      return _resultSet
    }
    mutating set
    {
      _resultSet = newValue
    }
  }

Et, pour le code de récupération, quelque chose comme ci : 

      guard var resultSet = self.resultSet else
      {
        return
      }
      
      for row in tables
      {
        let tableName: String = row.value(named: "name")

        let tableData = try dbQueue.inDatabase
        {
          db in
          
          try Row.fetchAll(db, "SELECT * FROM \(table)")
        }
        
        resultSet[tableName] = Array(tableData) // ou equivalent
      }


#47 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 30 janvier 2017 - 11:58

oui tout à fait ça.

 

je vais préparer la bonne méthode et je la post :)

 

Edit :

    mutating func fetchTableMetadata()throws
    {
        guard let connexion = self.connexion else
        {
            throw ConnexionError.dbQueueError
        }
            do
            {
                // récupère toutes les tables :
                let tables = try connexion.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'")

                
                let mutableArray:[String:Row] = []
                for table in tables
                {
                        // récupère toutes les données de chaque tables :
                        let metaDataTables = try connexion.prepare("SELECT * FROM \(table)")
                    
                        for metaDataTable in metaDataTables
                        {
                            //mutableArray[table] = metaDataTable
                            print(metaDataTable)
                        }
                        
                        print(mutableArray)
                }
            }
            catch
            {
                return print(error)
            }
    }

Edit:

par contre j'ai un retour de ma requête sur la console de debug avec une structure pas propre :

Exemple de la documentation: 
let stmt = try db.prepare("SELECT id, email FROM users")
for row in stmt {
for (index, name) in stmt.columnNames.enumerate() {
print ("\(name)=\(row[index]!)")
// voici ce que la console affiche -->  id: Optional(1), email: Optional("alice@mac.com")
}
}

je ne trouve pas comment retiré ce superflu ?j'aimerais juste voir la table (exemple)"console"

Du coup, je ne peu pas continuer mon autre requête avec ce genre de résultat.



#48 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 888 messages
  • LocationPlestin-les-Grèves (22)

Posté 30 janvier 2017 - 19:18

Qu'est-ce que j'ai dit ? Petit pas  :-*

      do
      {
        let tables = try connexion.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'")

Je devine un peu, car je n'ai pas installé SQLite.swift, mais selon le code dans Statement.swift, on y trouvera une var columnNames qui est de type [String]. Du coup, il vaut mieux d'écrire :

    do
    {
      let tableStatement = try connexion.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'")
      
      self.resultSet = [String : [String]]()
      
      for row in tableStatement
      {
        let tableName = row[0] as String
        
        var columnNames = [String]()
        
        let columnStatement = try connexion.prepare("SELECT * FROM \(tableName)")
        
        for columnName in columnStatement.columnNames
        {
          columnNames.append(columnName)
        }
        
        self.resultSet?[tableName] = columnNames
      }
    }

Je ne l'ai pas passé par le compilateur mais il semble plus ou moins correct. Sinon, dis moi  ::)



#49 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 30 janvier 2017 - 19:38

;)

 

alors je te remet le code complet :

import Foundation
import SQLite

struct ConnexionSQLite
{
    // Création d'une liste de type Error, pour personnaliser et afficher les erreurs de connexion:
    enum ConnexionError : Error
    {
        case dbQueueError
    }

    private var _resultSet: [String : [Row]]?
    
    internal private(set) var resultSet: [String : [Row]]?
        {
        get
        {
            return _resultSet
        }
        mutating set
        {
            _resultSet = newValue
        }
    }
    
    // Création du Singleton:
    static var sharedInstance: ConnexionSQLite? = ConnexionSQLite()
    
    
    // Création, test et affectation de la variable de connexion à la base de données:
    private lazy var connexion: Connection? =
    {
        do
        {
            // Si le test de la connexion est réussis on renvoi connexion:
            let connexion = try Connection("games.sqlite3") // pour tester
                
            return connexion
        }
        catch
        {
            return nil
        }
    }()
    
    // A l'instanciation du Singleton on test si fetchTableMetadata est valide puis il est appelé:
    private init?()
    {
        do
        {
            try self.fetchTableMetadata()
        }
        catch
        {
            return nil
        }
    }

    mutating func fetchTableMetadata()throws
    {
        guard let connexion = self.connexion else
        {
            throw ConnexionError.dbQueueError
        }
            do
            {
                let tableStatement = try connexion.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'")
                
                self.resultSet = [String : [String]]()
                
                for row in tableStatement
                {
                    let tableName = row[0] as String // comme proposition de correction ? : let tableName = row[0] as! String
                    
                    var columnNames = [String]()
                    
                    let columnStatement = try connexion.prepare("SELECT * FROM \(tableName)")
                    
                    for columnName in columnStatement.columnNames
                    {
                        columnNames.append(columnName)
                    }
                    
                    self.resultSet?[tableName] = columnNames
                }
            }
            catch
            {
                print(error)
            }
    }
}

j'ai deux erreurs à la compilation :

Cannot assign value of type '[String : [String]]' to type '[String : [Row]]?'

'Binding?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?

donc un soucis de "optional" et un soucis de parse, si je dis pas de bêtises.

 

 

Edit:

en débogant je m'aperçois que je récupère bien toutes mes tables (sans le optional()) donc très bien :)

mais arrivé ici :

                    for columnName in columnStatement.columnNames
                    {
                        print(columnNames.append(columnName))
                    }
                    
// j'ai tout une série de "()" vide...  

tout est vide... donc je pense que le type est pas encore le bon .



#50 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 30 janvier 2017 - 21:08

je re post, pour plus de clarté...

 

 

Après avoir tout débogué tout fonctionne bien !

le seul problème que je rencontre est que ceci :

                    for columnName in columnStatement.columnNames
                    {
                        columnNames.append(columnName)
                    }

ramène uniquement les entêtes des des colonnes de mes tables

donc, par exemple le schéma :

Par table je récupère ceci :

id

name

description

date

etc.

donc, pas encore les données... :( pour remplir mon dictionary:

resultSet[columnName] = les données

 

de plus, le type de resultSet est faux :

self.resultSet = [String : [Row]]()
// ou j'ai encore testé ceci :
self.resultSet = [String : [String]]()


#51 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 888 messages
  • LocationPlestin-les-Grèves (22)

Posté 30 janvier 2017 - 22:26

Ah, tu voulais les données ! J'ai cru que tu voulais les métadonnées.

 

Dans ce cas là, c'est le code dans les docs qu'il faut suivre :

    do
    {
      let tableStatement = try connexion.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'")
      
      self.resultSet = [String : [Any]]()
      
      for row in tableStatement
      {
        let tableName = row[0] as String
        
        let columnStatement = try connexion.prepare("SELECT * FROM \(tableName)")
        
        var rowData = [Any]()
        
        for dataRow in columnStatement
        {
          for (index, _) in columnStatement.columnNames.enumerate()

          rowData.append(row[index])
        }
        
        self.resultSet?[tableName] = columnNames
      }
    }

Et, il faut changer le type de resultSet et _resultSet vers [String : [Any]]

 

Mais, attention ! Tu auras tous les données de plusieurs rangs pour chaque table, sans séparation entre les rangs.

 

de plus, le type de resultSet est faux :

self.resultSet = [String : [Row]]()
// ou j'ai encore testé ceci :
self.resultSet = [String : [String]]()

 

 

Bah ouais ! Le type Row n'est pas utilisé dans cet exemple ; c'était du projet avec GRDB. Et, comme j'ai dit ci-dessus, il faut le changer encore une fois  8--)



#52 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 31 janvier 2017 - 10:06

bonjour Joanna Carter,

Et bien en fait ce n'est pas une si mauvaise idée :) de plus tu m'as devancé, j'étais en train justement de fouiller 

je prends les header (que tu m'as fait stocker via columnNames.append(columnName)

Puis, je les stocke dans un nouveau dictionary, ayant pour key:value :

header-->data (soit les info de mes tables)

niveau conception je ne sais pas ce que tu en penses ? Ça me parait propre.



#53 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 888 messages
  • LocationPlestin-les-Grèves (22)

Posté 31 janvier 2017 - 11:39

J'ai pu comprendre pourquoi tu voulais récupérer les métadonnées d'une BDD mais, récupérer les données, toutes en même temps ? Ça me surprendrait.

 

Tu peux nous dire le but de cet exercice ? Qu'est-ce que tu comptes faire avec les données ? Les montrer dans une TableView ?

 

Surtout avec iOS, on est limité en mémoire disponible et, si le système d'exploitation marque une grimpe assez importante, il arrêtera l'appli. Du coup, il ne faut q'acquérir le minimum des données à une seule fois.

 

Normalement, pour montrer les données d'une BDD sans CoreData, il faut :

 

1. récupérer le nombre de rangs dans la table (pour dire à la TableView combien en total)

 

2. récupérer assez de rangs de la BDD pour remplir les rangs visible dans la TableView, en même temps notant l'index du dernier rang, afin que l'on puisse l'utiliser pour la prochaine requête avec quelque chose comme - maTable.limit(nombre, offset: dernierIndex)

 

En gros, je crois que tu as commencé à réinventer la roue des frameworks comme CoreData  ???  :-*

 

Est-ce que tu as une bonne raison pour choisir d'accéder une BDD direct, au lieu d'utiliser un framework déjà écrit ?



#54 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 31 janvier 2017 - 12:46

Alors concernant coreData, je ne connais pas du tout son fonctionnement, mais (peut être à tort) je pensais qu'il n'utilisait pas de base de données en SQLite3 (ou autre peu importe).

 

Pour faire simple, est ce que je ne pourrais pas utiliser ma base de données.SQLite3 via CoreData ?

 

Voici le détail de mon appli :

 

une base de données.SQLite3 contenant comme Tables :

 

jeux vidéos

   id,nom, date etc

genres

      id,nom

plateforme

   id,nom, date etc

etc.

 

et je souhaiterais tout récupérer au lancement de l'application, y affecter dans un tableau pour ensuite l'itérer pour effectivement :

 

1) alléger la ressource (en affectant à un tableau toutes les valeurs de mes tables, pour les itéré ensuite via des boucles et seulement à la demande)

2) remplir des tableView

et passer les data de vues en vues (mais ça, ce n'est pas pour maintenant)

et par la suite une synchronisation (de cette base embarqué) via un web service sur une autre base (backup)

 

Voilà vous savez tout ;)

 

Pour te répondre, je n'es aucune restriction ou réticence à utiliser tel ou tel outils.(j'ai suivi les conseils donnés dans mon autre poste, par des membres bien plus au fait que moi) C'est juste que je ne sais pas quelle façon de faire utiliser.

 

je suis parti sur un concept que je connais : une base SQLite/SQL.

 

Après, je me suis peut être planté dans ma façon de concevoir ?...



#55 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 01 février 2017 - 09:33

du coupe je ne sais pas trop si je cloture ce post, dite moi :)



#56 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 888 messages
  • LocationPlestin-les-Grèves (22)

Posté 01 février 2017 - 13:03

Alors concernant coreData, je ne connais pas du tout son fonctionnement, mais (peut être à tort) je pensais qu'il n'utilisait pas de base de données en SQLite3 (ou autre peu importe).

 

Pour faire simple, est ce que je ne pourrais pas utiliser ma base de données.SQLite3 via CoreData ?

 

Avec Core Data, les données peut être stockées dans : XML, format binaire, SQLite ou seulement en mémoire https://developer.ap...reFeatures.html

 

Core Data commence avec le modèle des objets et c'est Core Data qui s'occupe de faire la base de données. Il n'est pas possible d'utiliser une BDD existante. En disant ça, c'est bien possible, après avoir créé le modèle, de faire une appli avec laquelle on peut transférer les données.

 

Voici le détail de mon appli :

 

une base de données.SQLite3 contenant comme Tables :

 

jeux vidéos

   id,nom, date etc

genres

      id,nom

plateforme

   id,nom, date etc

etc.

 

et je souhaiterais tout récupérer au lancement de l'application, y affecter dans un tableau pour ensuite l'itérer pour effectivement :

 

1) alléger la ressource (en affectant à un tableau toutes les valeurs de mes tables, pour les itéré ensuite via des boucles et seulement à la demande)

2) remplir des tableView

et passer les data de vues en vues (mais ça, ce n'est pas pour maintenant)

et par la suite une synchronisation (de cette base embarqué) via un web service sur une autre base (backup)

 

Voilà vous savez tout ;)

 

Pour te répondre, je n'es aucune restriction ou réticence à utiliser tel ou tel outils.(j'ai suivi les conseils donnés dans mon autre poste, par des membres bien plus au fait que moi) C'est juste que je ne sais pas quelle façon de faire utiliser.

 

je suis parti sur un concept que je connais : une base SQLite/SQL.

 

Après, je me suis peut être planté dans ma façon de concevoir ?...

 

 

On a déjà parlé du concept d'un ORM et, bien, on pourrait se lancer en la création d'une telle bête ; mais, crois moi, c'est pas facile.

 

En fait, j'ai commencé à jouer avec et développer les ORMs il y a presque 20 ans (en Delphi) ; j'étais une des premières de les concevoir.

 

Crois moi - c'est dur !!!

 

Côté traduction des objet ver les tables, ça c'est assez facile mais, côté traductions des relations entre les objets vers les relations entre les tables, ça c'est vraiment sioux.

 

Si on voulais modeler une relation comme Facture -> Lignes de facture :

 

En objets c'est

class LigneDeFacture
{
  var article: Article
  
  var quantite: Int
  
  var prixUnite: Double
   
  var montant: Double
}

class Facture
{
  var date: Date
  
  var client: Client
  
  var lignes: [LigneDeFacture]
  
  var montant: Double
  {
    // renvoyer total des montants des lignes
  }
}

... mais avec une BDD, on parlerait de

Table LigneDeFacture
{
  id: Int
  
  factureID: Int
  
  articleID: Int
  
  quantite: Int
  
  prixUnite: Double
   
  montant: Double
}

class Facture
{
  id: Int
  
  date: Date
  
  clientID: Int
  
  montant: Double // calculé des montants des lignes
}

C'est le boulot d'un ORM de "traduire" cette différence entre telles structures objet et telles structures BDD.

 

Un ORM doit connaître comment écrire le SQL pour gérer le CRUD (création / récupération / mis à jour / suppression) des objets ; n'oubliant pas les suppressions en cascade.

 

Core Data s'en occupe pas mal, mais il faut apprendre comment ça marche. En tout cas, là, si on ne choisissait pas le stockage SQLite, on serait obligé de charger toutes les données en même temps - ce qui n'est pas bon pour la consommation de mémoire sur un iBidule.



#57 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 01 février 2017 - 13:43

Bonjour,

 

oui, donc on a bien fait de me conseiller GRDB.swift ou encore SQLite.swift (enfin ce dernier, non, je le déteste !) !

 

je vais pas me prendre la tête, car l'a honnêtement tout ça pour ça... cela prend une ampleur incroyable !

 

Je veux dire par là, que je souhaite simplement afficher des requêtes dans des tableView(et je me répète désolé tout ça est de la re, re dite...)

 

Et en toute honnêteté je ne pige pas pourquoi SQLite.swift est si complexe sans raison.

CoreData j'en veux pas, si je ne peux même pas maitrise mes requêtes et surtout utilisées une base déjà existante, je ne comprends même pas l'intérêt de ce Framework...

Exemple, je n'arrive toujours pas a afficher les données de mes tables sans ces optional() qui entoure chaque résulta de requêtes.

 

Je t'avoue que je suis à deux doigts de tout supprimer là !

Le pire c'est que je sais quoi faire, il y a tellement de parse à faire, je ne pige vraiment pas pourquoi ce n'est pas plus userFriendly...

Ce n'est pas du tout l'idée que je m'étais fait d'un petit projet tout bête.

Le fait de changer deux fois de Framework n'arrange rien, je dois en prendre un et m'y tenir et je pense fuir SQLite.swift qui est horrible, ou alors je n'ai rien pigé...

:(

 

 

Edit:

De plus, je ne veux pas vous déranger... quand je vois l'ampleur de mon post, pour pas de résulta, vous allez vous ennuyer 



#58 colas_

colas_

    Broyeur de fèves

  • Membre
  • PipPipPipPipPipPip
  • 1 431 messages

Posté 01 février 2017 - 21:47

Non n'abandonne pas !

small-logo.png

Mathématiques pour classes prépa et enseignement supérieur sur iPad et iPhone

www.improov.fr > < Improov sur facebook >


#59 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 01 février 2017 - 22:12

Lu,
Non, bien sur je suis tenace ! Demain from scratch sur du GRDB.Swif !
La nuit porte conseil...

Je dois comprendre ces maudits optional(), peut importe le Framework, ce n'est pas encore clair pour moi, mais via SQLite.swif c'est trop infernal...
Sinon, j'ai des soucis de compréhension pour les types des dictionary, il faut que j'étudie tout ça.

Merci beaucoup pour tes encouragements

#60 colas_

colas_

    Broyeur de fèves

  • Membre
  • PipPipPipPipPipPip
  • 1 431 messages

Posté 01 février 2017 - 22:20

Je te conseille d'isoler des sous-problèmes (par exemple sur les optional ou sur les dico) et d'ouvrir des nouvelles questions sur le forums. Regarde aussi un tuto sur les playgrounds Swift si tu ne connais pas.

Bon courage,
Je peux t'assurer que ce que tu cherches à faire n'est pas compliqué et que tu seras très content d'avoir peiné puis compris.

Question:
Combien y a-t-il de tables dans ta BDD ?
Combien y a-t-il de lignes dans la plus grosse à peu près ?
Qui met à jour la table (il me semble que ton appli ne fait que lire la BDD) ?
Quelle est la fréquence de write à peu près? (Tous les jours ? Semaine? Mois ?)


Sinon, CoreData et Realm c'est hyper classe, mais pour l'instant et pour ce que tu cherches à faire, SQL semble très adapté. Enfin, ça dépend de tes réponses aux questions ci-dessus.

small-logo.png

Mathématiques pour classes prépa et enseignement supérieur sur iPad et iPhone

www.improov.fr > < Improov sur facebook >





0 utilisateur(s) li(sen)t ce sujet

0 membre(s), 0 invité(s), 0 utilisateur(s) anonyme(s)