Realm Studio

Use Realm Studio to make development more efficient. You can easily open any Realm database file or Realm object server to deploy objects and analyze them. Realm Studio allows you to easily open and edit local and synchronizable Realm databases, as well as manage the Realm platform. It runs on Mac, Windows, and Linux.

Download link

Add RealmSwift to the project

Carthage

  1. Cartfile addgithub "realm/realm-cocoa";
  2. Terminal CD to project files;
  3. runcarthage update --platform iOS
  4. inCarthage/Build/iOS/Lt.Realm.framework,RealmSwift.frameworkAdd to the Linked Frameworks and Libraries section of the “General” Settings TAB of the Xcode project;
  5. The following figure shows the path configuration. Carthage portal

CocoaPods

  1. Perform pod Repo update to update CocoaPods to the latest version of the Realm currently available;
  2. In your Podfile, add use_frameworks! And POD ‘RealmSwift’ added to the main application target and test target;
  3. Execute pod install from the command line;
  4. Use the.xcworkspace file generated by CocoaPods to write the project.

The dynamic library

Download address

Go to the “General” Settings TAB of the Xcode project and select the Swift version directory suitable for your project from the ios/, osx/, tVOs/or Watchos/directory. Drag realm. framework and Realmswift. framework into the Embedded Binaries section. Make sure Copy Items if needed is checked (unless you have multiple platforms in your project that need to use Realm) and then click the Finish button; In the “Build Settings” of the unit test target, add the parent directory of RealmSwift.framework to the “Framework Search Paths” section; If you are using Realm in iOS, watchOS, or tvOS projects, create a new “Run Script Phase” in the “Build Phases” section of the application target and paste the following code into the Script text box:

Copy to clipboardbash “${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/ realm. framework/strip-frameworks Store submission bug, so this step is necessary when packaging generic binaries.

Using RealmSwift

The data model

1. Create the data model

Data models stored in realms are subclasses of Object.

import Foundation
import RealmSwift

class Dog: Object {
   @objc dynamic var id: Int = 0
   @objc dynamic var name: String?
    
}

class Cat: Object {
    @objc dynamic var name: String?
}

Copy the code

@objc is for Swift4 compatibility

2. Supported attribute types

Realm supports the following types: Bool, Int, Int8, Int16, Int32, Int64, Double, Float, String, Date, and Data. The String, Date, and Data attributes are nullable, and the Object attribute must be nullable.

Up here in Dog you can see that you can’t write a numeric type as an Int, right? In Realm, the optional numeric type can be set as follows:

// Optional int property, default nil // RealmOption property should always use 'let', // because assigning it directly doesn't do anythinglet age = RealmOptional<Int>()
    
Copy the code
let realm = try! Realm()
try! realm.write() {
    var person = realm.create(Person.self, value: ["Jane", 27]) // // Read or modify 'RealmOptional' to implement person.age. Value = 28}Copy the code

RealmOptional supports Int, Float, Double, Bool, and Int8, Int16, Int32, and Int64 of all sizes.

3. Set the primary key

override static func primaryKey() -> String? {
    return "id"
}
Copy the code

Implementing this method sets the primary key directly

4. Index attributes

override static func indexedProperties() -> [String] {
   return ["title"]}Copy the code

Implement indexedProperties to set index properties.

Realm supports indexing of strings, integers, Booleans, and Date properties.

5. Attribute cheat sheets

type Nonnullable form Nullable form
Bool @objc dynamic var value = false let value = RealmOptional()
Int @objc dynamic var value = 0 let value = RealmOptional()
Float @objc dynamic var value: Float = 0.0 let value = RealmOptional()
Double @objc dynamic var value: Double = 0. let value = RealmOptional()
String @objc dynamic var value = “” @objc dynamic var value: String? = nil
Data @objc dynamic var value = Data() @objc dynamic var value: Data? = nil
Date @objc dynamic var value = Date() @objc dynamic var value: Date? = ni
Object Nonexistent: must be nullable @objc dynamic var value: Class?
List let value = List() Nonexistent: must be nonnullable
LinkingObjects let value = LinkingObjects(fromType: Class.self, property: “property”) Nonexistent: must be nonnullable

Create a Realm

/// /// -parameters: /// -databasename: dataBaseName /// -isreadonly: whether the database is read-only /// - Returns: Realm Instance @discardAbleresult Public FUNc creatDB(_ dataBaseName: String, isReadOnly: Bool =false) -> Realm? {
        let realm = openDB(dataBaseName, isReadOnly: isReadOnly)
        returnRealm} /// open database /// /// -parameter name: database name /// -isReadonly: whether it is read-only /// - Returns: Realm Instance @discardAbleresult Private Func openDB(_ dataBaseName: String, isReadOnly: Bool =false) -> Realm? {
        guard let dbPath = getCreatDatabasePath(dataBaseName) else {
            return nil
        }
        var config = Realm.Configuration()
        config.fileURL = dbPath
        config.readOnly = isReadOnly
        Realm.Configuration.defaultConfiguration = config
        do {
            let realm = try Realm.init(configuration: config)
            return realm
        }catch let error {
            mPrint("To open or create the database failure: \ n \ (error. LocalizedDescription)")
            return nil
        }
    }
