swift - 核心数据提取不适用于真实设备 - 核心数据 Swift 3

标签 swift xcode core-data nsfetchrequest

该应用程序的工作原理如下: bundle 中有一个内置的持久存储(当然是 3 个文件)。当应用程序启动时,它会将商店复制到核心数据目录(仅限第一次)并开始获取它。

  1. 核心数据提取在模拟器上运行良好,但在插入计算机的真实设备上无法提取任何内容。以下是 AppDelegate、CoreDataStack、ViewController 获取的代码以及将商店复制到应用程序目录的函数。

  2. 此外,我未能使用获取不同的结果,只是我无法将不同的结果放入数组中。相反,我使用非常糟糕的方式获取所有内容并将它们放入一个集合中。

第一个问题是需要立即解决的问题。非常感谢任何建议和帮助!

// application function of AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

_ = coreDataStack.mainContext

    guard let tabc = window?.rootViewController as? UITabBarController else {
        fatalError("Tab bar controller mis-configured.")
    }

    // Set the status bar to white

    guard let navc1 = tabc.viewControllers?[0] as? UINavigationController,
        let wordLibVC = navc1.topViewController as? WordLibraryViewController else {
            fatalError("Navigation controller[0] mis-configured.")
    }
    wordLibVC.coreDataStack = coreDataStack
    wordLibVC.levelDict = levelDict

    return true
}

// Core Data Stack Class
class CoreDataStack {

// MARK: - Properties
fileprivate let modelName: String

var storeDirectory: URL = NSPersistentContainer.defaultDirectoryURL()

lazy var mainContext: NSManagedObjectContext = {
    return self.container.viewContext
}()

lazy var container: NSPersistentContainer = {

    let container = NSPersistentContainer(name: self.modelName)

    self.seedCoreDataContainerIfFirstLaunch()

    container.loadPersistentStores { (storeDescription, error) in

        if let error = error as? NSError {

            fatalError("Could not load persistent stores. \(error), \(error.userInfo)")
        }
    }
    return container
}()

init(modelName: String) {
    self.modelName = modelName
}
}

// fetch function in ViewController
func executeRequest() {
    let fetchRequest = NSFetchRequest<Word>(entityName: "Word")
    fetchRequest.propertiesToFetch = ["level"]

    let levelSort = NSSortDescriptor(key: "level", ascending: true)
    fetchRequest.sortDescriptors = [levelSort]

    do {
        // The following line returns an empty array
        let results = try coreDataStack.mainContext.fetch(fetchRequest)
        // The above line returns an empty array
        var levels: [Int] = []
        for result in results {
            levels.append(Int(result.level))
        }
        let distinctLevels = Set(levels)
        let sortedLevels = Array(distinctLevels).sorted()
        print(sortedLevels)
        let stringLevels = sortedLevels.map{String($0)}
        dataSource.append(stringLevels)
    } catch let error as NSError {
        print("Could not fetch \(error), \(error.userInfo)")
    }
}

// This is the function that copies the store from the bundle to the directory
func seedCoreDataContainerIfFirstLaunch() {

    let previouslyLaunched = UserDefaults.standard.bool(forKey: "previouslyLaunched")
    if previouslyLaunched { return }
    UserDefaults.standard.set(true, forKey: "previouslyLaunched")

    // 1. sqlite file
    let destSQLite = storeDirectory.appendingPathComponent("wordlib.sqlite")
    let sourceSQLite = Bundle.main.url(forResource: "wordlib", withExtension: "sqlite")!
    try? FileManager.default.removeItem(at: destSQLite)
    do {
        try FileManager.default.copyItem(at: sourceSQLite, to: destSQLite)
        print("wordlib.sqlite seeded.")
    } catch let error as NSError {
        print("Could not copy sqlite file, \(error.localizedDescription)")
    }

    // 2. sqlite-shm file
    let destSHM = storeDirectory.appendingPathComponent("wordlib.sqlite-shm")
    let sourceSHM = Bundle.main.url(forResource: "wordlib", withExtension: "sqlite-shm")!
    try? FileManager.default.removeItem(at: destSHM)
    do {
        try FileManager.default.copyItem(at: sourceSHM, to: destSHM)
        print("wordlib.sqlite-shm seeded.")
    } catch let error as NSError {
        print("Could not copy shm file. \(error.localizedDescription)")
    }

    // 3. .sqlite-wal
    let destWAL = storeDirectory.appendingPathComponent("wordlib.sqlite-wal")
    let sourceWAL = Bundle.main.url(forResource: "wordlib", withExtension: "sqlite-wal")!
    try? FileManager.default.removeItem(at: destWAL)
    do {
        try FileManager.default.copyItem(at: sourceWAL, to: destWAL)
        print("wordlib.sqlite-wal seeded.")
    } catch let error as NSError {
        print("Error: \(error.localizedDescription), Could not copy wal file.")
    }
}

最佳答案

经过几天的挣扎,这个问题解决了。

操作系统和 iOS 文件系统有不同的要求:

OS 文件名不区分大小写,而 iOS 文件名区分大小写。

此外,在加载持久存储时,核心数据会尝试查找与您的数据模型同名的存储文件。因此,如果您的拼写相同但案例文件名不同,您将无法在真实设备上获取任何内容,但在模拟器上却可以。

因此,如果您只有一个存储文件,始终建议数据模型和存储文件的名称完全相同。

关于swift - 核心数据提取不适用于真实设备 - 核心数据 Swift 3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40980774/

相关文章:

iphone - 存储在 "External Storage"中的 Core Data BLOB 数据是否加密?

ios - UIPrintInteractionController 打印项目不显示/工作

ios - 在自定义相机 swift + xcode 中切换相机时平滑过渡

xcode - 使用 swift 在 OS X 中禁用 sleep 模式

ios - 带有 NSFetchedResultController 的 TableView 在屏幕外显示损坏的单元格

objective-c - Objective-C - 核心数据和建立关系?

swift - 多个动画困惑

ios - 使用PaypalSDK iOS iOS导航颜色在iOS中未更改

ios - 如何使用 Swift 使文本字段的文本成为下一个导航 Controller 的标题?

iphone - 如何将iPad应用程序作为内部应用程序分发?