软件产品的两种形态
client-server,客户端,本地存储用的较多 browser-server,网站,服务器存储用的多,例如mysql
IOS本地存储数据库
userdefaults 存储轻量级数据 core data 学习成本高,代码较多,速度没有realm快 realm 第三方功能包
realm
// 定义模型的做法和定义常规 Swift 类的做法类似,需要继承
class Dog: Object {
@objc dynamic var name = ""
@objc dynamic var age = 0
}
class Person: Object {
@objc dynamic var name = ""
@objc dynamic var picture: Data? = nil // 支持可空值
let dogs = List<Dog>()
}
// 像常规 Swift 对象一样使用
let myDog = Dog()
myDog.name = "Rex"
myDog.age = 1
print("name of dog: \(myDog.name)")
// 获取默认的 Realm 数据库
let realm = try! Realm()
// 检索 Realm 数据库,找到小于 2 岁 的所有狗狗
let puppies = realm.objects(Dog.self).filter("age < 2")
puppies.count // => 0 因为目前还没有任何狗狗被添加到了 Realm 数据库中
// 数据存储十分简单
try! realm.write {
realm.add(myDog)
}
// 检索结果会实时更新
puppies.count // => 1
// 可以在任何一个线程中执行检索、更新操作
DispatchQueue(label: "background").async {
autoreleasepool {
let realm = try! Realm()
let theDog = realm.objects(Dog.self).filter("age == 1").first
try! realm.write {
theDog!.age = 3
}
}
}
let user = User()
user.name = "gaibb"
user.age = 21
do {
let realm = try Realm()
try realm.write({
realm.add(user)
})
} catch{
print(error)
}
print(Realm.Configuration.defaultConfiguration.fileURL)
objects方法返回一个Results< Element>类型数据
var todos: Results<Todo>?
todos = realm.objects(Todo.self)
改:直接对获得的Results< Element>类型数据修改
do {
try realm.write({
todos![row].name = name
})
} catch {
print(error)
}
do {
try realm.write({
realm.delete(todos![indexPath.row])
})
} catch {
print(error)
}
条件搜索
/ 使用断言字符串来查询
var tanDogs = realm.objects(Dog.self).filter("color = 'tan' AND name BEGINSWITH 'B'")
// 使用 NSPredicate 来查询
let predicate = NSPredicate(format: "color = %@ AND name BEGINSWITH %@", "tan", "B")
tanDogs = realm.objects(Dog.self).filter(predicate)
比较操作数可以是属性名,也可以是常量。但至少要有一个操作数是属性名; 比较操作符 ==、<=、<、>=、>、!= 和 BETWEEN 支持 Int、Int8、Int16、Int32、Int64、Float、Double 以及 Date 这几种属性类型,例如 age == 45; 比较是否相同:== 和 !=,例如,Results().filter(“company == %@”, company); 比较操作符 == 和 != 支持布尔属性; 对于 String 和 Data 属性而言,支持使用 ==、!=、BEGINSWITH、CONTAINS 和 ENDSWITH 操作符,例如 name CONTAINS ‘Ja’; 对于 String 属性而言,LIKE 操作符可以用来比较左端属性和右端表达式:? 和 * 可用作通配符,其中 ? 可以匹配任意一个字符,* 匹配 0 个及其以上的字符。例如:value LIKE ‘?bc*’ 可以匹配到诸如 “abcde” 和 “cbc” 之类的字符串; 字符串的比较忽略大小写,例如 name CONTAINS[c] ‘Ja’。请注意,只有 “A-Z” 和 “a-z” 之间的字符大小写会被忽略。[c] 修饰符可以与 [d] 修饰符结合使用; 字符串的比较忽略变音符号,例如 name BEGINSWITH[d] ‘e’ 能够匹配到 étoile。这个修饰符可以与 [c] 修饰符结合使用。(这个修饰符只能够用于 Realm 所支持的字符串子集:参见当前的限制一节来了解详细信息。) Realm 支持以下组合操作符:“AND”、“OR” 和 “NOT”,例如 name BEGINSWITH ‘J’ AND age >= 32; 包含操作符:IN,例如 name IN {‘Lisa’, ‘Spike’, ‘Hachi’}; 空值比较:==、!=,例如 Results().filter(“ceo == nil”)。请注意,Realm 将 nil 视为一种特殊值,而不是某种缺失值;这与 SQL 不同,nil 等同于自身; ANY 比较,例如 ANY student.age < 21; List 和 Results 属性支持聚集表达式:@count、@min、@max、@sum 和 @avg,例如 realm.objects(Company.self).filter(“employees.@count > 5”) 可用以检索所有拥有 5 名以上雇员的公司。 支持子查询,不过存在以下限制:
@count 是唯一一个能在 SUBQUERY 表达式当中使用的操作符; SUBQUERY(…).@count 表达式只能与常量相比较;
排序
请注意,sorted(byKeyPath:) 和 sorted(byProperty:) 不支持 将多个属性用作排序基准,此外也无法链式排序(只有最后一个 sorted 调用会被使用)。 如果要对多个属性进行排序,请使用 sorted(by:) 方法,然后向其中输入多个 SortDescriptor 对象。
// 对颜色为棕黄色、名字以 "B" 开头的狗狗进行排序
let sortedDogs = realm.objects(Dog.self).filter("color = 'tan' AND name BEGINSWITH 'B'")
.sorted(byKeyPath: "name")
class Person: Object {
@objc dynamic var name = ""
@objc dynamic var dog: Dog?
}
class Dog: Object {
@objc dynamic var name = ""
@objc dynamic var age = 0
}
let dogOwners = realm.objects(Person.self)
let ownersByDogAge = dogOwners.sorted(byKeyPath: "dog.age")