Daymon Schroeder
Daymon Schroeder

Reputation: 682

Swift 2: Can't call createDirectoryAtUrl with definition

I am currently developing an application on xCode7 beta 2 using Swift 2 (it is a requirement at the moment).

Here is what I am trying to call:

let fileManager = NSFileManager.defaultManager()
let tempDirectoryURL = NSURL(string: NSTemporaryDirectory())!
let directoryURL = tempDirectoryURL.URLByAppendingPathComponent("com.test.manager/multipart.form.data")
var error: NSError?

if fileManager.createDirectoryAtURL(directoryURL, createIntermediates: true, attributes: nil) {
 ...
}

Here is the error I am getting:

Cannot invoke 'createDirectoryAtURL' with an argument list of type '(NSURL, createIntermediates: Bool, attributes: nil)'

Which is confusing because the definition for createDirectoryAtURL I am getting when I right click and "view definition" is:

 func createDirectoryAtURL(
    url: NSURL, 
    withIntermediateDirectories createIntermediates: Bool, 
    attributes: [String : AnyObject]?
 ) throws

The only only paramater that doesn't match verbatim is the last parameter "attributes", which the documentation (and all example usage) explicitly states can accept the value nil.

Apple's Documentation:

If you specify nil for this parameter, the directory is created according to the umask(2) Mac OS X Developer Tools Manual Page of the process.

Upvotes: 2

Views: 949

Answers (1)

rickster
rickster

Reputation: 126137

Two problems here:

  1. You've switched an parameter label for its internal name. The second parameter's label — part of the function name, required for calling it — is withIntermediateDirectories. The implementor of that function refers to that parameter's value as createIntermediates. So your call should look like this:

    fileManager.createDirectoryAtURL(directoryURL, withIntermediateDirectories: true, attributes: nil)
    
  2. Note the signature you quoted:

    func createDirectoryAtURL( ... ) throws
    

    You're using this call as the condition of an if statement — that means you need a function that returns Bool. The compiler is trying to satisfy the requirement of the if statement by looking for a function called createDirectoryAtURL whose type signature is (NSURL, Bool, [String : AnyObject]?) -> Bool, and complaining because it only sees one whose signature is (NSURL, Bool, [String : AnyObject]?) throws -> Void.

The error handling system in Swift 2 takes ObjC methods that return BOOL and have an NSError out parameter and turns them into throwing methods with no return type (that is, they return Void). So, if you're looking at Swift 1.x code that uses such methods, or porting ObjC code, you need to change patterns like the following:

var error: NSError? 
if fileManager.createDirectoryAtURL(directoryURL, withIntermediateDirectories: true, attributes: nil, error: &error) {
    // all good
} else {
    // handle error
}

And use patterns like this instead:

do {
    try fileManager.createDirectoryAtURL(directoryURL, withIntermediateDirectories: true, attributes: nil)
    // if here, all is good
} catch {
    // handle error
}

Upvotes: 3

Related Questions