Aller au contenu


Photo

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


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

#21 colas_

colas_

    Broyeur de fèves

  • Membre
  • PipPipPipPipPipPip
  • 1 460 messages

Posté 28 janvier 2017 - 19:25

Tu ne peux mettre `nil` que aux types du genre `Row?`


small-logo.png

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

www.improov.fr > < Improov sur facebook >


#22 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 28 janvier 2017 - 19:26

J'ai bien compris le concept du singleton :

        ConnexionSQLite.sharedInstance.dbQueue

Mais je ne vois pas comment m'en servir suivant ce que j'ai expliqué, à savoir une méthode init() (appelée dans AppDelegate)

 

T'as appelé init() depuis l'AppDelegate ? Mais tu m'as dit que tu comprends le Singleton  :snif:

 

Je t'ai déjà dit qu'il faut mettre init en private, afin que l'on ne puisse pas l'appeler de l'extérieur de la classe.

 

init() n'est pas une méthode comme les autres. C'est réservée seulement pour l'initialisation d'un instance de la classe.

 

Le principe d'un Singleton, c'est que l'on ne puisse jamais avoir plus d'un instance ; chaque fois que tu appelles init() tu crées un nouveau instance.

 

Tu ne devrais pas avoir aucune logique dans init(), à part de ce qui contribue à la construction d'un instance.

 

init() ne doit être accessible que depuis l'initialisation de :

static let sharedInstance = ConnexionSQLite() 

... c'est là que l'appel à init() est fait.

 

Le seul moyen d'accéder le seul instance de ConnexionSQLite est d'appeler les méthodes (mais pas init() ) via Connexion.SQLite.sharedInstance

 

Pour moi (alors oui je ne comprends pas tout) faire ConnexionSQLite.sharedInstance.dbQueue dans chaque méthode pour accéder au dbQueue me parait faux, pourquoi ? Et bien niveau ressources utilisées,  je pensais ( peut être à tort...) que ce n'était pas bien.

 

No, si tu n'appelles pas init() tu ne gaspilles pas de ressources car, comme j'ai dit, il n'y aura plus qu'un instance.

 

donc, là, c'est ma dernière version, sans la méthode déjà décrite plus haut. Ou tout est dans le init(), ce que je n'aime pas.

 

Supprimes tous le code d'init() et le mettre dans une autre méthode



#23 colas_

colas_

    Broyeur de fèves

  • Membre
  • PipPipPipPipPipPip
  • 1 460 messages

Posté 28 janvier 2017 - 19:34

Supprimes tous le code d'init() et le mettre dans une autre méthode

 

Que tu pourras appeler `func fetchAllTables` par exemple ;-)


  • Joanna Carter aime ceci

small-logo.png

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

www.improov.fr > < Improov sur facebook >


#24 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 28 janvier 2017 - 19:37

Que tu pourras appeler `func fetchAllTables` par exemple ;-)

 

 

Mais oui  :bravo!:



#25 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 28 janvier 2017 - 19:56

bon je te remercie  :D

 

je vais tout refaire en suivant tes précieux conseils !

 

Sinon, oui j'avais cru comprendre le singleton et la méthode init(), mais je dois réviser... 

 

A force je me suis vraiment embrouillé, la pause s'impose, je prends du recul, vous relis, assimile et reviens vous dire !

 

Merci, pour ta patience et ta pédagogie Joanna Carter et merci aussi à toi colas_ et à tous les autres, mon seul but étant d'évoluer et de me débrouiller seul.

 

grâce à vous tous c'est engagé  ;)



#26 colas_

colas_

    Broyeur de fèves

  • Membre
  • PipPipPipPipPipPip
  • 1 460 messages

Posté 28 janvier 2017 - 20:07

La méthode init() n'est jamais appelée. Sauf, cas rares, dans certaines méthodes init().

 

Je laisse les swifters compléter si besoin est ;-)


small-logo.png

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

www.improov.fr > < Improov sur facebook >


#27 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 29 janvier 2017 - 11:23

salut,

Cette fois tout fonctionne bien.

