【问题标题】:Deploy app with pre-populated Core Data使用预填充的核心数据部署应用程序
【发布时间】:2018-06-02 05:38:02
【问题描述】:

我正在尝试使用已填充的Core Data 发布我的应用程序。我找到了一些链接,他们解释了如何做到这一点,但要么它不起作用,要么答案很旧。我关注了this 的帖子,但它不起作用。一种解决方案可能是将.sqlite 文件导入应用程序文件夹,然后将它们复制到设备的文件系统,但我不知道该怎么做。有什么方法可以使用现有实体和记录预填充我的核心数据?

【问题讨论】:

标签: swift sqlite core-data


【解决方案1】:

这是我找到的解决方案:

第 1 步
在另一个应用程序中填充您的Core Data 并使用此代码获取文件的路径:

let paths = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
print(documentsDirectory)

第二步
将您的 3 个带有 .sqlite 扩展名的文件拖到您的 xCode 项目中。 (请务必选择Add to targets 选项)。

第三步
创建函数来检查应用的首次运行。

func isFirstLaunch() -> Bool {
    let hasBeenLaunchedBeforeFlag = "hasBeenLaunchedBeforeFlag"
    let isFirstLaunch = !UserDefaults.standard.bool(forKey: hasBeenLaunchedBeforeFlag)
    if (isFirstLaunch) {
        UserDefaults.standard.set(true, forKey: hasBeenLaunchedBeforeFlag)
        UserDefaults.standard.synchronize()
    }
    return isFirstLaunch
}

第四步
复制到AppDelegate:

func getDocumentsDirectory()-> URL {
    let paths = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    return documentsDirectory
}

// MARK: - Core Data stack

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "ProjectName")

    let appName: String = "ProjectName"
    var persistentStoreDescriptions: NSPersistentStoreDescription

    let storeUrl = self.getDocumentsDirectory().appendingPathComponent("FileName.sqlite")

    if UserDefaults.isFirstLaunch() {
        let seededDataUrl = Bundle.main.url(forResource: "FileName", withExtension: "sqlite")
        try! FileManager.default.copyItem(at: seededDataUrl!, to: storeUrl)
    }

    let description = NSPersistentStoreDescription()
    description.shouldInferMappingModelAutomatically = true
    description.shouldMigrateStoreAutomatically = true
    description.url = storeUrl

    container.persistentStoreDescriptions = [description]

    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

第 5 步
如果您想删除新的Core Data 文件,请使用此功能:

func deleteFiles() {
    let fileManager = FileManager.default
    let documentsUrl =  FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first! as NSURL
    let documentsPath = documentsUrl.path

    do {
        if let documentPath = documentsPath {
            let fileNames = try fileManager.contentsOfDirectory(atPath: "\(documentPath)")
            print("all files in cache: \(fileNames)")
            for fileName in fileNames {
                if (fileName.contains("YourFileName")) {
                    let filePathName = "\(documentPath)/\(fileName)"
                    try fileManager.removeItem(atPath: filePathName)
                }
            }
            let files = try fileManager.contentsOfDirectory(atPath: "\(documentPath)")
            print("all files in cache after deleting images: \(files)")
        }
    } catch {
        print("Could not clear temp folder: \(error)")
    }
}

【讨论】:

  • 如果我错了,请纠正我,但这个解决方案不会复制应用程序用于数据的磁盘空间量吗?从资源包中获取种子数据,然后注入核心数据数据库。该数据现在位于磁盘上的两个位置。如果我要部署一个包含 250Mb 数据的应用程序,我不想在磁盘上复制这些数据。
【解决方案2】:

我推荐以下教程。它解释了如何做到这一点。

https://www.youtube.com/watch?v=xcV8Ow9nWFo

【讨论】:

    【解决方案3】:

    我的第 4 步版本:

      private func isFirstLaunch() -> Bool {
        let isFirstLaunchKey = "firstLaunch"
        let userDefaults = UserDefaults.standard
        let isFirstLaunch = !userDefaults.bool(forKey: isFirstLaunchKey)
        
        if isFirstLaunch { userDefaults.setValue(true, forKey: isFirstLaunchKey) }
        return isFirstLaunch
      }
    
      lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "YourProjectCDName")
        
        if isFirstLaunch() {
          if let storeUrl = container.persistentStoreDescriptions.first?.url,
             let seededDataUrl = Bundle.main.url(forResource: "YourProjectCDName", withExtension: "sqlite") {
            do {
              try container.persistentStoreCoordinator.replacePersistentStore(
                at: storeUrl,
                destinationOptions: nil,
                withPersistentStoreFrom: seededDataUrl,
                sourceOptions: nil,
                ofType: NSSQLiteStoreType)
            } catch {
              print(error.localizedDescription)
            }
          } else {
            fatalError("Cannot unwrap URLs!")
          }
        }
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
          if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
          }
        })
        return container
      }()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      相关资源
      最近更新 更多