@[TOC](IOS DB Storage Realm. Swift)

Swift-Realm database usage details

  • Download the demo of this blog: kylRealmSwiftDemo

An overview of the

Realm-java is a cross-platform mobile database engine that performs better than Core Data and MDB-mobile databases. We can use realm-Java on Android and Realm-Cocoa on iOS. Support both OC and Swift language development. It is simple to use, free, excellent performance, cross-platform features widely loved by programmers GG.

Realm Chinese Documentation

This article will explain the use of Realm with some practical exercises.

Realm supports storage of the following properties

  • Int, Int8, Int16, Int32 and Int64
  • Boolean, Boolean
  • Double and Float
  • String
  • NSDate, Date(accuracy to second)
  • NSData, Data
  • Classes inherited from Object => as Used for one-to-one relations
  • List => As Used for one-to-many relations

The following table is an example declared in code:

type Non-optional value form Form of an optional value
Bool dynamic var value = false let value = RealmOptional()
Int dynamic var value = 0 let value = RealmOptional()
Float Dynamic var value: Float = 0.0 let value = RealmOptional()
Double Dynamic var value: Double = 0.0 let value = RealmOptional()
String dynamic var value = “” dynamic var value: String? = nil
Data dynamic var value = NSData() dynamic var value: NSData? = nil
Date dynamic var value = NSDate() dynamic var value: NSDate? = nil
Object Must be an optional value dynamic var value: Class?
List let value = List() The value must be non-optional
LinkingObjects let value = LinkingObjects(fromType: Class.self, property: “property”) The value must be non-optional

Realm Install – Use CocoaPods

pod 'RealmSwift' pod 'Realm'

Realm configuration

  • Write the following code in the AppDelegate didFinishLaunchingWithOptions method, this method is mainly used for data model properties when adding or removing data migration, each model properties change, will dbVersion plus one can, Realm detects new and removed properties and automatically updates the database schema on your hard drive, removing data from the properties.
// configure the database
    public class func configRealm(a){
        // If the data model attributes to be stored change, configure the current version number to be larger than the previous one
        let dbVersion : UInt64 = 2
        let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) [0] as String
        let dbPath = docPath.appending("/defaultDB.realm")
        let config = Realm.Configuration(fileURL: URL.init(string: dbPath), inMemoryIdentifier: nil, syncConfiguration: nil, encryptionKey: nil, readOnly: false, schemaVersion: dbVersion, migrationBlock: { (migration, oldSchemaVersion) in
            
        }, deleteRealmIfMigrationNeeded: false, shouldCompactOnLaunch: nil, objectTypes: nil)
        Realm.Configuration.defaultConfiguration = config
        Realm.asyncOpen { (realm, error) in
            if let _ = realm {
                print("Realm Server configuration successful!")}else if let error = error {
                print("Realm database configuration failed:\(error.localizedDescription)")}}}Copy the code

Define the model

import UIKit
import RealmSwift

class Book: Object {
    @objc dynamic var name = ""
    @objc dynamic var author = ""
    
    /// LinkingObjects represents the owner of the object backwards
    let owners = LinkingObjects(fromType: Student.self, property: "books")}class Student: Object {
    @objc dynamic var name = ""
    @objc dynamic var age = 18
    @objc dynamic var weight = 156
    @objc dynamic var id = 0
    @objc dynamic var address = ""
    @objc dynamic var birthday : NSDate? = nil
    @objc dynamic var photo : NSData?  = nil
    
    // override object.primarykey () to set the primaryKey of the model.
    // After the primary key is declared, objects are allowed to be queried, update speed is more efficient, and each object is required to be unique.
    // Once an object with a primary key has been added to a Realm, its primary key cannot be modified.
    override static func primaryKey(a) -> String? {
        return "id"
    }
    
    // Overriding Object.ignoredProperties() prevents a Realm from storing a property of the data model
    override static func ignoredProperties(a)- > [String] {
        return ["tempID"]}// Override the object.indexedProperties () method to index attributes in your data model. Realm supports indexing strings, integers, booleans, and Date attributes.
    override static func indexedProperties(a)- > [String] {
        return ["name"]}//List is used to represent a one-to-many relationship: there are multiple books in a Student.
    let books = List<Book>()
}

Copy the code

Note that all data models stored in realms areObjectA subclass of class.

1) set primaryKey -primarykey

Overriding object.primarykey () sets the primaryKey of the model. After the primary key is declared, the objects are allowed to be queried, the update speed is more efficient, and each object is required to be unique. Once an object with a primary key has been added to a Realm, the primary key of that object is not modifiable.

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

2) Ignore the property -ignoredProperties

