ios - 简单存储/检索 blob 或数据(可能是类的 NSKeyArchive)

标签 ios sql swift sqlite.swift

这里是经验丰富的开发人员...但对 Swift 有点陌生,并且是 SQLite.swift 的新手...

我正在尝试在 iOS 应用程序中使用 SQLite - 所以我创建了一个简单的应用程序来确保我掌握了基础知识...一切都很顺利,直到我到达存储和检索数据的地步对象(即类对象)...

这是我的代码:

    //**********************************************************************
    //**
    //** Create/Open database connection
    //**
    //**********************************************************************
    let dbPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
    let db: Connection = try! Connection("\(dbPath)/stickis.sqlite3")

    let dbTable = Table("testtbl")
    let id = Expression<Int64>("id")
    let boolfld = Expression<Bool>("boolfld")
    let int64fld = Expression<Int64>("int64fld")
    let stringfld = Expression<String>("stringfld")
    let blobfld = Expression<SQLite.Blob?>("blobfld") // optional due to ?

    //**********************************************************************
    //*
    //* Drop table if it exists
    //*
    //**********************************************************************
    try! db.run(dbTable.drop(ifExists: true))

    //**********************************************************************
    //**
    //** Create/Open Table
    //**
    //**********************************************************************
    do
    {
        try db.run((dbTable.create(ifNotExists: true)
        {
            t in
            t.column(id, primaryKey: true)
            t.column(boolfld)
            t.column(int64fld)
            t.column(stringfld)
            t.column(blobfld)
            })
        )
    }
    catch
    {
        print("Failed to create sticki table")
    }

    //**********************************************************************
    //**
    //** Add Record 1
    //**
    //**********************************************************************
    do
    {
        let testblob: Blob = windowcontent()
        let rowid = try db.run(dbTable.insert(boolfld <- true, int64fld <- 1963, stringfld <- "unknown", blobfld <- testblob))
        print("inserted id: \(rowid)")
    }
    catch
    {
        print("insertion failed: \(error)")
    }

    //**********************************************************************
    //**
    //** Add Record 2
    //**
    //**********************************************************************
    do
    {
        let rowid = try db.run(dbTable.insert(boolfld <- true, int64fld <- 1972, stringfld <- "David"))
        print("inserted id: \(rowid)")
    }
    catch
    {
        print("insertion failed: \(error)")
    }

    //**********************************************************************
    //**
    //** Update Record 1
    //**
    //**********************************************************************
    let rec2updt = dbTable.filter(id == 1)
    do
    {
        if try db.run(rec2updt.update(stringfld <- "TJ")) > 0
        {
            print("updated to TJ")
        }
        else
        {
            print("record not found")
        }
    }
    catch
    {
        print("update failed")
    }

    //**********************************************************************
    //**
    //** Query Particular Record using filter
    //**
    //**********************************************************************
    let tjFilter = dbTable.filter(int64fld == 1964)
    for dataRec in try! db.prepare(tjFilter)
    {
        print("id: \(dataRec[id]), stringfld: \(dataRec[stringfld])")
    }

    //**********************************************************************
    //**
    //** Query All Records
    //**
    //**********************************************************************
    for dataRec in try! db.prepare(dbTable)
    {
        print("id: \(dataRec[id]), stringfld: \(dataRec[stringfld])")
    }

    //**********************************************************************
    //**
    //** Delete Records
    //**
    //**********************************************************************
    try! db.run(dbTable.delete())

一切对我来说都工作得很好......直到我在“添加记录 1”评论 block 下添加了以下行...

    let testblob: Blob = windowcontent()

windowcontent() 是一个我想要“存档”并保存的类(或者可能是一个结构体)...我使用 Blob 来存储它的原因是存储的对象类型可能有几种不同的类型类。

我也尝试过这个:

        let testdata: Data = Data()
        let testblob: Blob = testdata as Blob

并收到无法将数据转换为 Blob 的预期错误

有人有一个可以与我分享的向 SQLite.Blob 分配数据和从 SQLite.Blob 检索数据的简单示例吗?

另外,当我运行完所有的“基础”iOS 示例代码后,是否有一个好地方可以分享它?假设其他新手可能会出现,这会让生活变得更轻松。

最佳答案

这是回答我的问题的运行代码。请参阅“使用过滤器查询特定记录”部分,了解我从 Blob 转换回 String 的位置。

