Почему сохранение данных в базу данных SQLite не работает с Swift 2?

Я использую SQLite.swift, и я использую этот код из демонстрация SQLite.swift.

import UIKit
import SQLite

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let db = try! Connection()
        let users = Table("users")
        let id = Expression<Int64>("id")
        let email = Expression<String>("email")
        let name = Expression<String?>("name")
        try! db.run(users.create { t in
            t.column(id, primaryKey: true)
            t.column(email, unique: true, check: email.like("%@%"))
            t.column(name)
        })
        try! db.run(users.insert(email <- "[email protected]"))
        for user in db.prepare(users) {
            print("id: \(user[id]), email: \(user[email])")
        }
    }
}

При первом запуске вывод был такой:

("SELECT * FROM \"users\"", [])
id: 1, email: [email protected]

Затем я удалил строку 17 ( try! db.run(users.insert(email <- "[email protected]")) ) и снова запустил, вывод отладчика изменился на:

("SELECT * FROM \"users\"", [])

Похоже, [email protected] не сохранился в базе данных. Так где я сделал это неправильно? Или как сохранить его в базу данных SQLite?

P.S. Я использую Xcode 7 бета 5, Swift 2.0


person David    schedule 20.08.2015    source источник
comment
Пожалуйста, проверьте базу данных. Запись доступна в базе данных?   -  person Ashish Kakkad    schedule 20.08.2015
comment
Я не знаю, где находится эта база данных в @iAshish.   -  person David    schedule 20.08.2015
comment
Вы указали путь для хранения базы данных по пути к каталогу документа, верно? @Дэйвид ?   -  person Ashish Kakkad    schedule 20.08.2015
comment
Просто напечатайте этот путь в консоли. и перейдите в эту базу данных с помощью Finder. откройте эту базу данных в браузере sqlite и проверьте, доступны ли данные или нет.   -  person Ashish Kakkad    schedule 20.08.2015
comment
Но как распечатать? @iAshish   -  person David    schedule 20.08.2015
comment
stackoverflow.com/ вопросов/24133022/ Просто используйте println() или print() в swift2.   -  person Ashish Kakkad    schedule 20.08.2015
comment
и закройте БД после вставки данных. db.close() должен работать с быстрым   -  person Ashish Kakkad    schedule 20.08.2015
comment
Я нашел этот путь к каталогу, используя эту ссылку @iAshish, но я не нашел этот файл базы данных   -  person David    schedule 20.08.2015


Ответы (3)


let db = try! Connection()

создает базу данных в памяти, как видно из документации по API:

/// Initializes a new SQLite connection.
///
/// - Parameters:
///
///   - location: The location of the database. Creates a new database if it
///     doesn’t already exist (unless in read-only mode).
///
///     Default: `.InMemory`.
///
///   - readonly: Whether or not to open the database in a read-only state.
///
///     Default: `false`.
///
/// - Returns: A new database connection.
public init(_ location: Location = .InMemory, readonly: Bool = false) throws

Данные не сохраняются в файле, а база данных изначально всегда пуста.

Для постоянной базы данных используйте

/// Initializes a new connection to a database.
///
/// - Parameters:
///
///   - filename: The location of the database. Creates a new database if
///     it doesn’t already exist (unless in read-only mode).
///
///   - readonly: Whether or not to open the database in a read-only state.
///
///     Default: `false`.
///
/// - Throws: `Result.Error` iff a connection cannot be established.
///
/// - Returns: A new database connection.
public convenience init(_ filename: String, readonly: Bool = false) throws

вместо этого, например

// Compute file path for database in Documents directory:
let docsDir = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last!
let dbPath = (docsDir as NSString).stringByAppendingPathComponent("database.sqlite")

do {
    let db = try Connection(dbPath)
    // ... use database

} catch (error) {
    // Could not create or open database, print error
}
person Martin R    schedule 20.08.2015

viewDidLoad сначала создает таблицу, а затем вставляет.

Я не знаю поведения функции создания таблицы, когда таблица уже существует, но если она не выдает никаких ошибок, она, вероятно, снова создает таблицу. Если это так, после вызова viewDidLoad с закомментированной вставкой вы, вероятно, получите новую новую пустую таблицу.

Попробуйте изменить логику, чтобы таблица не создавалась каждый раз заново.

person MirekE    schedule 20.08.2015

У вас может быть что-то вроде этого (очевидно, что все остальные могут улучшить код):

  1. Создайте модель вашего стола:

    class TUsers {
    static let TABLE_NAME : String = “users”
    static let ID = Expression<Int64>("id")
    static let EMAIL = Expression<String>(“email”)
    static let NAME = Expression<String>(“name”)
    
    class func addUser(email : String!, name : String!) -> Bool{
    
        let users = Table(TABLE_NAME)
    
        do {
    
            try DBHelper.instance.db.run(users.insert(
                TUsers.EMAIL <- email,
                TUsers.NAME <- name
            ))
    
            return true
        } catch {
            print("Insert failed")
            return false
        }
    }
    
    class func getAllUsers() -> [User] { // you must create the model user
        let users = Table(TUsers.TABLE_NAME)
    
        let query = users.select(*)
            //.filter(TUsers.EMAIL == “[email protected]”)
    
        var listOfUsers : [Users] = []
    
        for user in DBHelper.instance.db.prepare(query) {
            // Do whatever you need to instantiate the model User
    
    
            listOfUsers.append(User(email: users[TUsers.EMAIL], name: users[TUsers.NAME])
    
        }
    
        return listOfUsers
    }
    }
    
  2. Создайте помощник базы данных

    class DBHelper {
    
    static let instance = DBHelper()
    
    var db : Connection
    
    init() {
        do {
            self.db = try Connection("\(Util.getDBPath())/db.sqlite3")
            createTablesIfNotExists()
        } catch {
            print("Could not create a connection to database")
        }
    }
    
    func createTablesIfNotExists() {
    
        let users = Table(TUsers.TABLE_NAME)
        do {
            try db.run(logs.create(ifNotExists: true) { t in
                    t.column(TUsers.ID, primaryKey: true)
                    t.column(TUsers.EMAIL)
                    t.column(TUsers.NAME)
            })
        } catch {
            print(“Could not create table users”)
        }
    }
    }
    
  3. И наконец (здесь вам не нужно импортировать SQLite).

    class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    
       TUsers.addUser(“[email protected]”, “John Capuchon”)
    
        let users = TUsers.getAllUsers()
    
        for user in users {
            // do something
        }
    }
    

    }

person Kingslayerpy    schedule 08.10.2015