使用swift 3

时间:2017-09-21 15:51:21

标签: core-data swift3

在我的iOS应用中暂时自定义对象的最佳方法是什么?通过“暂时”,我的意思是当应用程序关闭时,对象“消失”。

  • UserDefaults 不会保留自定义对象(从我看到的内容)。
  • Keychain 过度,因为我不需要加密任何数据。
  • CoreData (内存中)似乎是唯一的其他选择,但它看起来有点沉重。

还有其他选择吗?

CoreData的苹果文档似乎是一个很好的起点,如果这是可行的方法,但在查看这些示例后,我甚至无法编译它们。

*更新的解决方案* 毕竟我决定选择一个单身人士......

    // Where userDto inherits NSObject, NSCoding and provides "func encode(with aCoder: NSCoder)" and "init?(coder aDecoder: NSCoder)" methods per the NSCoding protocol.

    // Store
    PersistenceManager.instance.store(userDto)
    PersistenceManager.instance.storeTemporary(userDto)

    // Retrieve
    if let dto:UserDto = PersistenceManager.instance.retrieve() {
       // Do something..
    }

    if let dto:UserDto = PersistenceManager.instance.retrieveTemporary() {
       // Do something..
    }

    import Foundation
    import CoreData

    final class PersistenceManager {
       static let instance = PersistenceManager()

       private var localStore = Dictionary<String, NSCoding?>()

       private init() {
       }

       // MARK: -- Store

       public func store<T>(_ data:T) where T: NSCoding {
          let key = getKey(for: T.self)
          let archivedNSCoding:NSData = archive(data)
          let userDefaults = UserDefaults.standard
          userDefaults.set(archivedNSCoding, forKey: key)
          userDefaults.synchronize()
       }

       public func storeTemporary<T>(_ data:T) where T: NSCoding {
          let key = getKey(for: T.self)
          localStore[key] = data
       }


       // MARK: -- Retrieve

       public func retrieve<T>() -> T? where T: NSCoding {
          let key = getKey(for: T.self)
          if let data = UserDefaults.standard.object(forKey: key) as? NSData {
             if let unarchived = unarchive(with: data) as? T {
                return unarchived
             }
          }

          return nil
       }

       public func retrieveTemporary<T>() -> T? where T: NSCoding {
          let key = getKey(for: T.self)
          return localStore[key] as? T
       }

       // MARK: -- Remove

       public func remove<T>(_ type: T.Type) -> T? where T: NSCoding {
          if let data:T = retrieve() {
             let key = getKey(for: type)
             let userDefaults = UserDefaults.standard
             userDefaults.removeObject(forKey: key)
             userDefaults.synchronize()
             return data
          } else {
             return nil
          }
       }

       public func removeTemporary<T>(_ type: T.Type) -> T? where T: NSCoding {
          let key = getKey(for: type)
          let data:T? = localStore[key] as? T
          localStore.removeValue(forKey: key)
          return data
       }

       // MARK: -- Miscellaneous

       public func exists<T>(_ type: T.Type) -> Bool where T: NSCoding {
          let key = getKey(for: type)
          return UserDefaults.standard.object(forKey: key) != nil
       }

       private func storeTemporary(data:NSCoding, forKey key: String) {
          localStore[key] = data
       }

       // MARK: -- Helper methods

       private func getKey<T>(for type: T.Type) -> String where T: NSCoding {
          return String(describing: T.self)
       }

       private func archive(_ data: NSCoding) -> NSData {
          return NSKeyedArchiver.archivedData(withRootObject: data) as NSData
       }

       private func unarchive(with data: NSData) -> NSCoding? {
          if let unarchivedNSCoding = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as? NSCoding {
             return unarchivedNSCoding
          } else {
             return nil
          }
       }
    }

2 个答案:

答案 0 :(得分:0)

这取决于你想要达到的目标。如果您的数据集非常小且不会增加太多,那么一旦升级到Swift4,您总是可以尝试使用JSONSerialization或新的Codable协议写入JSON文件。

如果你的数据集随着时间的推移而增加,想要在CoreData,SQLite或Realm上做一些更高级的逻辑。我建议看一下Realm,这是一个非常友好的数据库,他们声称它的性能比SQLite好,因此CoreData也是如此。 CoreData使用了SQLite。

