Unable to open a realm at path - ios

I am trying to use a bundled realm file without success. I know that my realm file was copied successfully to my application’s Directory but I ca not read it.
fatal error: 'try!' expression unexpectedly raised an error: "Unable
to open a realm at path
'/Users/…/Library/Developer/CoreSimulator/Devices/…/data/Containers/Data/Application/…/Documents/default-v1.realm'.
Please use a path where your app has read-write permissions."
func fullPathToFileInAppDocumentsDir(fileName: String) -> String {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,NSSearchPathDomainMask.UserDomainMask,true)
let documentsDirectory = paths[0] as NSString
let fullPathToTheFile = documentsDirectory.stringByAppendingPathComponent(fileName)
return fullPathToTheFile
}
In didFinishLaunchingWithOptions:
let fileInDocuments = fullPathToFileInAppDocumentsDir("default-v1.realm")
if !NSFileManager.defaultManager().fileExistsAtPath(fileInDocuments) {
let bundle = NSBundle.mainBundle()
let fileInBundle = bundle.pathForResource("default-v1", ofType: "realm")
let fileManager = NSFileManager.defaultManager()
do {
try fileManager.copyItemAtPath(fileInBundle!, toPath: fileInDocuments)
} catch { print(error) }
}
And setting the configuration used for the default Realm:
var config = Realm.Configuration()
config.path = fileInDocuments
Realm.Configuration.defaultConfiguration = config
let realm = try! Realm(configuration: config) // It fails here!!! :-)
As the documentation suggests, I have tried as well to open it directly from the bundle path by setting readOnly to true on the Realm.Configuration object. I am not sure if this is something related to Realm or if I am overlooking something with the file system…. I have also tried to store the file in the Library folder.
Realm 0.97.0
Xcode Version 7.1.1

I tried to open the realm file using Realm's browser app and the file does not open anymore. It has now new permissions: Write only (Dropbox). So, I decided to change the file permission back to read/write using file manager’s setAttributes method. Here is how I did it:
// rw rw r : Attention for octal-literal in Swift "0o".
let permission = NSNumber(short: 0o664)
do {
try fileManager.setAttributes([NSFilePosixPermissions:permission], ofItemAtPath: fileInDocuments)
} catch { print(error) }
The realm file can now be open at this path.

