iOS9 FileManager File permissions change
The original code is just wrong. You need to use the octal representation of the permissions:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/octal-literal
Correct code:
let fileManager = NSFileManager.defaultManager()
let directory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let path = "\(directory)/file.txt"
let attributes: [String:AnyObject] = [NSFilePosixPermissions: NSNumber(short: 0o666)]
let success = fileManager.createFileAtPath(path, contents: nil, attributes: attributes)
if success && fileManager.isWritableFileAtPath(path) && fileManager.isReadableFileAtPath(path) {
NSLog("Worked!")
} else {
NSLog("Failed!")
}
A function I used to test all possible permissions.
func testPermissions() {
let types: [Int16] = [0o666, 0o664, 0o662, 0o660, 0o646, 0o626, 0o606, 0o466, 0o266, 0o066]
for t in types {
testCreateFile(t)
}
}
func testCreateFile(permissions: Int16) {
let attributes: [String:AnyObject] = [NSFilePosixPermissions: NSNumber(short: permissions)]
let directory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let filename = "filename\(permissions.description)"
let path = "\(directory)/\(filename)"
let fileManager = NSFileManager.defaultManager()
let success = fileManager.createFileAtPath(path, contents: nil, attributes: attributes)
if success && fileManager.isWritableFileAtPath(path) && fileManager.isReadableFileAtPath(path) {
let octal = String(format:"%o", permissions)
NSLog("It worked for \(octal)")
}
}
iOS9 Swift File Creating NSFileManager.createDirectoryAtPath with NSURL
I figured this one out. createDirectoryAtPath() is unable to process a path with the "file://" prefix. To get a path without the prefix you must use path() or relativePath().
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let logsPath = documentsPath.URLByAppendingPathComponent("logs")
do {
try NSFileManager.defaultManager().createDirectoryAtPath(logsPath.path!, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
NSLog("Unable to create directory \(error.debugDescription)")
}
Incorrect path (notice file://):
file:///var/mobile/Containers/Data/Application/F2EF2D4F-94AF-4BF2-AF9E-D0ECBC8637E7/Documents/logs/
Correct path:
/var/mobile/Containers/Data/Application/F2EF2D4F-94AF-4BF2-AF9E-D0ECBC8637E7/Documents/logs/
Permission Denied when trying to create a directory in Application Support
The problem is in this line
directory = URL(fileURLWithPath: directory).appendingPathComponent("IAP").absoluteString
This return filePath, while below function required simple path of directory.
fileManager.createDirectory(atPath: directory, withIntermediateDirectories: true, attributes: nil)
So either change this line
directory = URL(fileURLWithPath: directory).appendingPathComponent("IAP").absoluteString
with this line
directory = directory + "/IAP"
OR
change same line with below line
let url = URL(fileURLWithPath: directory).appendingPathComponent("IAP")
and use this function to create directory
fileManager.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
Hope this helps you.
Error: You don’t have permission to save the file in the folder
Thanks to this post I realized its because of this line:
let destString = destPath.absoluteString
I had to change it to:
let destString = documentsURL.relativePath
Which allowed me to greatly simplify my function:
static func unzipFile(atPath path: String) -> Bool
{
let destString = documentsURL.relativePath
let success: Void? = try? SSZipArchive.unzipFile(atPath: path, toDestination: documentsURL.relativePath, overwrite: true, password: nil)
if success == nil
{
return false
}
return true
}
Different path URL for FileManager everytime I open the app
You are using the wrong API. absoluteString
(in rootURL.absoluteString
) returns the string representation including the scheme file://
. The correct API for file system URLs is path
I recommend to use the URL related API as much as possible
public func directoryExists(at url: URL) -> Bool {
let fileManager = FileManager.default
var isDir : ObjCBool = false
if fileManager.fileExists(atPath: url.path, isDirectory:&isDir) {
return isDir.boolValue
} else {
return false
}
}
and compose the URL in a more reliable way
func createARObjectDirectory() {
let rootURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
if directoryExists(at: rootURL.appendingPathComponent(DefaultURL.arObjectUrlDirectoryName) {
Logger.logServer("ARObject directly found")
} else {
createNewDirectory(name: DefaultURL.arObjectUrlDirectoryName)
}
}
And this is swiftier too
public func createNewDirectory(name: String) {
let documentDirectory = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let dirURL = documentDirectory.appendingPathComponent(name)
do
{
try FileManager.default.createDirectory(at: dirURL, withIntermediateDirectories: false, attributes: nil)
}
catch let error as NSError
{
Logger.logError("Unable to create directory \(error.debugDescription)")
}
Logger.logInfo("Dir Path = \(dirPath.path)")
}
Related Topics
How to Add UIpickerview in UIalertcontroller
How to Navigate from Initial UIviewcontroller to UIsplitviewcontroller in Swift
Changing a Label in Prepareforsegue
Open View Controller When Remote Notification Pressed
Swift: Benefits of Curry Function
(Key: Anyobject, Value: Anyobject)' Does Not Have a Member Named 'subscript'
Swift Struct Adopting Protocol with Static Read-Write Property Doesn't Conform
Accessing "Self" in Initializing Closure
Os X App Doesn't Launch New Window on Dock Icon Press in Swift
How to Detect When Two Objects Touch in Spritekit
Swift - Scanning with Ikscannerdeviceview on Osx
Multiple Scatterplots Using Core Plot and Swift
Error: Variable with Getter/Setter Cannot Have an Initial Value
Calling C++ from Swift - What Is The Equivalent of Std::Vector<T>