Copy the code

When you generate a realm.realm file locally, you will also have:

  • realm.lock– Resource lock file;
  • realm.management– Directory where process lock files are stored;
  • realm.note– Named pipes for notifications.

    These files are simply file deletions maintained by Realm or they don’t cause any problems.

When reporting Realm problems, submit these auxiliary Realms along with the main.realm files, as they are likely to contain information useful for debugging problems.

RealmStudioda: all classes that inherit Object create tables directly in RealmStudioda.

Open the Realm file in your project

/// open the pre-planted database /// /// -parameters: /// -databasename: dataBaseName /// -isreadonly: is it read-only /// - Returns: Realm Instance @discardAbleresult public func openReferenceDB(_ dataBaseName: String, isReadOnly: Bool =true) -> Realm? {
        guard let dbPath = getReferenceDatabasePaeh(dataBaseName) else {
            return nil
        }
        var config = Realm.Configuration()
        config.fileURL = dbPath
        config.readOnly = isReadOnly
        Realm.Configuration.defaultConfiguration = config
        do {
            let realm = try Realm.init(configuration: config)
            return realm
        }catch let error {
            mPrint("To open or create the database failure: \ n \ (error. LocalizedDescription)")
            return nil
        }
    }
Copy the code

Set up the Realm ofdefaultConfiguration

/// /// -parameters: /// -realmName: the name of the database /// -isReadOnly: Whether this is read-only public funcsetDefaltRealmConfiguration(_ realmName: String,isReference: Bool = false, isReadOnly: Bool = false) -> Bool{
        var realmPath: URL?
        if isReference {
            realmPath = getReferenceDatabasePaeh(realmName)
        }else {
            realmPath = getCreatDatabasePath(realmName)
        }
        if realmPath == nil {
            return false
        }
        var config = Realm.Configuration()
        config.fileURL = realmPath
        config.readOnly = isReadOnly
        Realm.Configuration.defaultConfiguration = config
        return true
    }
Copy the code

Gets the current default database

/// /// - Returns: Returns a database instance of the default Realm @discardAbleresult public func getDefaultRealm() -> Realm? {do {
            return try Realm()
        }catch let error {
            mPrint("Failed to get the default Realm of database: \ n \ (error. LocalizedDescription)")
            return nil
        }
    }
Copy the code

If defaultConfiguration is not configured, the default database is retrieved.

/Library/Developer/CoreSimulator/Devices
/26B4D5CC-1EF4-4897-8F02-BCFBE06F7C40/data
/Containers/Data/Application/7CDCBAF4-A7A2-45E4-9B8A-725E873975AD/Documents/default.realm
Copy the code

After the configuration, you can obtain the database where the path is set.

/Library/Developer/CoreSimulator/Devices
/26B4D5CC-1EF4-4897-8F02-BCFBE06F7C40/data
/Containers/Data/Application/E050DEE4-71FB-4866-A10C-CBADA288D35C/Library/Caches/DB/2237DB/2237DB.realm
Copy the code

Instances of realms do not need global data sharing. After configuring the default database, you get the same Realm() wherever you want.

increase

/ / MARK: - / / / / to create table | | update table / / / / / / - Parameters: / / / -type: Indicates the object corresponding to the table direction. /// -value: indicates the value. /// -update: indicates whether the value is updated"true"/// -result: The object was added successfully. If it was added successfully, the object will be returned to public func creatObject(_)type: RealmSwift.Object.Type, value: Any? = nil, update: Bool = false, result: ((RealmSwift.Object? , Error?) -> Void)? = nil){let realm = getDefaultRealm()
        do{ try realm? .write {letobject = (value == nil) ? realm? .create(type) : realm? .create(type, value: value! , update: update) result? (object, nil) } } catchlet error {
            mPrint("Failed to get the default Realm of database: \ n \ (error. LocalizedDescription)") result? (nil, error) } }Copy the code
