Hi I have been battling with a swift error as I cannot match the arguments of an objective-c method
SimpleAuth.authorize("instagram",
options: ["scope" : "likes"], completion: {
(responseObject : NSDictionary!, error : NSError!) -> Void in
self.accessToken = responseObject["credentials"]["token"]
......
})
//error Extra argument 'options' in call
Declared as:
+ (void)authorize:(NSString *)provider options:(NSDictionary *)options completion:(SimpleAuthRequestHandler)completion;
Code completion is :
SimpleAuth.authorize(<#provider: String!#>, options: <#[NSObject : AnyObject]!#>, completion: <#SimpleAuthRequestHandler!##(AnyObject!, NSError!) -> Void#>)
I have tried type casting, down casting, declaring as a separate variables, but still cant get it to work.
Any ideas, will be much appreciated
It's your definition of your completion block. SimpleAuthRequestHandler is defined as:
typedef void (^SimpleAuthRequestHandler) (id responseObject, NSError *error);
But your completion block/closure is defined as:
(responseObject : NSDictionary!, error : NSError!) -> Void in
You can't just change the type from id (AnyObject in Swift) to NSDictionary! without explicitly casting it. Your call should look something like this:
SimpleAuth.authorize("instagram", options: ["scope" : "likes"], completion: {
(responseObject : AnyObject!, error : NSError!) -> Void in
/* ... */
})
You can then make responseObject an NSDictionary with a cast:
var response = responseObject as NSDictionary
Related
I am trying to call a swift method, which is implemented like this:-
#objc class DataAPI: NSObject {
func makeGet(place:NSString , completionHandler: (String! , Bool!) -> Void)
{
var str:String = ""
let manager = AFHTTPSessionManager()
manager.GET("https://api.com", parameters: nil, success:
{ (operation, responseObject) -> Void in
str = "JSON: \(responseObject!.description)"
print(str)
completionHandler(str,false) //str as response json, false as error value
},
failure: { (operation,error: NSError!) in
str = "Error: \(error.localizedDescription)"
completionHandler("Error",true)
})
}}
Now when I am trying to call it in my Objective C class, it is throwing an error "No Visible interface for DataAPI declares selector makeGet:completionHandler"
This is how I am calling the method in my Objective C class:-
[[DataAPI new] makeGet:#"" completionHandler:^{
}];
Try to clean and Rebuild to generate the "YourModule-Swift.h" again with all your changes.
Then it should be something like this:
[[DataAPI new] makeGet:#"" withCompletionHandler:^(NSString* string, BOOl b){
// your code here
}];
If you still getting that error, your "YourModule-Swift.h" file hasn't been generated correctly. Check it!
I see that in Swift the completion handler has two arguments: String and Bool whereas in your Objective-C call you pass a block without any arguments. I think it may be the cause of the error.
Try:
[[DataAPI new] makeGet:#"" completionHandler:^(NSString* string, BOOl b){
}];
You shouldn't use !(ImplicitUnwrappedOptional) keyword in closure. That is not allow bridging to ObjC code. just remove ! from closure.
func makeGet(place:NSString , completionHandler: (String! , Bool!) -> Void)
to
func makeGet(place:NSString , completionHandler: (String , Bool) -> Void)
I have made a success & failure block in objC and I am trying to use that function in swift. Getting error, I'm stuck on it please help me.
Objective C :
-(void)registerAppWithSuccessBlock:(void (^)(id responseObject))success andFailureBlock:(void (^)(NSError *error))failure{}
I am calling the same function in swift its showing error.
Swift :
USSecService.sharedInstance().registerAppWithSuccessBlock({(responseObject : AnyObject) -> Void in{code}
}, andFailureBlock: { (error : NSError) -> Void in {code}
})
Getting this Error :
Cannot invoke 'registerAppWithSuccessBlock' with an argument list of type '((AnyObject) -> Void, andFailureBlock: (NSError) -> Void)'
USSecService.sharedInstance().registerAppWithSuccessBlock({ (responseObject) -> Void in
print("Success")
}, andFailureBlock: { (error) -> Void in
print("Failure")
})
You don't need to specify the argument type in those closures. Change your swift code like below:
Without second closure label syntax:
USSecService.sharedInstance().registerAppWithSuccessBlock({ (responseObject) -> Void in
// Your success code
}){ (error) -> Void in
// Your error code
}
or
With second closure label syntax:
USSecService.sharedInstance().registerAppWithSuccessBlock({ (responseObject) -> Void in
// Your success code
}, andFailureBlock: ({ (error) -> Void in
// Your error code
}))
I’m using AFHTTPRequestOperation in swift like this :
let operation : AFHTTPRequestOperation? = manager.GET(requestURL, parameters: nil,
success: { (operation:AFHTTPRequestOperation!, responseObject:AnyObject!) -> Void in
...
...
...
success(downloadedItems: responseObject)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in
failure(responseFromCache: responseFromCache, error: error);
})
and I’m using setCacheResponseBlock for application specific purpose (ETag etc.)
operation!.setCacheResponseBlock { (connection: NSURLConnection, cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse in
print("Returns:200")
responseFromCache = false
return cachedResponse
}
Everything was OK until updating XCode to new version XCode7.1.
Here is my problem, I get this error when I build my application after update :
Cannot convert value of type '(NSURLConnection, NSCachedURLResponse) -> NSCachedURLResponse' to expected argument type '((NSURLConnection!, NSCachedURLResponse!) -> NSCachedURLResponse!)!'
How to fix this?
After checking error message I understand something wrong with my parameters. I check method’s declaration in XCode and I understand method’s declaration just updated :
func setCacheResponseBlock(block: ((NSURLConnection!, NSCachedURLResponse!) -> NSCachedURLResponse!)!)
I updated my method like this :
operation!.setCacheResponseBlock { (connection: NSURLConnection!, cachedResponse: NSCachedURLResponse!) -> NSCachedURLResponse! in
print("Returns:200")
responseFromCache = false
return cachedResponse
}
and another happy ending with build succeeded message in Xcode. Hope this will help someone.
let's say I have in my objective-c this:
typedef void (^DirectionBlock)(NSArray *steps, NSError *error);
-(void)requestWithStartPoint:(CLLocationCoordinate2D)start endPoint:(CLLocationCoordinate2D)end travelMode:(NSString*)travel language:(NSString*)lng result:(DirectionBlock)resultBlock;
to call requestWithStartPoint in objective-c it will look like this:
Direction *direction = [[Direction alloc] init];
[direction requestWithStartPoint:startPoint endPoint:endPoint travelMode:#"driving" language:#"en" result:^(NSArray *steps, NSError *error) {
if (!error) {
NSLog(#"RESULT: %#", [steps[0] description]);
}
}];
I used this converter here t get the swift equivalent and I got this:
var direction: Direction = Direction()
direction.requestWithStartPoint(startPoint, endPoint: endPoint, travelMode: "driving", language: "en", result: {(steps: [AnyObject], error: NSErrorPointer) in if !error {
NSLog("RESULT: %#", steps[0].description())
}
})
But I got this error:
Cannot invoke 'requestWithStartPoint' with an argument list of type '(CLLocationCoordinate2D, endPoint: CLLocationCoordinate2D, travelMode: String, language: String, result: ([AnyObject], NSErrorPointer) -> _)'
I have a feeling it has something to do with NSArray pointer being converted to [AnyObject]. Any ideas how to solve this ?
thanks to #Aderstedt comment, by verifying method signature I found it used [AnyObject]! and NSError! and not [AnyObject] and NSErrorPointer.
I need to rewrite an Objective-C block but I can't
This is the block in question :
[service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, GTLDriveFileList* files, NSError *error) {
}];
In Swift, I tried :
service.executeQuery(query, completionHandler: {(ticket:GTLServiceTicket!,files:GTLDriveFileList!,error:NSError!) -> Void in
})
But the compiler don't agree with that.
I tried :
service.executeQuery(query, completionHandler: {(ticket:GTLServiceTicket?,files:GTLDriveFileList?,error:NSError?) -> () in
})
But same issue.
And when I cmd+click on the class, I find :
// Clients should create a standard query with any of the class methods in
// GTLQueryDrive.h. The query can the be sent with GTLService's execute methods,
//
// - (GTLServiceTicket *)executeQuery:(GTLQuery *)query
// completionHandler:(void (^)(GTLServiceTicket *ticket,
// id object, NSError *error))handler;
Does anyone knows how to made that ?
Thanks
The completion handlers second parameter is an id object (obj c) so in swift it will become AnyObject
swift < 2.3 --
service.executeQuery(query, completionHandler: {(ticket:GTLServiceTicket!, object: AnyObject!, error: NSError!)->Void in
})
swift 3.0 --
since id parameter in objc code has Any type in Swift 3.0 hence --
service.executeQuery(query, completionHandler: {(ticket:GTLServiceTicket?, object: Any?, error: Error?)->Void in
})