微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

swift- realmswift本地数据库使用与常见问题

RealmSwift

官方文档

https://www.mongodb.com/docs/realm/sdk/swift/

realmswift存储和sql存储使用上最大的区别是,realmswift可以直接将对象存储,无需写sql建表,建索引。

它将数据存储为一个文档,数据结构由键值(key=>value)对组成。也就是说能以对象的形式进行存储。

model编写

1、object model不能使用struct

2、model必须继承Object或Embeddedobject

3、对象必须要加前缀@Persisted

4、如果是Object类型,而且需要写入、删除添加操作的话,要加主键@Persisted(primaryKey: true)

5、数组array必须要用realmswift.List<element>

6、如果更改数组后没更新版本或者没重装app,不执行do内容

$R1 = "Migration is required due to the following errors:\n- Property ‘Person.name’ has been added

7、不能多个对象引用同一个对象

报的错误类似Thread 1: “Attempting to create an object of type ‘Person’ with an existing primary key value ‘A’.”

数据写入

1、任何读操作都得是在这里执行

        do {
            let realm = try Realm()
          let personList = realm.objects(Person.self)
        }

2、如果是需要写的操作,就必须在这里执行,保证原子性。

        do {
            let realm = try Realm()
            try realm.write({
                // 报错原因 浅拷贝,地址都是一样的,指向的内容也是一样的,因此不能add上去
                realm.add(person)
//                realm.add(anotherPerson)
            })
           let personList = realm.objects(Person.self)
        }

let personList = realm.objects(Person.self) 这只是引用地址,如果后面有写的操作,会直接报错。

报错源码:Thread 1: “Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.”

3、如果你在本地里打开文件(Realm studio),运行不执行try realm.write。如果把try去掉会直接报错

4、add添加数据库的时候,realm.add(person,update: .modified)如果没设置主键会直接报错

Thread 1: “‘Person’ does not have a primary key and can not be updated”

.add(person,update: .modified)是如果主键一致的话,修改里面的内容,主键不一样的话,添加新的数据。

技术点

Realm.Configuration数据库的深度定制

一般使用这个

var config = Realm.Configuration(fileURL: ,
                                         encryptionKey: ,
                                         schemaVersion: ,
                                         migrationBlock: )

fileURL存储的位置,一般是存储document里,

encryptionkey 密钥

schemaVersion 更新model参数时需要在这+1

migrationBlock 初始化后如果需要对数据进行操作的回调,也可以在闭包里对model更改的数据进行操作。

当需要删除表时,如果都是使用Object作为model的话,删除的只是当前对象的基础类型参数。如果引用了其他的Object类型的model作为参数,该参数的信息依旧保留,不会链式删除

如果想删除当前Object,并且删除以对象形式的参数,该参数的model应为Embeddedobject

配合网络请求

ObjectMapper

直接看demo代码

public class DiningPartnerList: Object, Mappable {
    @Persisted(primaryKey: true) var primaryKey = 1
    
    @Persisted public var brands = List<DiningPartnerItem>()
    public override init() {}
    
    required public init?(map: ObjectMapper.Map) {
        
    }
    public func mapping(map: ObjectMapper.Map) {
        brands <- (map["brands"], ListTransformWithEmbeddedobject<DiningPartnerItem>())
    }
}

DiningPartnerItem.swift

public class DiningPartnerItem: Embeddedobject, Mappable {
    @Persisted public var id: String?
    @Persisted public var name: String?
    @Persisted public var isNewBrand: Bool = false
    @Persisted public var isOnlinestore: Bool = false
    
    public override init() {}
    
    required public init?(map: ObjectMapper.Map) {
        
    }
    
    public func mapping(map: ObjectMapper.Map) {
        id <- map["id"]
        name <- map["name"]
        isNewBrand <- map["new_brand"]
        isOnlinestore <- map["is_online_store"]
    }
}

ListTransformWithEmbeddedobject是array转换List的过程。这个是Embeddedobject类型,如果想要Object类型的话

public struct ListTransformWithEmbeddedobject<T: RealmSwift.Embeddedobject>: TransformType where T: BaseMappable

改成

public struct ListTransformWithObject<T: RealmSwift.Object>: TransformType where T: BaseMappable

代码是从github那里搬下来的

public struct ListTransformWithEmbeddedobject<T: RealmSwift.Embeddedobject>: TransformType where T: BaseMappable {
    
    public init() { }
    
    public typealias ListObject = List<T>
    public typealias ListJSON = [Any]
    
    public func transformFromJSON(_ value: Any?) -> List<T>? {
        if let objects = Mapper<T>().mapArray(JSONObject: value) {
            let list = List<T>()
            list.append(objectsIn: objects)
            return list
        }
        return nil
    }
    
    static public func arrayToList<T>() -> TransformOf<List<T>, [T]> {
        return TransformOf(
            fromJSON: { (value: [T]?) -> List<T> in
                let result = List<T>()
                if let value = value {
                    result.append(objectsIn: value)
                }
                return result
        },
            toJSON: { (value: List<T>?) -> [T] in
                var results = [T]()
                if let value = value {
                    results.append(contentsOf: Array(value))
                }
                return results
        })
    }
    
    public func transformToJSON(_ value: ListObject?) -> ListJSON? {
        return value?.compactMap { $0.toJSON() }
    }
}

codable

RealmSwift的list已经支持Codable,这是 List.swift文件的源码,如果是数组只需要使用list<element>就行

// MARK: - Codable

extension List: Decodable where Element: Decodable {
    public convenience init(from decoder: Decoder) throws {
        self.init()
        var container = try decoder.unkeyedContainer()
        while !container.isAtEnd {
            append(try container.decode(Element.self))
        }
    }
}

extension List: encodable where Element: encodable {}

demo

class ColorList: Object, Codable {
    @Persisted var color: List<MyColor>
    enum CodingKeys: String, CodingKey {
        case color = "xxxcolor"
    }
   
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(color, forKey: .color)
    }
}

class MyColor: Embeddedobject, Codable {
    @Persisted var name: String?
    @Persisted var hexColor: String?
    
    enum CodingKeys: String, CodingKey {
        case name, hexColor
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