/ / / add data | | according to the primary key data update / / / / / / - Parameters: / / / - object: to add a data / / / - update: whether to update, if it istrue/// -result: Add data status public func addObject(_ object: realmSwift. object, update: Bool =false, result: ((Error?) -> Void)? = nil) {
        let realm = getDefaultRealm()
        do{ try realm? .write { realm? .add(object, update: update) result? (nil) } } catchlet error {
            mPrint("Add data failure: \ n \ (error. LocalizedDescription)") result? (error) } }Copy the code

delete

/// /// -parameters: /// -object: deleteObject // -result: delete state public func deleteObject(_ object: RealmSwift.Object, result: ((Error?) -> Void)? = nil) {let realm = getDefaultRealm()
        do{ try realm? .write { realm? .delete(object) result?(nil) } } catchlet error {
            mPrint("Add data failure: \ n \ (error. LocalizedDescription)") result? (error) } }Copy the code
/// /// -parameter result: delete state public func deleteAllObject(result: ((Error?)) -> Void)? = nil) {let realm = getDefaultRealm()
        do{ try realm? .write { realm? .deleteAll() result?(nil) } } catchlet error {
            mPrint("Add data failure: \ n \ (error. LocalizedDescription)") result? (error) } }Copy the code
/// /// -parameter dataBaseName: the name of the database /// - Returns: @discardAbleresult public func deleteCreatDBFile() -> Bool {discardableResult public func deleteCreatDBFile() -> Boolreturn  autoreleasepool { () -> Bool in
            let realmURL = Realm.Configuration.defaultConfiguration.fileURL!
            let realmURLs = [
                realmURL,
                realmURL.appendingPathExtension("lock"),
                realmURL.appendingPathExtension("note"),
                realmURL.appendingPathExtension("management")]for URL in realmURLs {
                do {
                    try FileManager.default.removeItem(at: URL)
                    return true} catch {// error handlingreturn false}}return false}}Copy the code

change

//MARK: - change /// update according to primary key /// /// -parameters: /// -object: the object to be updated /// -update: Whether to update according to primary key, if so"false"/// -result: data update result public func updateObject(_ object: realmSwift. object, update: Bool =true, result: ((Error?) -> Void)? = nil) {
        addObject(object, update: update, result: result)
    }
Copy the code
/// update /// /// -parameters according to the primary key: /// -type: Type of the object to be updated /// -value: value to be updated, for example: ["id": 1, "price": 9000.0] /// -update: Whether to update by primary key, if yes"false"/// -result: updateObject(_type: RealmSwift.Object.Type, value: Any? = nil, update: Bool = true, result: ((RealmSwift.Object? , Error?) -> Void)? = nil) { creatObject(type, value: value, update: update, result: result)
    }
Copy the code
/// /// -parameters: /// -property: the property to be changed /// -value: the value to be changed /// - Returns: @discardAbleresult public func updateObject(Property: Inout Any, value: Any) -> Bool {discardableResult public func updateObject(Property: inout Any, value: Any) -> Boollet realm = getDefaultRealm()
        do{ try realm? .write { property = value }return true
        } catch let error {
            mPrint("Update object properties directly error: \ (error. LocalizedDescription)")
            return false}}Copy the code
/// change the values of all the fields in the table /// /// -parameters: /// -type: table object type /// -key: field name to be changed /// -value: changed value /// - Returns: changed result public func updateObjects(type: RealmSwift.Object.Type, key: String, value: Any) -> Bool {
        let objects = getObjects(type: type)
        do{ try getDefaultRealm()? .write { objects? .setValue(value,forKeyPath: key)
            }
            return true
        } catch let error {
            mPrint("Change all the data in a table error: \ (error. LocalizedDescription)")
            return false}}Copy the code
// update the data in an object according to the primary key /// /// -parameters: /// -type: table type /// -primarykey: primaryKey /// -key: attribute to be changed /// -value: changed value /// - Returns: changed status public func updateObject(type: RealmSwift.Object.Type, primaryKey: Any, key: String, value: Any) -> Bool {
        let object = getObjectWithPrimaryKey(type: type, primaryKey: primaryKey)
        do{ try getDefaultRealm()? .write { object? .setValue(value,forKeyPath: key)
            }
            return true
        } catch let error {
            mPrint(Update the data error: \ "(error. LocalizedDescription)")
            return false}}Copy the code

check