That exception gets thrown whenever a low level I/O operation is denied permission to the file you've specified (You can check it out on Realm's GitHub account).
Even though everything seems correct in your sample code there, something must be set incorrectly with the file location (Whether it be the file path to your bundle's Realm file, or the destination path) to be causing that error.
A couple of things I can recommend trying out.
Through breakpoints/logging, manually double-check that both fileInDocuments and fileInBundle are being correctly created and are pointing at the locations you were expecting.
When running the app in the Simulator, use a tool like SimPholders to track down the Documents directory of your app on your computer, and visually ensure that the Realm file is being properly copied to where you're expecting.
If the Realm file is in the right place, you can also Realm's Browser app to try opening the Realm file to ensure that the file was copied correctly and still opens properly.
Try testing the code on a proper iOS device to see if the same error is occurring on the native system.
If all else fails, try doing some Realm operations with the default Realm (Which will simply deposit a default.realm file in your Documents directory), just to completely discount there isn't something wrong with your file system
Let me know how you go with that, and if you still can't work out the problem, we can keep looking. :)

This will occur if you have your realm file open in Realm Studio at same time you relaunch your app. Basically in this case Realm can't get write permissions if Studio already has them.

To add to the solution based on what I've discovered, make note of what error Realm reports when it throws the exception, as well as the type of Error that is passed.
As of writing, Realm documents their errors here:
https://realm.io/docs/objc/latest/api/Enums/RLMError.html
What this means is that you can find out if your Realm file has permissions problems and react to those based on Realm passing you a RLMErrorFilePermissionDenied. Or if the file doesn't exist with RLMErrorFileNotFound.
The tricky thing I'm finding is when you get a more generic RLMErrorFileAccess, but that's for another question on Stack Overflow...

I had the same issue and tried too many ways to fix it. The easiest way to fix this problem is manually creation of the folder XCode cannot reach '/Users/…/Library/Developer/CoreSimulator/Devices/…/data/Containers/Data/Application/…/Documents/...' as explained at https://docs.realm.io/sync/using-synced-realms/errors#unable-to-open-realm-at-path-less-than-path-greater-than-make_dir-failed-no-such-file-or-directory
Once you created this folder and run the project, XCode creates the Realm files inside this folder automatically.

Related

iOS reading from a file

I'm trying to get my iPhone app to load text from a file into a string array, with 1 line from the file per array element.
I've created an input file as a text file using sublime text. I dragged the file (which is located inside of a folder inside of my project directory) into xCode into a folder in the same location in the project heirarchy.
I also tried adding it as a bundle (by copying the folder and renaming it with the .bundle extension), to no avail. Currently, my app has the file in 2 places (Obviously I plan to delete the unneeded version, but I'm not sure how this will work so I've left it for now).
I've written a function that I want to read my file, and assemble its contents into an array:
func readFromFile(filename: String) -> [String]? {
guard let theFile = Bundle.main.path( forResource: fileName, ofType: "txt") else {
return nil // ALWAYS returns nil here: Seems 'filename' can't be found?????
}
do { // Extract the file contents, and return them as a split string array
let fileContents = try String(contentsOfFile: theFile)
return fileContents.components(separatedBy: "\n")
} catch _ as NSError {
return nil
}
}
As it stands, the function always returns nil at the location commented in the code.
I've been working on this for ~6hrs (and tried every suggestion I could find on StackOverflow, google etc) and I'm just getting more and more confused by the differences between the various versions of Swift and intricacies of iOS development. I can't seem to find a consistent answer anywhere. I've checked the apple documentation but it's too high level with no example code for me to understand at my swift beginner level.
I also tried naming the file with a ".txt" extension but that didn't help either.
The file must certainly be named alert01.txt if you are going to refer to it as forResource: "alert01", ofType: "txt".
Loading from a bundle will not work. The file needs to be part of your project as shown in the first entry.
However, your code is not going to work because you have created a folder reference. That means the folder PanicAlertFiles is being copied with all its contents into your bundle. Your code will need to dive into that folder in order to retrieve your file. Use path(forResource:ofType:inDirectory:) to do that, or (if you don't want to have to code the file name explicitly) get the folder and then use the FileManager to examine its contents.

iOS Realm readOnly causes empty result

I have a little problem with realm setting readOnly to true in the configuration. I am using Swift but I am using the normal Realm.framework ... Maybe this causes the error but I don't think so. (I am using it because I don't want to refactor my whole code...)
Here is an example of what I am talking about.
I tried this:
if let path = NSBundle.mainBundle().pathForResource("database", ofType: "realm")
{
//Alternative: or move the file from the app bundle into a writable location
var config = RLMRealmConfiguration()
config.path = path
config.readOnly = true
do {
try self.realm = RLMRealm(configuration:config)
} catch {
print("ERROR")
}
I also tried this:
if let path = NSBundle.mainBundle().pathForResource("database", ofType: "realm")
{
//Alternative: or move the file from the app bundle into a writable location
var config = RLMRealmConfiguration()
config.path = path
config.readOnly = true
RLMRealmConfiguration.setDefaultConfiguration(config)
do {
try self.realm = RLMRealm(configuration: RLMRealmConfiguration.defaultConfiguration())
} catch {
print("ERROR")
}
Both of them fail every time. (Printing: "Error") I figured out that the problem is that readOnly is set to true. I got both snippets working by setting readOnly to false.
Do you have any idea how to fix this issue?
I printed the Error and it is:
Error Domain=io.realm Code=2 "Unable to open a realm at path
'/Users/UserName/Library/Developer/CoreSimulator/Devices/NR/data/Containers/Bundle/Application/NR/AppName.app/database.realm'"
UserInfo={NSFilePath=/Users/UserName/Library/Developer/CoreSimulator/Devices/NR/data/Containers/Bundle/Application/NR/AppName.app/database.realm,
NSLocalizedDescription=Unable to open a realm at path
'/Users/UserName/Library/Developer/CoreSimulator/Devices/NR/data/Containers/Bundle/Application/NR/AppName.app/database.realm',
Error Code=2}
Okay guys I have no idea what happened but it works now.
I made a sample project with the database of their database and an object for their database and tried my code and it worked. (Both of them)
This confused me pretty much and I thought maybe my database is damaged or the object is wrong. I replaced their database in the sample project with my database and used my object and surprise it worked...
So I just deleted my database in my normal project (as I did 1000 times before) and added it again. I just put it on the top of my project structure and tried it again and it is working now...

How to input a default .txt file into an iPhone through Xcode in Swift

I am trying to read from a text file that I have already created on my desktop. I put this Story.txt into the corresponding file path on my computer through Xcode, something along these lines :
(/Users/username/Library/Developer/CoreSimulator/Devices/12F046A7-a lot more numbers/data/Containers/Data/Application/8AECCA06-160C-4702-B16E-FF50B2A145F5)
and the code works perfectly. However, when I try to run the app on my iPhone, it changes the file path and Xcode doesn't automatically transfer my files to my iPhone documents folder at this file path.
(/var/mobile/Containers/Data/Application/139C80A3-more numbers/Documents)
How do I manually put a .txt file at this location?
Here is the code I use to read the file.
func loadStory()
{
if let dir : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first
{
let path = dir.stringByAppendingPathComponent("Story.txt")
print(path)
do
{
//reads file
let text:String = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String
}
catch {/* error handling here */}
}
}
Since it seems you want the file included with your app, do not attempt to manually install the file somewhere on your computer. That only works with the Simulator if you happen to put the file in just the right place.
Instead, add the file to your Xcode project. Then the file will be added to your app's resource bundle. Then you can access the file using NSBundle to get its path. It will not be in the app's Documents folder. It will be in the app's bundle.
See Where to place a .txt file and read from it in a IOS project for more details.
You need to add it to your project. Drag and drop it inside your project so it'll be bundled in. Than you can access it using
Let string = NSBundle.mainBundle().resourcePath as NSString
String.stringByAppendingPathComponent('Story.txt')
If you could change the file from .txt to plist, you could integrate it on your project, and never think where it is, it will be always accessible.

I cannot get "default.realm" file in my iOS Simulator

I want to access the Realm data file which is created on iOS Simulator. With the instruction of this question, I got to the following directory:
~/Library/Developer/CoreSimulator/Devices/0AB2D954-A3D5-4ABF-A5C5-CC470FB4ABDE/data/Containers/Data/Application/7192723E-7582-48EB-8B66-14E1073D7CE6/Documents
However, the directory has only the following Realm files:
default.realm.note
default.realm.log_a
default.realm.log_b
default.realm.log
default.realm.lock
and I cannot find the Realm file default.realm.
Also, when I open up the Realm Browser and access to the directory, all the files above except default.realm.note is grayed-out and I cannot access the Realm data.
Note that I create a Realm instance and save data by realm.write:
try! self.realm.write {
for (_, value) in json { // json is from SwiftyJSON
let pitcher = Player()
player.year.value = value["year"].int
player.name = value["name"].stringValue
self.realm.add(player)
}
}
So how can I access the Realm data file?
Realm's auxiliary files (.note, .lock, etc) are always created next to the .realm file itself. So it seems like something is deleting the realm file without deleting the auxiliary files, which would explain why you can't find it.
Please make sure you're not deleting this Realm file somewhere in your code.

realm.io writeCopyToPath ? what's the inverse operation?

so I have some realm swift code:
let realm = Realm()
realm.writeCopyToPath(tempfile! , encryptionKey: nil)
let newasset = CKAsset(fileURL: NSURL(fileURLWithPath: tempfile!, isDirectory: false))
and then I save off the newasset to cloudkit...
but when I bring it back,
let defaultPath = Realm().path
var someError: NSError?
NSFileManager.defaultManager().removeItemAtPath(defaultPath, error: &someError)
if someError != nil {
println("Error removing realm file, \(someError)")
}
NSFileManager.defaultManager().copyItemAtPath(asset.fileURL.path!, toPath: defaultPath, error: &someError)
if someError != nil {
println("Error copying realm file into place, \(someError)")
}
it does not seem to work... I'm wondering if there is another way to bring back the realm file and place it where realm expects it?
The default location and file name of the default Realm file is default.realm, located in the app's Documents directory. As long you've correctly copied the Realm file out of CloudKit and to that location with the proper file name, accessing that file via calling Realm() should just work straight out of the box.
It sounds like you've got a few points in here that you can potentially test to see if anything is failing:
1) Make sure the duplicate Realm file is being created properly.
2) Ensure the file is uploaded to CloudKit properly, without fail.
3) Ensure the file came back down from CloudKit properly without any errors.
4) Double-check that copying the file from CloudKit to the default Realm file path succeeded.
If that all didn't work, please let me know here what sort of error you're specifically getting. Thanks, and good luck!

Resources