override func viewDidLoad()
{
    super.viewDidLoad()
    // Do any additional setup after loading the view.


    //**********************************************************************
    //**
    //** Create/Open database connection
    //**
    //**********************************************************************

    // dbpath is where we want the sqlite file to reside... in this case we are using the documents directory
    let dbPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!

    // the filename we are giving our database is "testdb.sqlite3" - it can be what ever you like.  If the file exists, it opens it as a database, if it does not exist, it will create it and then open it.
    let db: Connection = try! Connection("\(dbPath)/testdb.sqlite3")

    // defining the name of the SQLite table we want to use as well as the field names we want to create in the table.  In this case, we are creating one of each major type of fields - Bool, Long Int, String, Blob
    let dbTable = Table("testtbl")
    let id = Expression<Int64>("id")
    let boolfld = Expression<Bool>("boolfld")
    let int64fld = Expression<Int64>("int64fld")
    let stringfld = Expression<String>("stringfld")
    let blobfld = Expression<SQLite.Blob?>("blobfld") // Blob field is optional due to SQLite.Blob? - remove the ? to make it require "Not Null"

    //**********************************************************************
    //*
    //* Drop table if it exists
    //*
    //**********************************************************************
    // Deleting the table if it exists - this is simply to allow the program to be rerun and start by  creating a new table
    try! db.run(dbTable.drop(ifExists: true))

    //**********************************************************************
    //**
    //** Create/Open Table
    //**
    //**********************************************************************
    do
    {
        // create the table with the following fields...
        try db.run((dbTable.create(ifNotExists: true)
        {
            t in
            // the fields in our table...
            t.column(id, primaryKey: true)
            t.column(boolfld)
            t.column(int64fld)
            t.column(stringfld)
            t.column(blobfld)
            })
        )
    }
    catch
    {
        // should not get to this, but if it does, you can expect the remainder of the app to fail also.
        print("Failed to create sticki table")
    }

    //**********************************************************************
    //**
    //** Add Record 1
    //**
    //**********************************************************************
    do
    {
        // setup a Data var and then save it as an SQLite.Blob
        let testdata: Data = "foo".data(using: .utf8)!  //Data()
        let testblob: Blob = Blob(bytes: [UInt8](testdata))

        // insert a new record into the database... the function will return the rowID of the newly inserted record.
        let rowid = try db.run(dbTable.insert(boolfld <- true, int64fld <- 1963, stringfld <- "unknown", blobfld <- testblob))

        print("inserted id: \(rowid)")
    }
    catch
    {
        print("insertion failed: \(error)")
    }

    //**********************************************************************
    //**
    //** Add Record 2
    //**
    //**********************************************************************
    do
    {
        // Adding a 2nd record to the database - no Blob field this time
        let rowid = try db.run(dbTable.insert(boolfld <- true, int64fld <- 1972, stringfld <- "David"))
        print("inserted id: \(rowid)")
    }
    catch
    {
        print("insertion failed: \(error)")
    }

    //**********************************************************************
    //**
    //** Update Record 1
    //**
    //**********************************************************************

    // Setup filter to get record "WHERE id == 1"
    let rec2updt = dbTable.filter(id == 1)
    do
    {
        // db.run will return the # of records updated - must be > 0 (actually, == 1)
        if try db.run(rec2updt.update(stringfld <- "TJ")) > 0
        {
            print("updated to TJ")
        }
        else
        {
            print("record not found")
        }
    }
    catch
    {
        print("update failed")
    }

    //**********************************************************************
    //**
    //** Query Particular Record using filter
    //**
    //**********************************************************************

    // Setup filter to get record "WHERE int64fld == 1963"
    let tjFilter = dbTable.filter(int64fld == 1963)

    // Run using filter and print out results (should only be 1 rec in our case)
    for dataRec in try! db.prepare(tjFilter)
    {
        // Convert Blob back to String
        let tmpStr: String = String(bytes: dataRec[blobfld]!.bytes, encoding: .utf8)!
        print("id: \(dataRec[id]), stringfld: \(dataRec[stringfld]), blobfld: \(tmpStr)")
    }

    //**********************************************************************
    //**
    //** Query All Records
    //**
    //**********************************************************************

    // Prints all records in database
    for dataRec in try! db.prepare(dbTable)
    {
        print("id: \(dataRec[id]), stringfld: \(dataRec[stringfld])")
    }

    //**********************************************************************
    //**
    //** Delete Records
    //**
    //**********************************************************************

    // Deletes ALL records in the table (use a filter to delete individual records)
    try! db.run(dbTable.delete())

}

override func didReceiveMemoryWarning()
{
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

关于ios - 简单存储/检索 blob 或数据(可能是类的 NSKeyArchive),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46102049/

相关文章:

sql - select count(field) 和 select field,count 是在同一行吗?

ios - 仅在首次启动时显示 View - Swift 3

objective-c - NSHTTPCookieStorage 状态未在应用退出时保存。那里有任何明确的知识/文档吗?

sql - 外部查询先于内部查询运行

mysql - 交叉连接的性能

ios - Swift:Objective-C 方法冲突(尝试更改 calloutview 时出错)

ios - 为什么 UIImageView 没有使用 Swift 正确加载

swift - 进程无法从 Swift 中的标准输入读取

ios - CNContactStore 联系人记录数

ios - UItableViewCells 中的单选按钮逻辑