Blame view

Twear/Tools/RealmTools.swift 19.1 KB
75d24c15   yangbin   123
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  //
  //  RealmTools.swift
  //  Twear
  //
  //  Created by yangbin on 2021/11/22.
  //
  import UIKit
  import RealmSwift
  
  /**
   Realm 致力于平衡数据库读取的灵活性和性能为了实现这个目标 Realm 中所存储的信息的各个方面都有基本的限制例如
   1类名称的长度最大只能存储 57  UTF8 字符
   2属性名称的长度最大只能支持 63  UTF8 字符
   3NSData 以及 String 属性不能保存超过 16 MB 大小的数据如果要存储大量的数据可通过将其分解为16MB 大小的块或者直接存储在文件系统中然后将文件路径存储在 Realm 如果您的应用试图存储一个大于 16MB 的单一属性系统将在运行时抛出异常
   4对字符串进行排序以及不区分大小写查询只支持基础拉丁字符集”、“拉丁字符补充集”、“拉丁文扩展字符集 A 以及拉丁文扩展字符集 B“(UTF-8 的范围在 0~591 之间)。
   */
  
  // 事件闭包(做完Realm操作后的事件)
  public typealias RealmDoneTask = () -> Void
  class RealmTools: NSObject {
      /// 单粒
      static let sharedInstance = RealmTools()
      private var config: Realm.Configuration?
      /// 当前的 Realm
      fileprivate var currentRealm: Realm? {
          return try? Realm(configuration: config!)
      }
      /// 当前realm存储的路径
      static var fileURL: URL? {
          return sharedInstance.currentRealm?.configuration.fileURL
      }
      /// 当前的版本号
      fileprivate var currentSchemaVersion: UInt64 = 0
      /// 当前的加密字符串
      fileprivate var currentKeyWord: String? = ""
      
  //    private let dbQueue = DispatchQueue(label: "com.codepgq.github", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit, target: nil)
  //       //DispatchQueue(label:"com.appcoda.queue2", qos:DispatchQoS.userInitiated)
  //       func execQueueSQL(action : @escaping (_ manager : RealmTools) ->()){
  //           //开一个子线程
  //           DispatchQueue.global().async {
  //               action(self)
  //           }
  //       }
  //
  }
  
  // MARK:- Realm数据库配置和版本差异化配置
  /**
   通过调用 Realm() 来初始化以及访问我们的 realm 变量其指向的是应用的 Documents 文件夹下的一个名为default.realm的文件
   通过对默认配置进行更改我们可以使用不同的数据库比如给每个用户帐号创建一个特有的 Realm 文件通过切换配置就可以直接使用默认的 Realm 数据库来直接访问各自数据库
   */
  // (application:didFinishLaunchingWithOptions:)中进行配置
  extension RealmTools {
      
  //    public class func configRealm() {
  //           /// 这个方法主要用于数据模型属性增加或删除时的数据迁移每次模型属性变化时 dbVersion  1 即可Realm 会自行检测新增和需要移除的属性然后自动更新硬盘上的数据库架构移除属性的数据将会被删除
  //           let dbVersion : UInt64 = 1
  //           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(configuration: config) { (realm, error) in
  ////            if let _ = realm {
  ////                print("Realm 服务器配置成功!")
  ////            }else if let error = error {
  ////                print("Realm 数据库配置失败:\(error.localizedDescription)")
  ////            }
  ////        }
  //
  //
  //       }
      
      // MARK: 配置数据库为用户提供个性化的 Realm 配置(加密暂时没有使用)
      /// 配置数据库为用户提供个性化的 Realm 配置
      /// - Parameters:
      ///   - userID: 用户的ID
      ///   - keyWord: 加密字符串
      ///   - schemaVersion: 设置新的架构版本(如果要存储的数据模型属性发生变化)这个版本号必须高于之前所用的版本号如果您之前从未设置过架构版本那么这个版本号设置为 0
      ///   
      static func configRealm(migrationBlock: MigrationBlock? = nil) {
          let currentVersion: UInt64 = 1
          let config = Realm.Configuration(fileURL: URL.init(string: getRealmPath()), inMemoryIdentifier: nil, syncConfiguration: nil, encryptionKey: nil, readOnly: false, schemaVersion: currentVersion, migrationBlock: { (migration, oldSchemaVersion) in
                      
                  }, deleteRealmIfMigrationNeeded: false, shouldCompactOnLaunch: nil, objectTypes: nil)
                  Realm.Configuration.defaultConfiguration = config
  
                  Realm.asyncOpen { (result) in
                      switch result {
                         case .success(_):
                          print("Realm 服务器配置成功!")
                         case .failure(let error):
                          print("Realm 数据库配置失败:\(error.localizedDescription)")
  
                            
                         }
                  }
      
  //        let config = Realm.Configuration(fileURL: URL(string: getRealmPath()), schemaVersion: currentVersion, migrationBlock: { (migration, oldSchemaVersion) in
  //            // 目前我们还未进行数据迁移因此 oldSchemaVersion == 0
  //            if oldSchemaVersion < 1 {
  //                // 什么都不要做Realm 会自行检测新增和需要移除的属性然后自动更新硬盘上的数据库架构
  //            }
  //            // 低版本的数据库迁移......
  //            if migrationBlock != nil {
  //                migrationBlock!(migration, oldSchemaVersion)
  //            }
  //        })
  //        // 告诉 Realm 为默认的 Realm 数据库使用这个新的配置对象
  //        Realm.Configuration.defaultConfiguration = config
  //        guard let realm = try? Realm(configuration: config) else {
  //            return
  //        }
          sharedInstance.currentSchemaVersion = currentVersion
          sharedInstance.config = config
  //        sharedInstance.currentRealm = realm
  //        sharedInstance.currentKeyWord = keyWord
      }
      
      
      
      // MARK: 删除当前的realm库
      /// 删除当前的realm库
      @discardableResult
      static func deleteRealmFiles() -> Bool {
          let realmURL = sharedInstance.currentRealm?.configuration.fileURL ?? Realm.Configuration.defaultConfiguration.fileURL!
          let realmURLs = [
              realmURL,
              realmURL.appendingPathExtension("lock"),
              realmURL.appendingPathExtension("management")
          ]
          for URL in realmURLs {
              do {
                  try FileManager.default.removeItem(at: URL)
                  self.configRealm()
              } catch {
                  // handle error
                  return false
              }
          }
          return true
      }
      
      private class func getRealmPath() -> String{
          
          
  //        let filePathDaildata = "\(Bundle.main.resourcePath!)/wyp.realm"
  ////        NSString *dialDirectoryPath = [NSString stringWithFormat:@"%@/%@/%@/%d",filePathDaildata,@"dial",@"DialDataRtk",2];
  ////        dialDirectoryPath = [NSString stringWithFormat:@"%@/%@",dialDirectoryPath,@"dial.bin"];
  //        return "/Users/yangbin/Desktop/Twear.realm"
          
           let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0] as String
   
           let name : String = "Twear"
           let dbPath = docPath.appending("/\(name).realm")
   //        print("realm地址为: \(dbPath)")
           return dbPath
       }
  }
  
  // MARK:- 
  extension RealmTools {
      
      // MARK: 添加单个对象
      /// 添加单个对象
      /// - Parameters:
      ///   - object: 对象
      ///   - update: 是否更新
      ///   - task: 添加后操作
      static func add(_ object: Object, update: Realm.UpdatePolicy = .error) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          try? weakCurrentRealm.write {
              weakCurrentRealm.add(object, update: update)
          }
      }
  
      
      // MARK: 添加多个对象
      /// 添加多个对象
      /// - Parameters:
      ///   - objects: 对象组
      ///   - update: 是否更新
      ///   - task: 添加后操作
      static func addList(_ objects: Array<Object>, update: Realm.UpdatePolicy = .error) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          try? weakCurrentRealm.write {
              weakCurrentRealm.add(objects, update: update)
          }
      }
  }
  
  // MARK:- 
  extension RealmTools {
      
      // MARK: 在事务中删除一个对象
      /// 在事务中删除一个对象
      /// - Parameters:
      ///   - object: 单个被删除的对象
      ///   - task: 删除后操作
      static func delete(_ object: Object) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          try? weakCurrentRealm.write {
              weakCurrentRealm.delete(object)
          }
      }
      
      // MARK: 在事务中删除多个对象
      /// 在事务中删除多个对象
      /// - Parameters:
      ///   - objects: 多个要被删除的对象
      ///   - task: 删除后操作
      static func deleteList(_ objects: Array<Object>) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          try? weakCurrentRealm.write {
              weakCurrentRealm.delete(objects)
          }
      }
      
      // MARK: 删除所有数据不要轻易调用
      ///  Realm 中删除所有数据
      /// - Parameter task: 删除后操作
      static func deleteAll(task: @escaping RealmDoneTask) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          try? weakCurrentRealm.write {
              weakCurrentRealm.deleteAll()
              task()
          }
      }
      
      // MARK: 根据条件删除对象
      /// 根据条件删除对象
      /// - Parameters:
      ///   - object: 对象类型
      ///   - predicate: 条件
      static func deleteByPredicate(object: Object.Type, filter: String) {
          guard let results: Array<Object> = queryObjects(object, filter: filter) else {
              return
          }
          deleteList(results)
      }
  }
  
  // MARK:- 
  extension RealmTools {
      
      // MARK: 更改某个对象根据主键存在来更新元素必须有主键
      /// 更改某个对象根据主键存在来更新
      /// - Parameters:
      ///   - object: 某个对象
      ///   - update: 是否更新
      static func update(object: Object, update: Realm.UpdatePolicy = .modified) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          try? weakCurrentRealm.write {
              weakCurrentRealm.add(object, update: update)
          }
      }
  
      // MARK: 更改多个对象根据主键存在来更新元素必须有主键
      /// 更改多个对象根据主键存在来更新
      /// - Parameters:
      ///   - objects: 多个对象
      ///   - update: 是否更新
      static func updateList(objects: Array<Object>, update: Realm.UpdatePolicy = .modified) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          try? weakCurrentRealm.write {
              weakCurrentRealm.add(objects, update: .modified)
          }
      }
      
      // MARK: 更新操作对于realm搜索结果集当中的元素在action当中直接赋值即可修改(比如查询到的某些属性可直接修改)
      /// 更新操作对于realm搜索结果集当中的元素在action当中直接赋值即可修改
      /// - Parameter action: 操作
      static func updateWithTranstion(action: (Bool) -> Void) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          try? weakCurrentRealm.write {
              action(true)
          }
      }
      
      // MARK: 更新一个一个对象的多个属性值根据主键存在来更新元素必须有主键
      /// 更新一个一个对象的多个属性值
      /// - Parameters:
      ///   - object: 对象类型
      ///   - value: 数组数组
      ///   - update: 更新类型
      static func updateObjectAttribute(object: Object.Type, value: Any = [:], update: Realm.UpdatePolicy = .modified) {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return
          }
          do {
              try weakCurrentRealm.write {
                  weakCurrentRealm.create(object, value: value, update: update)
              }
          } catch _ {
              
          }
      }
  }
  
  // MARK:- 
  extension RealmTools {
      // MARK: 查询某个对象数据
      /// 查询某个对象数据
      /// - Parameter type: 对象类型
      /// - Returns: 返回查询的结果
      /// _ predicateFormat: String, _ args: Any...
      static func queryObjects(_ object: Object.Type, filter: String? = nil, _ argumentArray: [Any]? = nil) -> Array<Object>? {
          var results : Results<Object>?
          if filter != nil {
              results =  queryWith(object: object, filter: filter!, argumentArray)
          }
          else {
              results = queryWithType(object: object)
          }
          if results == nil {
              return nil
          } else {
              return resultsToObjectList(results: results!)
          }
      }
          
      
      // MARK: 查询某个对象数据(根据条件)
      /// 查询某个对象数据(根据条件)
      /// - Parameters:
      ///   - object: 对象类型
      ///   - predicate: 查询条件
      /// - Returns: 返回查询结果
      static func queryObjectsWithPredicate(object: Object.Type, filter: String) -> Array<Object>? {
          guard let results = queryWith(object: object, filter: filter) else {
              return nil
          }
          return resultsToObjectList(results: results)
      }
      
      // MARK: 带排序条件查询
      ///  带排序条件查询
      /// - Parameters:
      ///   - object: 对象类型
      ///   - predicate:  查询条件
      ///   - sortedKey: 排序的键
      ///   - isAssending: 升序还是降序默认升序
      /// - Returns: 返回查询对象数组
      static func objectsWithPredicateAndSorted(object: Object.Type,
                                             predicate: NSPredicate? = nil,
                                             sortedKey: String,
                                           isAssending: Bool = true) -> Array<Object>? {
          guard let results = queryWithSorted(object: object, predicate: predicate, sortedKey: sortedKey, isAssending: isAssending) else {
              return nil
          }
          return resultsToObjectList(results: results)
      }
      
      
      // MARK: 带分页的查询
      /// 带分页的查询
      /// - Parameters:
      ///   - object: 对象类型
      ///   - predicate: 查询条件
      ///   - sortedKey: 排序的键
      ///   - isAssending: 升序还是降序默认升序
      ///   - fromIndex: 起始页
      ///   - pageSize: 一页的数量
      /// - Returns: 返回查询对象数组
      static func objectsWithPredicateAndSortedForPages(object: Object.Type,
                                                        predicate: NSPredicate? = nil,
                                                        sortedKey: String,
                                                        isAssending: Bool = true,
                                                        fromIndex: Int = 1,
                                                        pageSize: Int) -> Array<Object>? {
          guard let results = queryWithSorted(object: object,
                                           predicate: predicate,
                                           sortedKey: sortedKey,
                                       isAssending: isAssending) else {
              return nil
          }
          var resultsArray = Array<Object>()
          if results.count <= pageSize * (fromIndex - 1) || fromIndex <= 0 {
              return resultsArray
          }
          if results.count > 0 {
              for i in pageSize * (fromIndex - 1)...(min(fromIndex * pageSize, results.count) - 1) {
                  resultsArray.append(results[i])
              }
          }
          return resultsArray
      }
  }
  
  //MARK:- 私有(查询)
  extension RealmTools {
      
      /// 查询某个对象数据
      /// - Parameter object: 对象类型
      /// - Returns: 返回查询对象数组
      private static func queryWithType(object: Object.Type) -> Results<Object>? {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return nil
          }
          return weakCurrentRealm.objects(object)
      }
      
      // MARK: 根据条件查询数据
      /// 根据条件查询数据
      /// - Parameters:
      ///   - object: 对象类型
      ///   - predicate: 查询条件
      /// - Returns: 返回查询对象数组
      private static func queryWith(object: Object.Type,
                                    filter: String, _ argumentArray: [Any]? = nil) -> Results<Object>? {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return nil
          }
          
          if argumentArray == nil {
              return weakCurrentRealm.objects(object).filter(filter)
          } else {
              return weakCurrentRealm.objects(object).filter(NSPredicate(format: filter, argumentArray: argumentArray))
          }
          
       
          
          
      }
      
      // MARK: 带排序条件查询
      /// 带排序条件查询
      /// - Parameters:
      ///   - object: 对象类型
      ///   - predicate: 查询条件
      ///   - sortedKey: 排序的键
      ///   - isAssending: 升序还是降序默认升序
      /// - Returns: 返回查询对象数组
      private static func queryWithSorted(object: Object.Type,
                                       predicate: NSPredicate? = nil,
                                       sortedKey: String,
                                     isAssending: Bool = true) -> Results<Object>? {
          guard let weakCurrentRealm = sharedInstance.currentRealm else {
              return nil
          }
          if predicate == nil {
              return weakCurrentRealm.objects(object)
                  .sorted(byKeyPath: sortedKey, ascending: isAssending)
          } else {
              return weakCurrentRealm.objects(object).filter(predicate!)
                  .sorted(byKeyPath: sortedKey, ascending: isAssending)
          }
         
      }
      
      // MARK: 查询结果转Array<Object>
      /// 查询结果转Array<Object>
      /// - Parameter results: 查询结果
      /// - Returns: 返回Array<Object>
      private static func resultsToObjectList(results: Results<Object>) -> Array<Object> {
          var resultsArray = Array<Object>()
          if results.count > 0 {
              for i in 0...(results.count - 1) {
                  resultsArray.append(results[i])
              }
          }
          return resultsArray
      }
  }