Vos explications vont me permettre de mieux comprendre, cette fois ça été beaucoup plus clair.

 

Pour pouvoir me débrouiller seul (et surtout comprendre !)

Comment faire pour avoir une variable globale dans ma classe ?

 

J'ai bien mon resultSet (ma requête) mais j'aimerais pouvoir y disposer depuis l'ensemble de mon projet.

 

Ma question, est de comment connaitre le type à employer quand on ne le connait pas ?

 

Bien sûr, avec le debug me direz vous, il m'indique que table_datas est de type "Row" (sauf erreur de ma part ?)

 

du coup je tente de construire ma variable globale ainsi :

// Voici donc mes propositions :

var resultSet:String = ""
var resultSet:Row = nil
var resultSet:Row? = nil

// je ne comprends d'ailleurs pas ce que [:] est colas_ ?
var resultSet:[String:Row] = [:]
var resultSet:Row = [:]

// et pour y accéder :
ConnexionSQLite.sharedInstance.resultSet

// et voici comment je réalise l'affectation depuis ma requêtes :
ConnexionSQLite.sharedInstance.resultSet  = tables_data 
mais sans succès, le type est faux et l'affectation aussi je pense.
 
voici l'erreur retournée :
Cannot assign value of type '[Row]' to type 'Row?'


#28 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 29 janvier 2017 - 11:45

On ne peut pas avoir une variable globale dans une classe. Les globales sont déclarées hors de toutes classes.

 

Mais tu as déjà l'equivalent d'une globale avec ConnexionSQLite.sharedInstance. On peut l'accéder de n'importe quel code, partout dans le projet.

 

Tu dis que tu as ton resultSet mais je te demanderais où ça se trouve ? Tu utilises quel code pour créer et stocker le resultSet ?

 

Tu peux nous montrer le code qui appelle ConnexionSQLite pour faire ce que tu veux ?

 

Côté questions sur le sujet de colas :

[String : Row]

