该应用程序的工作原理如下: bundle 中有一个内置的持久存储(当然是 3 个文件)。当应用程序启动时,它会将商店复制到核心数据目录(仅限第一次)并开始获取它。
核心数据提取在模拟器上运行良好,但在插入计算机的真实设备上无法提取任何内容。以下是 AppDelegate、CoreDataStack、ViewController 获取的代码以及将商店复制到应用程序目录的函数。
此外,我未能使用获取不同的结果,只是我无法将不同的结果放入数组中。相反,我使用非常糟糕的方式获取所有内容并将它们放入一个集合中。
第一个问题是需要立即解决的问题。非常感谢任何建议和帮助!
// 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/