pablo1b
pablo1b

Reputation: 13

Objective C to Swift completion syntax with NSError

I'm trying to rewrite the following to Swift:

[client getProductsPage:0 completion:^(NSArray *products, NSUInteger page, BOOL reachedEnd, NSError *error) {
    if (error == nil) {
        self.products = products;
    } else {
        // Handle errors here
    }
}];

One of the several things I tried was:

client.getProductsPage(0, completion:{(products:Array, page:UInt, reachedEnd:Bool, error:NSError) -> Void in
        if(error == nil) {
            self.products = products
        } else {
            println("error")
        }
    })

I understand that Swift takes away NSError parameters, but if I try removing the error parameter I get a compiler error saying I have a wrong number of parameters. Otherwise, I get "cannot invoke getProductsPage an argument list of type (Int, completion:(Array, UInt, Bool, NSError)->Void)". I tried several other things but none worked. Any thoughts? Am I doing something else wrong?

(If relevant, the framework for getProductsPage is https://docs.shopify.com/mobile-buy-sdk/ios/api/Classes/BUYClient#//api/name/getProductsPage:completion: )

Upvotes: 1

Views: 644

Answers (1)

Rob
Rob

Reputation: 437382

The issue associated with "Swift takes away NSError parameters" is not relevant here. First, that's a Swift 2 feature only. Second, that applies to the NSError ** parameters of a method, but not to the NSError * parameters of a block/closure.

In this case, the issue is probably the nullability of the parameters to that block/closure. For example, the NSError parameter certainly should be an optional (because if there is no error, it would be nil). If they didn't explicitly audit the class for nullability, I suspect that both the products array and the error reference would be implicitly unwrapped optionals (e.g. [AnyObject]! and NSError!, respectively):

client.getProductsPage(1, completion: { (products: [AnyObject]!, page: UInt, reachedEnd: Bool, error: NSError!) -> Void in
    if error == nil {
        self.products = products
    } else {
        // Handle errors here
    }
})

If you let Xcode do "code completion" for you, it will show you precisely what those were supposed to be. It's hard to identify what the Swift interface is based solely upon the documentation link you've shared with us. So let Xcode show you what those parameters should be.

By the way, you can often simplify the issue by omitting the types altogether. The Xcode editor/compiler will infer the appropriate types for you:

client.getProductsPage(0) { products, page, reachedEnd, error in
    if error == nil {
        self.products = products   // you may have to do a cast here
    } else {
        // Handle errors here
    }
}

Note, if you were using Swift 2, you might use guard, instead:

client.getProductsPage(0) { products, page, reachedEnd, error in
    guard error == nil else {
        // Handle errors here
        return
    }

    self.products = products   // you may have to do a cast here
}

Upvotes: 1

Related Questions