//MARK: - query /// query all data in a table /// /// -parametertype: object type /// - Returns: query data public func getObjects(type: RealmSwift.Object.Type) -> RealmSwift.Results<RealmSwift.Object>? {returngetDefaultRealm()? .objects(type)}Copy the code
/// /// -parameters: /// -type: object type /// -primarykey: primaryKey /// - Returns: data queried public func getObjectWithPrimaryKey(type: RealmSwift.Object.Type, primaryKey: Any) -> RealmSwift.Object? {
        returngetDefaultRealm()? .object(ofType:type.forPrimaryKey: primaryKey)
    }
Copy the code
/// query /// /// -parameters with the assertion string: /// -type: object type /// -filter: filter criteria /// - Returns: query data /// -example: /// -var tanDogs = realm.objects(dog.self).filter()"color = 'tan' AND name BEGINSWITH 'B'")
    public func getObject(type: RealmSwift.Object.Type, filter: String) -> RealmSwift.Results<RealmSwift.Object>? {
        return getObjects(type: type)? .filter(filter) }Copy the code
/// query with the predicate /// /// -parameters: /// -type: Object type /// - predicate: predicate object /// - Returns: queried data /// -example: /// -let predicate = NSPredicate(format: "color = %@ AND name BEGINSWITH %@"."tan"."B")
    ///   - tanDogs = realm.objects(Dog.self).filter(predicate)
    public func getObject(type: RealmSwift.Object.Type, predicate: NSPredicate) -> RealmSwift.Results<RealmSwift.Object>? {
        return getObjects(type: type)? .filter(predicate) }Copy the code
/// To sort the data in a query, note that multiple attributes are not supported as a sort base, and there is no chaining sort (only the last sorted call will be used). If you want to sort multiple attributes, use the sorted(by:) method, and then type multiple SortDescriptor objects into it. /// /// - Parameters: /// -type: object type /// -filter: filter criteria /// -sortedKey: field to be sorted /// - Returns: final result public func getObject(type: RealmSwift.Object.Type, filter: String, sortedKey: String) -> RealmSwift.Results<RealmSwift.Object>? {
        return getObject(type: type, filter: filter)? .sorted(byKeyPath: sortedKey) }Copy the code
/// To sort the data in a query, note that multiple attributes are not supported as a sort base, and there is no chaining sort (only the last sorted call will be used). If you want to sort multiple attributes, use the sorted(by:) method, and then type multiple SortDescriptor objects into it. /// /// - Parameters: /// -type: queue type /// - predicate: predicate object /// - sortedKey: sorted fields /// - Returns: sorted data public func getObject(type: RealmSwift.Object.Type, predicate: NSPredicate, sortedKey: String) -> RealmSwift.Results<RealmSwift.Object>? {
        return getObject(type: type, predicate: predicate)? .sorted(byKeyPath: sortedKey) }Copy the code

A collection of

Realms have a number of types that can represent a set of objects, called “collections of realms” :

  • Results class, which represents the collection of objects returned by queries.
  • The List class that represents a pairwise relationship between models.
  • LinkingObjects class that represents a bidirectional relationship between models.
  • RealmCollection protocol, which defines common interfaces for all collections of Realms.
  • AnyRealmCollection class, which is a typeless class that can forward calls to a concrete Realm collection, such as Results, List, or LinkingObjects.

Realm collection types all implement the RealmCollection protocol, which ensures that they all behave the same. This protocol inherits from CollectionType, so it is used in the same way as collections in the library. The protocol also declares other commonly used Realm collection apis, such as retrieval, sorting, aggregation operations, and so on. List also has some additional modification operations that are not defined in the protocol interface, such as adding or deleting objects.

Using the RealmCollection protocol, you can write generic code that operates on any collection of Realms:

Copy to clipboardFunc operateOn<C: RealmCollection>(Collection: C) {// Collection can be either RLMResults or RLMArrayprint("operating on collection containing \(collection.count) objects")}Copy the code

Due to the limitations of the Swift type system, a typeless wrapper such as AnyRealmCollection must be used to store this collection in properties or variables:

Copy to clipboardclass ViewController {
//    let collection: RealmCollection
//                    ^
//                    error: protocol 'RealmCollection' can only be used
//                    as a generic constraint because it has Self or
//                    associated type requirements
//
//    init<C: RealmCollection>(collection: C) where C.ElementType == MyModel {
//        self.collection = collection
//    }

    let collection: AnyRealmCollection<MyModel>

    init<C: RealmCollection>(collection: C) where C.ElementType == MyModel {
        self.collection = AnyRealmCollection(collection)
    }
}
Copy the code

The basics of using Realm are written here, and more details can be found in the documentation (which is pretty detailed).

In the use of RealmSwift add delete change check and RxSwift encapsulated a layer. The project address

The resources

  1. English document
  2. Chinese document

thank you