I want to use realm file with implicit data in my app (In separate project I filled it with data, then made copy of it. Model object is same in both apps).
On simulator, everything is just fine. But when I run app on iPhone, Xcode throws me error.
let path = (NSBundle.mainBundle().pathForResource("testLevel", ofType: "realm"))!
let config = Realm.Configuration(path: path)
let realm = try! Realm(configuration: config) // also tried try! Realm(path: path)
When I print path to .realm file, everything's fine - no nil -
Dont know how to handle it, any ideas? (iOS9)
Error:
fatal error: 'try!' expression unexpectedly raised an error: Error
Domain=io.realm Code=2 "Operation not permitted" UserInfo={Error
Code=2,
NSFilePath=/var/containers/Bundle/Application/7DE151B5-42EE-45C6-8245-B57683EA64D8/sneakers.app/testLevel.realm,
NSLocalizedDescription=Operation not permitted}: file
/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-703.0.18.1/src/swift/stdlib/public/core/ErrorType.swift,
line 54
The Resources folder of your app is read-only, so you can't directly open a writeable Realm file from there.
You'll need to copy it to a directory in which your app has write access (e.g the 'Documents' or 'Application Support' directories) and then try and open it from there. :)
Related
I'm trying to import a custom file from one of my apps to another one (let's call them App_A and App_B). If I export the file directly from App_A and in the share sheet I select App_B everything works fine.
My problem is that the file is saved in iCloud Drive so the user can access it through the system's File app. When I try to select the same file from Files app or in App_B through UIDocumentPickerViewController.
In both cases I run the following code (inside UIDocumentPickerDelegate or AppDelegate):
let access = url.startAccessingSecurityScopedResource()
var error: NSError? = nil
NSFileCoordinator().coordinate(readingItemAt: url, error: &error) { (coorURL) in
do{
let data = try Data(contentsOf: coorURL)
}catch{
print("manage error: \(error.localizedDescription)")
}
if access{
url.stopAccessingSecurityScopedResource()
}
}
The error I get is always the same:
Error Domain=NSCocoaErrorDomain Code=257 ... NSUnderlyingError=0x2803e07b0 {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}} and url.startAccessingSecurityScopedResource() returns always false.
I'm doing this on Xcode 11.4.1, Swift 5, iOS 13.3.1 on device and 13.4.1 on simulator, but the result doesn't change.
Do you have an idea about this weird error? I suppose that if the user select a file and an app to open it the permission would be granted, but probably I'm missing something. Could you help?
I am struggeling with using a new defaultConfiguration for Realm (I think so...)
So what do I try to achieve. I'd like to change the default Realm URL to an Apple App group based ID because I want to use the same Realm from both the Today Extension of my App as well as my App itself.
I found a (slightly outdated Realm tutorial for WatchKit Extension ) where thy put the following to the AppDelegate:
realmUrl: NSURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.net.exchange.On")!
realmUrl.URLByAppendingPathComponent("db.realm")
var config = Realm.Configuration.defaultConfiguration
config.fileURL = realmUrl
Realm.Configuration.defaultConfiguration = config
This works. But my coding to read from Realm, which was working before that, now crashes with the exeption:
This was working up to that change: `let realm = try! Realm()``
But now it creates this beautiful error ;-)
fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm
Code=2 "Operation not permitted" UserInfo={Error Code=2,
NSFilePath=/private/var/mobile/Containers/Shared/AppGroup/4E8402AD-89E4-4138-8B83-CA6B409BB238,
Underlying=n/a, NSLocalizedDescription=Operation not permitted}:
file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-703.0.18.8/src/swift/stdlib/public/core/ErrorType.swift, line 54
I am a bit lost. Hopefully anybody can help me out. TIA John
The problem is that the path fileURL you're setting on Realm's configuration is the path to your app group container, not the path to a file within it. This is due to the following piece of the code:
let realmUrl: NSURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.net.exchange.On")!
realmUrl.URLByAppendingPathComponent("db.realm")
NSURL.URLByAppendingPathComponent(_:) returns a new URL rather than mutating the existing one. Changing the code to something like the following should result in the correct URL being set on the Realm's configuration:
let groupContainerUrl = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.net.exchange.On")!
let realmUrl = groupContainerUrl.URLByAppendingPathComponent("db.realm")
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.
iOS 8.4 | Swift 2.1
When I was tried to create a new folder in NSSearchPathDirectory.ApplicationDirectory, I followed with this error on device (in simulator it did worked, though):
code:
let docuPath:NSURL = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.ApplicationDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0])
ConstantsVO.imagePath = docuPath.URLByAppendingPathComponent("imagegallery")
if !NSFileManager.defaultManager().fileExistsAtPath(ConstantsVO.imagePath.path!)
{
do
{
try NSFileManager.defaultManager().createDirectoryAtPath(ConstantsVO.imagePath.path!, withIntermediateDirectories: true, attributes: nil)
}
catch let error as NSError
{
NSLog("\(error.localizedDescription)")
}
catch
{
print("general error - \(error)", terminator: "\n")
}
}
error
2015-11-02 10:53:21.114 Elmo[218:5055] You don’t have permission to
save the file “imagegallery” in the folder “Applications”. fatal error:
'try!' expression unexpectedly raised an error: Error
Domain=NSCocoaErrorDomain Code=4 "The file “imagegallery” doesn’t
exist."
UserInfo={NSURL=file:///var/mobile/Containers/Data/Application/48D90635-0D66-44C2-81CE-F67BAFDA819A/Applications/imagegallery,
NSFilePath=/var/mobile/Containers/Data/Application/48D90635-0D66-44C2-81CE-F67BAFDA819A/Applications/imagegallery,
NSUnderlyingError=0x16e7d540 {Error Domain=NSPOSIXErrorDomain Code=2
"No such file or directory"}}: file
/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-700.0.59/src/swift/stdlib/public/core/ErrorType.swift,
line 50
However, using NSSearchPathDirectory.DocumentDirectory did worked for me and worked expectedly. But in my application, I've feature to share/import through iTunes, so I have the "Application supports iTunes file sharing" TRUE in my info.plist - this exposed NSSearchPathDirectory.DocumentDirectory in iTunes. I don't want the files/folders that I'm saving through my app to be expose to the user in iTunes. Then where should I save the files/folders yet can able to use file sharing through iTunes by exposing NSSearchPathDirectory.DocumentDirectory?
I found the answer from this post is helpful:
Path directory usable in iOS
As far as I know only these are usable on iOS:
NSDocumentDirectory is Documents/ (persistent, backed up, may
be visible in iTunes) NSLibraryDirectory is Library/
(persistent, backed up, not visibe to the user) NSCachesDirectory is
Library/Caches/ (not backed up, may be cleared by system)
Now after I'm using NSSearchPathDirectory.LibraryDirectory the I'm having no NSFileManager error on device nor the directories/files I'm storing inside NSSearchPathDirectory.LibraryDirectory are exposed to the users in iTunes sharing tab.
Great!
iOS 8.2
iPad a1474
inside app on IPAD, my code is
var dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
user records voice and it saves to
Optional(file:///var/mobile/Containers/Data/Application/2B2028C4-8E7D-4D7F-9FAF-EB843F506A5E/Documents/audio-2015-01-25-144545.m4a)
in Itunes/App,
have tried
MusicDirectory and SharedPublicDirectory
with either of
LocalDomainMask or DocumentDirectory
none work with error
The operation couldn’t be completed. (OSStatus error 2003334207.)
fatal error: unexpectedly found nil while unwrapping an Optional value
so what gives?
why can't app save to local MusicDirectory on the iPad??? there is nothing in the docs to indicate that this is protected area on the iPad.
no issues with iTunes or OSX, this is an iOS issue.
Under iOS8, the path that you have saved won't be the same across launches. The id you see "410AB24E-5FB0-4401-AC59-3C03D676E951" will change with each launch.
The workaround is to save the filename and not the complete path, and to recreate the URL or complete path, by getting the path to the Documents (or tmp) folder and appending the filename to it.