Storing and Retrieving Image in Sqlite with swift

前端 未结 3 693
小蘑菇
小蘑菇 2020-12-21 20:05

How to store and fetch images in SQLite and in what format the images get saved? It would be more helpful if explained with an example.

相关标签:
3条回答
  • 2020-12-21 20:25

    Image itself cannot be stored into a database columns but you can first convert it into a string and then store it. The string is called base64 string. As far as I know, any image can be converted to that and reversely.

    To encode to base 64:

    let image : UIImage = UIImage(named:"imageNameHere")!
    let imageData:NSData = UIImagePNGRepresentation(image)!
    let strBase64 = imageData.base64EncodedString(options: .lineLength64Characters)
    

    Now your UIImage object is converted to a String! Save strBase64 to SQLite DB. Remember to use text as column type because this string is very long.

    To decode back to UIImage:

    let dataDecoded:NSData = NSData(base64EncodedString: strBase64, options: NSDataBase64DecodingOptions(rawValue: 0))!
    let decodedimage:UIImage = UIImage(data: dataDecoded)!
    
    0 讨论(0)
  • 2020-12-21 20:30

    Alternative

    1. save your image into document directory.
    2. save your image file path or name of image in sqlite
    3. Get the image path or name from sqlite and access that path from document directory.

    Take Ref : Iphone : How to Display Document Directory images in Image View?

    0 讨论(0)
  • 2020-12-21 20:48

    You can also store your image directly as a BLOB, however it depends on which framework you use for SQLite access. In case you use SQLite.swift, then there is an option:

    Set up a file SQLiteHelper.swift like that:

    class SQLiteHelper{
        var db: Connection!
    
        let personsTable = Table("person")
        let id = Expression<Int>("id")
        let firstName = Expression<String>("firstName")
        let lastName = Expression<String>("lastName")
        let profileImage = Expression<Data>("profileImage")
        let date = Expression<Date>("savedAt")
    
        init() {
            do{
                let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
                let dbTemp = try Connection("\(path)/myDb.sqlite3") //Create db if not existing
                self.db = dbTemp
            }
            catch {
                print("Error info: \(error)")
            }
        }
    
        public func insertData(firstNameVal: String,
                               lastNameVal: String,
                               profileImageVal: Data,
                               dateVal: Date){
    
            do{
                //Create a new table only if it does not exist yet
                try db.run(personsTable.create(ifNotExists: true) { t in      // CREATE TABLE "person" (
                    t.column(id, primaryKey: true)          //     "id" INTEGER PRIMARY KEY NOT NULL,
                    t.column(firstName)                     //     "firstName" TEXT,
                    t.column(lastName)                      //     "lastName" TEXT,
                    t.column(profileImage)                  //     "profileImage" BLOB,
                    t.column(date)                          //     "savedAt" DATETIME)
                })
            }
            catch {
                print("The new SQLite3 Table could not be added: \(error)")
            }
    
            do{
                try db.run(personsTable.insert(firstName <- firstNameVal,
                                                lastName <- lastNameVal,
                                                profileImage <- profileImageVal,
                                                date <- dateVal
                ))
            }
            catch {
                print("Could not insert row: \(error)")
            }
        }
    
        public func getData() -> [Person]{
            var persons = [Person]()
            do{
                for row in try db.prepare(personsTable) {
                    let person: Person = Person(firstName: row[firstName],
                                                   lastName: row[lastName],
                                                   profileImage: row[profileImage],
                                                   savedAt: row[date])
    
                    persons.append(person)
                }
            }
            catch {
                print("Could not get row: \(error)")
            }
            return persons
        }
    

    Now create a file Person.swift and put the following struct inside of it:

    import Foundation
    
    struct Person: Identifiable {
        var id = UUID()
        var firstName: String
        var lastName: String
        var profileImage: Data
        var savedAt: Date
    }
    

    Store Data

    In order to store data as a .png BLOB you would now basically do something like that:

    var databaseHelper: SQLiteHelper = SQLiteHelper.init()
    self.databaseHelper.insertData(firstNameVal: "yourFirstName",
                                       lastNameVal: "yourLastName",
                                  profileImageVal: yourImageView.pngData(),
                                  dateVal: Date())
    

    Retreive Data

    If you want to display the image later in another Imageview you would have to do this:

    var persons = self.databaseHelper.getData()
    let profileImage = UIImage(data: persons[0].profileImage)
    let myImageView = UIImageView(image: profileImage)
    

    Saving UIImage as BLOB

    I have saved the image as a .png because I want to use my database outside of iOS and therefore want to ensure compatibility. If you want you can also store your UIImage directly. You would roughly need to change it like that:

    let profileImage = Expression<UIImage>("profileImage")
    ...
    profileImageVal: yourImageView,
    ...
    let myImageView = persons[0].profileImage
    ...
    
    import Foundation
    import UIKit
    
    struct Person: Identifiable {
        var id = UUID()
        var firstName: String
        var lastName: String
        var profileImage: UIImage
        var savedAt: Date
    }
    

    Note: SQLite.swift also supports lazy loading, which would probably make more sense in ascenario like that...

    0 讨论(0)
提交回复
热议问题