Overriding Object.ignoredProperties() prevents a Realm from storing a property of the data model. Realm will not interfere with the normal operation of these properties, they will be supported by member variables (var), and you can easily override their setters and getters.

    override static func ignoredProperties(a)- > [String] {
        return ["tempID"]}Copy the code

3) Index properties – indexedProperties

Overriding the Object.indexedProperties() method can index attributes in the data model that need indexing. Realm supports indexing strings, integers, booleans, and Date attributes.

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

4) Implement one-to-many relationship with List – indexedProperties

List is used to indicate a one-to-many relationship: there are multiple books in a Student. A List can contain objects of the simple type, superficially similar to a mutable Array, using the same methods and accessing the data (indexes and subscripts), and all contained objects should be of the same type. You cannot precede the declaration with dynamic because generic properties cannot be represented at Objective-C runtime. Note: Lists can only contain Object types, not base types such as strings.

    //List is used to represent a one-to-many relationship: there are multiple books in a Student.
    let books = List<Book> ()Copy the code

5) Reverse relationship – LinkingObjects

With a reverse relationship (also known as a backlink), you can get all the objects that are related to a given object through a specific property. Realm provides “linking Objects” properties to express these backward relationships. With linked object properties, you can get all objects linked to a specified object by the specified property. For example, a Book object can have a link object property called Owners that contains Student objects that contain the identified Book object in their books property. You can set the Owners property to type LinkingObjects and then specify a relationship that includes its owner Student object.

  let owners = LinkingObjects(fromType: Student.self, property: "books")
Copy the code

1 to add

1.1 Requirement: Insert 1 student’s information into local database?

import UIKit
import RealmSwift
class XWStudentRealmTool: Object {
    private class func getDB() - >Realm {
        let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) [0] as String
        let dbPath = docPath.appending("/defaultDB.realm")
        /// The incoming path automatically creates the database
        let defaultRealm = try! Realm(fileURL: URL.init(string: dbPath)!)
        return defaultRealm
    }
}
/ / /
extension XWStudentRealmTool {
   
    public class func insertStudent(by student : Student) - >Void {
        let defaultRealm = self.getDB()
        try! defaultRealm.write {
            defaultRealm.add(student)
        }
        print(defaultRealm.configuration.fileURL ?? "")}}Copy the code
