Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 3 change to NSErrorPointer?

I have code I've been using for SwiftyJSON and I'm trying to update to Swift 3 using XCode 8.0 Beta 3. I'm running into an issue where the compiler doesn't like the argument 'error: &err' as it did before. I've been searching for how to correctly pass an NSErrorPointer but everything I've found says to re-write, leave out the error and throw an error back. Since this isn't my code I'd rather leave it as it is. So what's the correct new way to use an NSErrorPointer?

var err : NSError?
// code to get jsonData from file
let json = JSON(data: jsonData, options: JSONSerialization.ReadingOptions.allowFragments, error: &err)
if err != nil {
   // do something with the error
} else {
    return json
}

The code above results in compiler error: '&' can only appear immediately in a call argument list. I've tried creating an NSErrorPointer so I can use that instead but I can't find anything on how to initialize one (the type alias declaration is not enough). I've already been to Using Swift with Cocoa and Obj-C, it does not contain the word NSErrorPointer, instead goes over the new way of throwing errors. I've also looked over a couple dozen posts all using the &err so apparently this is new to Swift 3.

Is there anyone out there that's solved this one? What's the answer to using NSErrorPointer?

Thanks, Mike

like image 582
Mike Avatar asked Mar 12 '23 15:03

Mike


1 Answers

That seems to be an error in the Swift 3 branch of SwiftyJSON at

  • https://github.com/SwiftyJSON/SwiftyJSON/blob/swift3/Source/SwiftyJSON.swift

which defines the init method as

public init(data:Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer? = nil) {
    do {
        let object: AnyObject = try JSONSerialization.jsonObject(with: data, options: opt)
        self.init(object)
    } catch let aError as NSError {
        if error != nil {
            error??.pointee = aError
        }
        self.init(NSNull())
    }
}

In the Swift 3 that comes with Xcode 8 beta 3, NSErrorPointer is an optional:

public typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>?

as a consequence of

  • SE-0055: Make unsafe pointer nullability explicit using Optional

Therefore the error parameter should have the type NSErrorPointer, not NSErrorPointer? (and consequently error??.pointee changed to error?.pointee). With these changes the init method becomes

public init(data:Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer = nil) {
    do {
        let object: AnyObject = try JSONSerialization.jsonObject(with: data, options: opt)
        self.init(object)
    } catch let aError as NSError {
        if error != nil {
            error?.pointee = aError
        }
        self.init(NSNull())
    }
}

and then your code compiles and runs as expected.

like image 164
Martin R Avatar answered Mar 19 '23 08:03

Martin R