使用领域,您可以轻松编写一个对象,并通过简单的调用领域编写,您就完成了。 如果您没有任何SQL经验,那么Realm或CoreData就是您的最佳选择。

我自己不喜欢CoreData,因为我更喜欢访问SQL而且我不喜欢不得不围绕一个全新的系统来解决它有自己的怪癖和想法来处理。它确实可以很好地集成到iOS和Xcode中,这对你来说也是一个很大的优势。

Realm自己的数据库浏览器很好,但是缺乏足够的功能,并且不支持解密加密的Realm数据库(这对我来说真的很奇怪)。 Realm在代码大小方面也相当沉重,但是你可以通过在构建期间运行剥离脚本来摆脱它。

答案 1 :(得分:0)

经过一番说服,我确实决定选择一个单身人士。

在我的特定情况下,我只需要在临时存储中存储几个特定对象类型中的任何一个的1个版本(因此类名作为键)。我还决定可能需要在UserDefaults中存储这些相同对象的选项,所以我也添加了该代码。

<强>用法

// Where userDto inherits NSObject, NSCoding and provides "func encode(with aCoder: NSCoder)" and "init?(coder aDecoder: NSCoder)" methods per the NSCoding protocol.

// Store
PersistenceManager.instance.store(userDto)
PersistenceManager.instance.storeTemporary(userDto)

// Retrieve
if let dto:UserDto = PersistenceManager.instance.retrieve() {
   // Do something..
}

if let dto:UserDto = PersistenceManager.instance.retrieveTemporary() {
   // Do something..
}

import Foundation
import CoreData

final class PersistenceManager {
   static let instance = PersistenceManager()

   private var localStore = Dictionary<String, NSCoding?>()

   private init() {
   }

   // MARK: -- Store

   public func store<T>(_ data:T) where T: NSCoding {
      let key = getKey(for: T.self)
      let archivedNSCoding:NSData = archive(data)
      let userDefaults = UserDefaults.standard
      userDefaults.set(archivedNSCoding, forKey: key)
      userDefaults.synchronize()
   }

   public func storeTemporary<T>(_ data:T) where T: NSCoding {
      let key = getKey(for: T.self)
      localStore[key] = data
   }


   // MARK: -- Retrieve

   public func retrieve<T>() -> T? where T: NSCoding {
      let key = getKey(for: T.self)
      if let data = UserDefaults.standard.object(forKey: key) as? NSData {
         if let unarchived = unarchive(with: data) as? T {
            return unarchived
         }
      }

      return nil
   }

   public func retrieveTemporary<T>() -> T? where T: NSCoding {
      let key = getKey(for: T.self)
      return localStore[key] as? T
   }

   // MARK: -- Remove

   public func remove<T>(_ type: T.Type) -> T? where T: NSCoding {
      if let data:T = retrieve() {
         let key = getKey(for: type)
         let userDefaults = UserDefaults.standard
         userDefaults.removeObject(forKey: key)
         userDefaults.synchronize()
         return data
      } else {
         return nil
      }
   }

   public func removeTemporary<T>(_ type: T.Type) -> T? where T: NSCoding {
      let key = getKey(for: type)
      let data:T? = localStore[key] as? T
      localStore.removeValue(forKey: key)
      return data
   }

   // MARK: -- Miscellaneous

   public func exists<T>(_ type: T.Type) -> Bool where T: NSCoding {
      let key = getKey(for: type)
      return UserDefaults.standard.object(forKey: key) != nil
   }

   private func storeTemporary(data:NSCoding, forKey key: String) {
      localStore[key] = data
   }

   // MARK: -- Helper methods

   private func getKey<T>(for type: T.Type) -> String where T: NSCoding {
      return String(describing: T.self)
   }

   private func archive(_ data: NSCoding) -> NSData {
      return NSKeyedArchiver.archivedData(withRootObject: data) as NSData
   }

   private func unarchive(with data: NSData) -> NSCoding? {
      if let unarchivedNSCoding = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as? NSCoding {
         return unarchivedNSCoding
      } else {
         return nil
      }
   }
}