The test code
Func testInsterStudent() {let stu = Student() stu.name = "stu.age" stu.id = 2; func testInsterStudent() {let stu = Student() stu.name = "stu.age" stu.id = 2; let birthdayStr = "1993-06-10" let dateFormatter = DateFormatter() dateFormatter.dateFormat = "YYYY-MM-dd" stu.birthday = dateFormatter.date(from: birthdayStr)! As NSDate stu. Weight = 160 stu. Address = "huilongguan" XWStudentRealmTool. InsertStudent (by: stu)}Copy the code

Through the Realm Browser view just saved data through the print (Realm. Configuration. FileURL?? “”) prints the data path

Effect:

1.2 Requirements: Test to insert a student object with multiple books and an avatar into the database

The test code
// Test inserts a student object in the database with multiple books and an avatar
    func testInsertStudentWithPhotoBook(a) {
        let stu = Student()
        stu.name = "Geekology is great _ with pictures _ with books."
        stu.weight = 151;
        stu.age = 26
        stu.id = 3;
        / / avatar
        stu.setPhotoWitName("cat")

        let bookFubaba = Book.init(name: "Rich dad poor dad", author: "Robert. T. kiyosaki")
        let bookShengmingbuxi = Book.init(name: "There is no end to life.", author: "Luo Yonghao")
        let bookDianfuzhe = Book(value: ["Subversive: The Autobiography of Zhou Hongyi".Zhou Hongyi])
        stu.books.append(bookFubaba);
        stu.books.append(bookShengmingbuxi);
        stu.books.append(bookDianfuzhe);
        
        XWStudentRealmTool.insertStudent(by: stu)
    }
Copy the code

Result: The database is automatically created and two tables, Student and Book, are associated

1.3 Requirements: Test to insert 44 student objects into the database

Save method

/// save some Student
    public class func insertStudents(by students : [Student]) -> Void {
        let defaultRealm = self.getDB()
        try! defaultRealm.write {
            defaultRealm.add(students)
        }
        print(defaultRealm.configuration.fileURL ?? "")}Copy the code
The test code
    // Test to insert multiple student objects with multiple books and portraits into the database
    func testInsertManyStudent(a) {
        var stus = [Student] ()for i in 100.144 {
            let stu = Student()
            stu.name = "Geeks learn to be great\(i)"
            stu.weight = 151;
            stu.age = 26
            stu.id = I;
            / / avatar
            stu.setPhotoWitName("cat")
            let birthdayStr = "1993-06-10"
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "YYYY-MM-dd"
            stu.birthday = dateFormatter.date(from: birthdayStr)! as NSDate
            stus.append(stu)
        }
        
        XWStudentRealmTool.insertStudents(by: stus)
    }
Copy the code

Demo Results:

2 check

2.1 General query: query all student models in the database and output the name, picture and book information owned

  /// get the saved Student
    public class func getStudents() - >Results<Student> {
        let defaultRealm = self.getDB()
        return defaultRealm.objects(Student.self)}Copy the code
The test code
     let stus = XWStudentRealmTool.getStudents()
        for stu in stus {
            print(stu.name)
            ifstu.photo ! =nil {
                self.imageV.image = stu.getPhotoImage()
            }
            if stu.books.count > 0 {
                for book in stu.books {
                    print(book.name + "+" + book.author)
                }
            }
        }
Copy the code

Demo Results:

Assign the image to the imageView

2.2 Primary key query: Query the student model with ID 110 in the database and output the name

    /// get Student with specified id (primary key)
    public class func getStudent(from id : Int) - >Student? {
        let defaultRealm = self.getDB()
        return defaultRealm.object(ofType: Student.self, forPrimaryKey: id)
    }
Copy the code
The test code
 // Query by primary key
    func testSearchStudentByID(a){
        let student = XWStudentRealmTool.getStudent(from: 110)
        if let studentL = student {
            print(studentL.name)
        }
    }
Copy the code

Demo Results:

In the corresponding database:

2.2 Primary key query: Query the student model with ID 110 in the database and output the name

    /// get the specified condition
    public class func getStudentByTerm(_ term: String) - >Results<Student> {
        let defaultRealm = self.getDB()
        print(defaultRealm.configuration.fileURL ?? "")
        let predicate = NSPredicate(format: term)
        let results = defaultRealm.objects(Student.self)
        return  results.filter(predicate)
    }
Copy the code
The test code
    // Conditional query
    func testSearchTermStudent(a)  {
        let students = XWStudentRealmTool.getStudentByTerm("Name = 'geek_110 '")
        if students.count= =0 {
            print("No data found")
            return
        }
        for student in students {
            print(student.name,student.weight)
        }
    }
Copy the code

Output result:

Ascending/descending query

// Query by ascending name
let stus = realm.objects(Student.self).sorted(byKeyPath: "id")

// Query by name in descending order
let stus = realm.objects(Student.self).sorted(byKeyPath: "id", ascending: false)

Copy the code

3 to change

3.1 Primary Key Update – Update individual students

    /// Update a single Student
    public class func updateStudent(student : Student) {
        let defaultRealm = self.getDB()
        try! defaultRealm.write {
            defaultRealm.add(student, update: true)}}Copy the code

3.2 Primary key Update – Update multiple students

    /// Update multiple Student
    public class func updateStudent(students : [Student]) {
        let defaultRealm = self.getDB()
        try! defaultRealm.write {
            defaultRealm.add(students, update: true)}}Copy the code

The test code

    /// batch change
    func testUpdateStudents(a) {
        var stus = [Student] ()for i in 100.144 {
            let stu = Student()
            stu.name = "Geek Xuewei changed his name to _\(i)"
            stu.weight = 148;
            stu.age = 27
            stu.id = I;
            stus.append(stu)
        }
        XWStudentRealmTool.updateStudent(students: stus)
    }
Copy the code

Before the update:

After the update:

3.3 Key Value update – All students age changed to 18

    /// Update multiple Student
    public class func updateStudentAge(age : Int) {
        let defaultRealm = self.getDB()
        try! defaultRealm.write {
            let students = defaultRealm.objects(Student.self)
            students.setValue(age, forKey: "age")}}Copy the code

Test code:

    /// change the age in batches
    func testUpdateStudentsAge(a) {
        XWStudentRealmTool.updateStudentAge(age: 18)}Copy the code

Demo Results:

4 delete

     /// delete a single Student
    public class func deleteStudent(student : Student) {
        let defaultRealm = self.getDB()
        try! defaultRealm.write {
            defaultRealm.delete(student)
        }
    }
    
    /// delete multiple Student
    public class func deleteStudent(students : Results<Student>) {
        let defaultRealm = self.getDB()
        try! defaultRealm.write {
            defaultRealm.delete(students)
        }
    }
Copy the code

Test code:

    /// delete student whose id is 3
    func testDeleteOneStudent(a) {
        let stu = XWStudentRealmTool.getStudent(from: 3)
        ifstu ! =nil {
            XWStudentRealmTool.deleteStudent(student: stu!) }}/// delete all
    func testDeleteAllStudent(a) {
        let stus = XWStudentRealmTool.getStudents()
        XWStudentRealmTool.deleteStudent(students: stus)
    }
Copy the code

Deleted database: