问题
I'm developing an app with realmSwift. I want to set preset data on realm db initially, then I want it to show up when user open the app and to make it writable. I write some code based on other questions about realm bundle. such as Realm - Add file with initial data to project (iOS/Swift) and Realm fileExists is always true Then I managed to do what I want to on simulator but it doesn't work on a physical device. This is the code I wrote on AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
openRealm()
let config = Realm.Configuration(
fileURL: Bundle.main.url(forResource: "default", withExtension: "realm"),
readOnly: true)
var realm = try! Realm(configuration: config)
print(Realm.Configuration.defaultConfiguration.fileURL)
return true
}
func openRealm() {
let realm = try! Realm()
let bundlePath = Bundle.main.path(forResource: "default", ofType: "realm")
let destPath = Realm.Configuration.defaultConfiguration.fileURL?.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: destPath!) {
//File exist, do nothing
print("File exist")
try! fileManager.removeItem(atPath: destPath!)
do {
//Copy file from bundle to Realm default path
try fileManager.copyItem(atPath: bundlePath!, toPath: destPath!)
print("Copied")
} catch {
print("\n",error)
}
} else {
do {
try fileManager.copyItem(atPath: bundlePath!, toPath: destPath!)
print("Copied")
} catch {
print("\n",error)
}
}
}
回答1:
There are 3 issue with your code: firstly, you shouldn't be using the true part of your if branch, since as long as you run openRealm() from your AppDelegate's applicationDidFinishLaunching and before you'd make any calls to Realm the only reason why a default.realm file can exist is because your app isn't launching for the first time, so you shouldn't overwrite it.
Secondly, you shouldn't be calling let realm = try! Realm() at the beginning of your openRealm function since that will actually create a realm, which will make harder it than it should be to detect if the prepopulated .realm file was already copied to the defaultPath or not. You don't actually need to call try! Realm() at all in the openRealm() function unless you want to perform a migration before your Realm could be opened from anywhere else in your code.
func openRealm() {
let bundlePath = Bundle.main.path(forResource: "default", ofType: "realm")!
let defaultPath = Realm.Configuration.defaultConfiguration.fileURL?.path!
let fileManager = FileManager.default
// Only need to copy the prepopulated `.realm` file if it doesn't exist yet
if !fileManager.fileExists(atPath: defaultPath){
print("use pre-populated database")
do {
try fileManager.copyItem(atPath: bundlePath, toPath: defaultPath)
print("Copied")
} catch {
print(error)
}
}
Lastly, you shouldn't be creating a new configuration where you overwrite the path of Realm with your bundlePath since files in the application bundle shouldn't be modified ever (that will break your code signature). Moreover, you already copied your prepopulated file from your application bundle to Realm's defaultPath, so if you simply call Realm(), it will be modifying the prepopulated file, since it is stored at the default location.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
openRealm()
print(Realm.Configuration.defaultConfiguration.fileURL)
return true
}
来源:https://stackoverflow.com/questions/50483432/realm-data-doesnt-show-up-on-a-physical-device