2

I'm using a third party library written in objective C with the following method:

- (void)manageServerResponse:(NSURLResponse*)response NSData:(NSData*)data andNSError:(NSError*)error onComplete:(void (^)(NSInteger kindOfError, NSDictionary*jsonResponse))onComplete;

when I port it to swift I do the following:

typealias ResponseCompletedBlock = (NSInteger, NSDictionary?) -> Void
...
let completedResponseMethod : ResponseCompletedBlock = {(kindOfError: NSInteger, jsonResponse: NSDictionary?) -> Void in
    self.onComplete(kindOfError, jsonResponse: jsonResponse)}

let responseManager: ResponseManager = ResponseManager.sharedResponseManager() as! ResponseManager
responseManager.manageServerResponse(response, 
    NSData: data, 
    andNSError: error, 
    onComplete: completedResponseMethod)

I'm getting this error:

Cannot invoke 'manageServerResponse' with an argument list of type '(NSURLResponse?, NSData: NSData?, andNSError: NSError?, onComplete: ResponseCompletedBlock)'

and if I replace the last sentence for

responseManager.manageServerResponse(response, 
    NSData: data, 
    andNSError: error, 
    onComplete: nil)

everything works, so I assume that the problem is with the block structure, but I've tried to change everything and the error remains.

Can you help?

3
  • I'm not that experienced with Swift yet, but did you try making NSDictionary implicitly unwrapped in your (NSInteger, NSDictionary?) -> Void closure? Commented May 28, 2015 at 9:18
  • In swift blocks you often need to figure out what needs to be unwrapped or not - explicitly. Adding a ! or ? might solve the issue. Generally ! solves it for me... Commented May 28, 2015 at 9:33
  • I've tried several things, including adding ! and ? to the NSDictionary parameter. No luck Commented May 28, 2015 at 10:07

3 Answers 3

4

NSDictionary * is mapped to Swift as [NSObject : AnyObject]!, therefore the type of the response block should be

typealias ResponseCompletedBlock = (Int, [NSObject : AnyObject]!) -> Void

and consequently

let completedResponseMethod = {(kindOfError: Int, jsonResponse: [NSObject : AnyObject]!) -> Void in
    // ...
}

One method to figure out the correct Swift signature of functions is to use the autocompletion in Xcode: You start typing

 responseManager.manageServerResponse(

and Xcode suggests

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

@F.D.FDev: You are welcome! – I have added some information about how you can solve this kind of problems generally.
Thanks for that, although my Xcode refuses to autocomplete code from ObjC in a Swift file... don't know why (And I've deleted derived data if you ask so)
1

Per Apple docs:

When you bridge from an NSDictionary object to a Swift dictionary, the resulting dictionary is of type [NSObject: AnyObject].

Also, unless the Objective-C code is annotated for nullability, the Swift dictionary is an implicitly-unwrapped optional. Therefore your typealias should look like this:

typealias ResponseCompletedBlock = (NSInteger, [NSObject : AnyObject]!) -> Void

I'd also recommend changing the NSInteger to Int.

Comments

0

Is the typealias and completedResponseMethod absolutely necessary for your program to function? If not, this would probably solve your problem:

responseManager.manageServerResponse(response, NSData: data, andNSError: error, onComplete: { 
    $0, $1 in
    self.onComplete($0, jsonResponse: $1)
}

As your error suggests, the error was due to a type mismatch. If you use the default local parameters, you'll be able to work around that particular problem.

1 Comment

Not at all, I added the type alias just to try to split all the problem into parts. In fact it was just one line of code at the beginning...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.