... signifie un dictionnaire avec les clés de type String et les valeurs de type Row.`

var resultSet: [String : Row] = [:]

... signifie l'initialisation d'une var de ce type avec un dictionnaire vide.

 

On pourrait aussi écrire :

var resultSet = [String : Row]()

... où le type de resultSet s'est déduit de la valeur qui est assignée



#29 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 29 janvier 2017 - 12:00

Tu dis que tu as ton resultSet mais je te demanderais où ça se trouve ? Tu utilises quel code pour créer et stocker le resultSet ?

 

Tu peux nous montrer le code qui appelle ConnexionSQLite pour faire ce que tu veux ?

 

Je comprends que ma déclaration de variable globale doit ce faire ailleurs, du coup appDelegate (je pense ?) mais quelle type utilisé (Row) et surtout quelle affectation ? puisque visiblement contrairement à ce que je pensais sur swift je dois lui assigné une affectation.

 

Avant ta réponse je le mettait la déclaration de resultSet dans ConnexionSQLite

struct ConnexionSQLite
{
    static var sharedInstance = ConnexionSQLite()
    var resultSet:Row?

               /***********/

et puis son affectation avec tables_data (ma requêtes)

    private init(){}
    
    func getallData()
    {
        // teste que self.dbQueue ne soit pas nil avant de l'utiliser
        guard let dbQueue = ConnexionSQLite.sharedInstance.dbQueue else
        {
            return
        }
        
        do
        {
            // récupère toutes les tables :
            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")
                
                // récupère toutes les données de chaque tables :
                let tables_data = try dbQueue.inDatabase
                {
                    db in
                    try Row.fetchAll(db, "SELECT * FROM \(table)")
                }
                   // affectation de resultSet avec tables_data (qui serait de type Row) :
                   ConnexionSQLite.sharedInstance.resultSet = tables_data
            }
        }
        catch
        {
            print(error)
        }
    }

et son appel depuis (par exemple pour moi) ViewController :

    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        let data = ConnexionSQLite.sharedInstance.resultSet
        print(data)
    }


#30 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 29 janvier 2017 - 13:39

Bah non !

 

Tu confonds toujours beaucoup de choses.

 

À l'intérieur de la struct ce n'est pas nécessaire d'utiliser sharedInstance, tous le code qui se trouve dans les méthodes de l'instance peuvent utiliser "self", qui fait référence à l'instance actuel.

 

Du coup, on aurait :

struct ConnexionSQLite
{
  static var sharedInstance = ConnexionSQLite()
  
  private var dbQueue: DatabaseQueue?
  
  var resultSet: Row?
  
  private init(){}
  
  func getallData()
  {
    guard let dbQueue = self.dbQueue else
    {
      return
    }
    
    do
    {
      // récupère toutes les tables :
      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")
        
        // récupère toutes les données de chaque tables :
        let tables_data = try dbQueue.inDatabase
          {
            db in
            try Row.fetchAll(db, "SELECT * FROM \(table)")
        }
        
        self.resultSet = tables_data
      }
    }
    catch
    {
      print(error)
    }
  }
}

J'ai essayé de recréer les types de GRDB (pour tester ton code), sans inclure GRDB lui-même, dans mon projet mais, malgré tous ça, le compilateur n'aime pas quelques lignes de ton code.



#31 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 29 janvier 2017 - 13:54

En plus...

 

Si tu crées ConnexionSQLite comme struct, tu devras marker la méthode getallData() comme mutating et écrire la var resultSet pour permettre la mutation.

  private var _resultSet: Row?
  
  var resultSet: Row?
  {
    get
    {
      return _resultSet
    }
    mutating set
    {
      _resultSet = newValue
    }
  }
  mutating func getallData()
  {
    ...
  }


#32 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 29 janvier 2017 - 13:55

Ça je l'avais déjà fait 

 var resultSet: Row?

Comprends moi bien, étant donné que cela ne fonctionnait toujours pas, j'ai essayé différentes choses

 

D'ou le code actuel.

 

Je me doute que dans la structure/classe peu importe, il faut utiliser la référence à CETTE instance, mais cela ne donnait rien donc, oui j'ai utilisé autre chose...

 

Tu sais comme dans un pointer-cliquer ou tu vois très bien ce qu'il faut faire, mais que rien de logique ne fonctionne et à un moment donné (désespoir) tu fais n'importe quoi...

 

Ayant la librairie d'installer, je n'ai AUCUNE autre erreur de compilation, juste celle du type pour ma variable, je ne vois pas d'ou viendrais ton souci, à part le fait que toi tu n'as pas installé les outils.

 

voilà, voilà...

 

Edit:

pour le mutable sur ma méthode, moi aussi le compilateur me l'avait proposé, mais en vain.



#33 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 29 janvier 2017 - 14:05

Ça je l'avais déjà fait 

 var resultSet: Row?

 

 

Bah, non, tu n'as pas fait ce que j'ai proposé. Il faut écrire la var comme je l'ai écrit et la var private.

 

Je me doute que dans la structure/classe peu importe, il faut utiliser la référence à CETTE instance, mais cela ne donnait rien donc, oui j'ai utilisé autre chose...

 

Quoi ? Tous que tu écris à importance sur la réussite de ton code.

 

Tu comprends le concept de self ? Si oui, dis moi ce tu en entends et pourquoi tu as essayé d'utiliser sharedInstance dans tes méthodes ?



#34 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 29 janvier 2017 - 14:31

self. fait référence à l'intance présente, donc à l'objet en cours.

Et pourquoi j'ai essayé de passer par le singleton ? comme déjà, car rien ne fonctionnait et je désespérais, donc j'ai fait des bêtises, pour tester le comportement...

 

Concernant ta proposition, je ne vois pas comment l'utiliser et ou la placer :

    var resultSet: Row?
        {
        get
        {
            return _resultSet
        }
        mutating set
        {
            _resultSet = newValue // je ne comprends pas d'ou sort newValue ?
        }

pour l'affectation ça je sais :


// self. ce réfère donc à la propriété de cette instance (donc du singleton) :
self.resultSet = tables_data

//puis pour l'appeler ailleurs dans mon projet, j(utilise l'instance de ConnexionSQLite (le singleton):
ConnexionSQLite.sharedInstance.resultSet

Mon raisonnement (ma compréhension) est il complètement à la ramasse, ou c'est correct ?

 

Edite :

 

Pour qu'il n'y est de mal entendu, voici mon code :

import Foundation
import GRDB

struct ConnexionSQLite
{
    static var sharedInstance = ConnexionSQLite()
    private var _resultSet: Row?
    
    var resultSet: Row?
        {
        get
        {
            return _resultSet
        }
        mutating set
        {
            _resultSet = newValue
        }
    }
    
    
    lazy var dbQueue: DatabaseQueue? =
        {
            do
            {
                let dbQueue = try DatabaseQueue(path: "games.sqlite3")
                return dbQueue
            }
            catch
            {
                print(error)
                return nil
            }
    }()
    
    private init(){/* je devrais appeler getallData() une fois l'instance créée la méthode charge resultSet et à mon appelle de resulSet (ailleurs) le contenu est dispo ?!  */}
    
    mutating func getallData()
    {
        guard let dbQueue = ConnexionSQLite.sharedInstance.dbQueue else
        {
            return
        }
        
        do
        {
            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)
        }
    }
}


ViewController pour l'appelle de ma méthode :

        let data = ConnexionSQLite.sharedInstance.resultSet
        print(data)

et avec ceci j'ai toujours la même erreur sur la ligne self.resultSet = tables_data

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



#35 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 29 janvier 2017 - 16:28

    guard let dbQueue = ConnexionSQLite.sharedInstance.dbQueue else
    {
      return
    }

Tu n'as pas corrigé cette référence à sharedInstance pour self

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

De ce que j'ai appris de GRDB, Row.fetchAll(...) renvoie un Array de Row [Row]. Du coup, resultSet devrait être de ce type, pas Row?

 

 

 

À part de ces fautes, tu peut nous dire exactement (sans code) ce que attends faire avec ce projet ?

 

Est-ce que tu veux accéder plusieurs BDD SQLite ?

 

Après avoir accéder le structure des tables, tu veux accéder les données là dedans ?



#36 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 29 janvier 2017 - 16:56

je ne comprends pas du tout ce que tu me dis, surtout concernant le ".self"

 

ce que tu as quoté est différent de ce que tu m'avais déjà proposé, si je fais un print() de tables_data, tout est ok ! donc mon erreur est bien au niveau de ma compréhension de la variable globale.

 

Et avant de continuer, j'aimerais déjà comprendre ceci : (et pas avancer bêtement)

    private var _resultSet:[Row] // j'ai modifié le type.
    
    var resultSet:[Row]
        {
        get
        {
            return _resultSet
        }
        mutating set
        {
            _resultSet = newValue
        }
    } 

par ce que là, cela me paume complètement..

 

tu voudrais que je fasse ça ? :

        guard let dbQueue = ConnexionSQLite.self.sharedInstance.dbQueue else
        {
            return
        }

Non... Je ne dois pas comprendre ce que tu me proposes, c'est pas possible autrement...

En plus, mon code fonctionne parfaitement sans erreur, jusqu'à l'affectation de la variable via table_datas.

 

ce que je veux ? (juste avoir les données de getAllData disponibles, soit en variable globale, soit en return)

 

Une fois que mon singleton est instancié, je veux déclencher la méthode getAllData, puis remplir une variable des datas récupérées par la requête, puis finalement pouvoir y accéder ailleurs, pour par exemple remplir une tableView.

 

Je ne vois pas pourquoi cela devient si complexe...

 

Donc, niveau conception, voilà ce que je vois dans les grandes lignes :

 

L'inti() (de ConnexionSQLite) contenant l'appel de la méthode {self.getAllData} et la méthode getAllData qui return une variable avec ... mes datas, ou une variable globale disponible.

 

Voilà, j'espère avoir été plus clair et je te remercie encore pour ton aide.

 

Edit :

 

ha oui, autre chose que vous avez surement déjà tous compris, mais je le re-précise :

 

Je souhaite au lancement de mon application, charger une variable de toutes les données de mes tables(via getAllData).

Pour ne plus refaire de requêtes et donc ne plus user de ressources.

Une itération au besoin, se fera depuis cette même variable pour en extraire son contenu et l'afficher dans une tableView ou autre. 



#37 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 29 janvier 2017 - 18:59

je ne comprends pas du tout ce que tu me dis, surtout concernant le ".self"

tu voudrais que je fasse ça :

        guard let dbQueue = ConnexionSQLite.self.sharedInstance.dbQueue else
        {
            return
        }

non je dois pas comprendre, c'est pas possible...

 

Non, c'est tout simplement :

    guard let dbQueue = self.dbQueue else
    {
      return
    }

Tu comprends ce que ça fasse ? Dis-moi.

 

 

ce que je veux ? (juste avoir les données de getAllData disponible)

 

Une fois que mon singleton est instancié, déclenché la méthode getAllData, puis remplir une variable des data récupérées par la requête, puis pouvoir y accéder ailleurs, pour par exemple remplir une tableView.

 

 

Bon. Après que tu as entendu comment coder la struct et ses méthodes correctement, avec les bons types

 

Je ne vois pas pourquoi cela est si complexe, mais pas du tout.

 

 

1. Il faut lire la documentation d'Apple sur le coding

 

2. Il faut lire la documentation pour GRDB, lire son code et comprendre ce qui se passe là. Sinon, tu ne pigeras jamais comment récupérer les données que tu veux.

 

Moi, je suis consultante, analyste, programmeuse et enseignante en analyse et programmation pendant 25 ans et, toujours, il met du temps pour apprendre les nouvelles compétences.

 

Mais il faut commencer avec les petits pas. On ne peut pas présumer que ce que l'on a appris dans un autre environnement convient dans un nouveau.

 

Du coup, je propose que tu recommences à zéro.

 

Tout d'abord, supprimes tous ton code.

 

Nous nous occuperons de parler avec un framework SQLite, qui contient plusieurs méthodes qui "throw" ; du coup, le code sera plus complexe que normal.

 

Allons-y...

struct ConnexionSQLite
{
  enum ConnexionError : Error
  {
    case dbQueueError
  }
  
  static var sharedInstance: ConnexionSQLite? = ConnexionSQLite()

D'abord, nous aurons besoin de nos propres Errors, on peut les étendre plus tard.

  private lazy var dbQueue: DatabaseQueue? =
  {
    do
    {
      let dbQueue = try DatabaseQueue(path: "games.sqlite3")
      
      return dbQueue
    }
    catch
    {
      return nil
    }
  }()

Tout dépendra si le fichier sqlite existe ou non. Si on ne le trouve pas, dbQueue renvoie nil.

 

Comment peut-on déterminer si la connection soit valide ou no ?

 

Dans le code de ViewController, ou autre, nous pourrions utiliser quelque chose comme :

    guard let connexion = ConnexionSQLite.sharedInstance else
    {
      return
    }

C'est à dire, si le fichier n'existe pas, le init() de ConnexionSQLite renverra nil, du coup, sharedInstance sera nil. Pour réaliser cette fonctionnalité, il faut créer un "failable initialiser" :

  private init?()
  {
    do
    {
      try self.fetchTableMetadata()
    }
    catch
    {
      return nil
    }
  }

Le code dans fetchTableMetadata sera le premier d'appeler notre lazy var dbQueue et, pour le tester, on fait :

  mutating func fetchTableMetadata() throws
  {
    throw ConnexionError.dbQueueError // seulement pour tester
    
  }

Maintenant, tous le code de dessus ensemble :

struct ConnexionSQLite
{
  enum ConnexionError : Error
  {
    case dbQueueError
  }
  
  static var sharedInstance: ConnexionSQLite? = ConnexionSQLite()
  
  private lazy var dbQueue: DatabaseQueue? =
  {
    do
    {
      let dbQueue = try DatabaseQueue(path: "fauxChemin.sqlite3") // pour tester
      
      return dbQueue
    }
    catch
    {
      return nil
    }
  }()
  
  private init?()
  {
    do
    {
      try self.fetchTableMetadata()
    }
    catch
    {
      return nil
    }
  }
  
  mutating func fetchTableMetadata() rethrows
  {
    guard let dbQueue = self.dbQueue else
    {
      throw ConnexionError.dbQueueError
    }
    
    // ...
  }
}

Et le code dans une ViewController :

  override func viewDidLoad()
  {
    super.viewDidLoad()
    
    guard let connexion = ConnexionSQLite.sharedInstance else
    {
      print("nil connexion")

      return
    }
    
    print("bonne connexion")
  }


#38 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 29 janvier 2017 - 19:21

 

Non, c'est tout simplement :

guard let dbQueue = self.dbQueue else
{
return
}

Tu comprends ce que ça fasse ? Dis-moi.

là, je comprends bien mieux ! ( et pour tout dire j'osais pas trop vous en parler, mais je trouvais ça étrange quand j'ai quoté mon code...)

L'instance état déjà créée, je n'ai donc pas besoin de faire ça :

ConnexionSQLite.sharedInstance.dbQueue
 

Par contre, comprends juste, que dans le feu de l'action et les copier/coller multiples j'ai énormément perdu confiance en moi et je n'ai pas vérifié les choses évidentes...

 

Bref, ceci étant, je comprends mieux ce que tu me disais pour ce morceau de code.

le .self réfère la variable du singleton (de l'instance)

exact ?

 

 

Du coup, je propose que tu recommences à zéro.

 

Tout d'abord, supprimes tous ton code.

 

Nous nous occuperons de parler avec un framework SQLite, qui contient plusieurs méthodes qui "throw" ; du coup, le code sera plus complexe que normal.

 

Allons-y...

 

 

 

Par contre tu veux que je recommence tout mon projet avec le framework https://github.com/s...is/SQLite.swift ?

 

Je me suis habitué à GRDB.swift et à sa syntaxe, si je change tout le temps, comprends que je serais encore plus perdu.

D'un point de vue pédagogique je ne pense pas que cela me soit très adapté.

 

Après si ce Framework est meilleur pour ma compréhension, ok. Mais il faut que cela me soit bénéfique.

 

Sur vos conseils à tous (surtout ceux de Céroce) j'avais décidé de choisir GRDB.swift, pourquoi encore changer ?

 

Sinon, je lis avec attention tes réponses et analyse tout ça, en ce moment même.

 

Edit :

Attention, ce n'est pas par fainéantise que je t'ai fait remarquer ma crainte de tout recommencer via un nouveau Framework !

j'utilise cocoapods, cela est très simple et rapide à initier...

Mais bien, pour en tiré bénéfice.

 

Edit 2:

 

Et avant de courir 2 lièvres en même temps, j'aimerais bien comprendre mon erreur, concernant la variable globale de mon code ?

À savoir récupérer toutes mes métas données de ma méthode getALLData dans (par exemple) la vue.

// exemple dans ma vue de ce que je souhaite :
 let data = ConnexionSQLite.sharedInstance.resultSet

...itération de data .... 

et bien séparer toutes mes classes/structures (MVC) comme je l'ai fait jusqu'à présent. Pour un meilleur débogage, je trouve ça plus sain, surtout quand on débute.

 

Edit 3 :

j'ai réglé mon souci de variable globale et j'avoue m'être bien pris la tête à chercher tout et n'importe quoi, alors que c'était très simple  :


// un tableau vide ressemble donc à ça :
var resultSet:[Row]=[]

// et non à ça :
var resultSet:[Row]=[:]



#39 Joanna Carter

Joanna Carter

    Broyeur de fèves

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

Posté 29 janvier 2017 - 22:35

Bref, ceci étant, je comprends mieux ce que tu me disais pour ce morceau de code.

le .self réfère la variable du singleton (de l'instance)

exact ?

 

Oui et non  ;)

 

La variable du singleton n'est qu'un membre statique de la struct/classe, qui tient un instance de la struct/classe et qui (dès son instantiation) vit pour la durée de vie de l'application.

 

On ne peut pas accéder self sauf si on est dans une des méthodes d'instance de la struct/classe. On peut dire que self est une référence interne, alors que tous les autres références sont là pour l'utilisation externe.

 

Si on créait plusieurs instances d'une struct/classe (non-singleton), self ferait référence à l'instance que l'on est en cours d'utiliser.

 

Une struct/classe se comporte comme un emporte-pièce ; tous que l'on trouve là dedans fait partie de l'emporte-pièce.

 

Les instance des structs/classes se comportent comme les petit gâteaux qui sont formées par l'emporte-pièce.

 

Un singleton est un emporte-pièce qui ne peut que créer un seul petit gâteau.

 

Par contre tu veux que je recommence tout mon projet avec le framework https://github.com/s...is/SQLite.swift ?

 

Je me suis habitué à GRDB.swift et à sa syntaxe, si je change tout le temps, comprends que je serais encore plus perdu.

D'un point de vue pédagogique je ne pense pas que cela me soit très adapté.

 

Après si ce Framework est meilleur pour ma compréhension, ok. Mais il faut que cela me soit bénéfique.

 

Sur vos conseils à tous (surtout ceux de Céroce) j'avais décidé de choisir GRDB.swift, pourquoi encore changer ?

 

 

Moi, je n'ai pas de préférence ; j'utilise CoreData qui fait l'arbitre entre le monde des objets et SQLite lui-même. Avec ça on ne travaille qu'avec les objets et CoreData s'occupe de leurs stockage et leurs récupération.

 

 

Et avant de courir 2 lièvres en même temps, j'aimerais bien comprendre mon erreur, concernant la variable globale de mon code ?

À savoir récupérer toutes mes métas données de ma méthode getALLData dans (par exemple) la vue.

 

 

S'il ne te dérange trop, il y a plus que je voudrais te montrer dans la méthode fetchTableMetadata mais il est tard.

 

Il suffit de dire, avant de m'endormir, que les noms des vars et méthodes devrait avoir une importance relatifs à leurs fonctionnes ; getAllData n'est pas le plus adapté pour décrire ce que tu fasse ; dans ce struct la, tu t'occupes plutôt des métadonnées d'un BDD, du coup, fetchTableMetadata  :)

 

À demain  -_-



#40 toolsDev

toolsDev

    Cueilleur de cabosses

  • Membre
  • PipPipPip
  • 93 messages

Posté 30 janvier 2017 - 09:43

Bonjour Joanna Carter,

Désolé pour hier soir je n'ai pas put venir.

 

Je viens de créer un projet avec SQLite.swift, la librairie est prête.

 

Tout est refait comme tu me l'as proposé, je vais maintenant analyser ton code, en y ajoutant des commentaires pour que tu puisses voir si je comprends bien tout avant d'avancer plus loin.

 

Conscient que tu prennes beaucoup de ton temps libre pour m'expliquer les concepts évoqué plus haut, sache que je te remercie pour le temps et la pédagogie que tu me donnes.  :bravo!: 

 

Edit

Voilà mon code, que j'ai un peut modifié car j'avais des erreurs :

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
    }
    
    // Création du Singleton:
    static var sharedInstance: ConnexionSQLite? = ConnexionSQLite()
    
    
    // Création, test et affectation de la variable de connexion à la base de données:
    // j'ai modifié le type DatabaseQueue pour Connection (je pense que tu as du te tromper, cette classe "Connection" n'existe pas.

    private lazy var dbQueue: Connection? =
    {
        do
        {
            // Si le test de la connexion est réussis on renvoi dbQueue:
            let dbQueue = try Connection("games.sqlite3")
                
            return dbQueue
        }
        catch
        {
            return nil
        }
    }()
    
    // A l'instanciation du Singleton fetchTableMetadata est appelé:
    private init?()
    {
        do
        {
            try self.fetchTableMetadata()
        }
        catch
        {
            return nil
        }
    }

    // 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
        }
        
        // ...
    }
}

ViewController:

// 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")





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

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