How can I rewrite in Swift this block? - ios

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
})

Related

Call Swift completion handler in objective c

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)

convert obj-c block to swift 2 closure

I have the following code -
[self.camera capture:^(LLSimpleCamera *camera, UIImage *image, NSDictionary *metadata, NSError *error) {
if(!error) {
}
}];
which, to me, should translate to
self.camera.capture({(camera: LLSimpleCamera, image: UIImage, metadata: [NSObject : AnyObject], error: NSError) -> Void in
if !error {
}
})
but it's throwing all the errors about 'cannot convert value of type etc, between the front and the return Void in section. Can someone tell me, is this a place when you have to use unSafeMutablePointers? If so, how would i know that.
Thanks!
The problem is that these are nullables, so you need exclamation marks. So:
self.camera.capture {
(camera:LLSimpleCamera!, image:UIImage!, metadata:[NSObject : AnyObject]!, error:NSError!) -> Void in
// whatever
}
Or more compactly, just omit the types and let Swift infer them from the Objective-C declaration:
self.camera.capture {
camera, image, metadata, error in
// whatever
}
Also, you can't say !error in Swift, but you can cross that bridge when you come to it.

"Parameter name omitted" Error when migrate objc to swift , dealing with closure

I'm migrating my object-c project to swift, I can use closure for block , but there is error "Parameter name omitted", I have to add the paramater by my self, instead of generated automatically by xcode
here is my swift closure code, the closure has parameters
func GET(urlSting:String!,
parameters:[String: AnyObject]?,
success:((responseObject:AnyObject?) -> Void)?,
failure:((error:NSError?) -> Void)?){
// somethings
}
here is my code generated in project-Swift.h, block has no parameter
- (void)GET:(NSString * __null_unspecified)urlSting
parameters:(NSDictionary<NSString *, id> * __nullable)parameters
success:(void (^ __nullable)(id __nullable))success
failure:(void (^ __nullable)(NSError * __nullable))failure;
here is my code in objc.m, block has no parameter,
[[APIClientS sharedClient] GET:"www.google.com/xxxx"
parameters:nil
success:^(id _Nullable) {
} failure:^(NSError * _Nullable) {
}];
I need to add the parameters by myself,
failure:^(NSError * _Nullable error)
It is really a boring work , how can I generate the parameter name automatically ??
Edit -2015-11-22 09:48:24
Answer Bobj-C's Question:
what do you mean "block has no parameter" ?
As the Following the Pic show, the block not have parameter error, I have to add it by myself

blocks in swift error

I am trying to convert my objectiveC application into swift and i am able to do it most of the things but here is some confusion ...
My ObjectiveC code is
-(void)getResponseFromURL:(NSString *)strURL
withParams:(NSMutableDictionary *)dictParams
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject, bool isSuccess))blockSuccess
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))blockFailure
showLoader:(BOOL)isShowDefaultLoader
showAnimated:(BOOL)isShowLoaderAnimated hideLoader:(BOOL)isHideDefaultLoader
{ //some code here }
My Swift code
func getResponseFromURL(strURL: String, withParams dictParams:Dictionary,
Success:(operation:AFHTTPRequestOperation, responseobject:AnyObject, isSucces:Bool)->void,
Failure:(operation:AFHTTPRequestOperation, error:NSError)->void,
showLoader isShowDefaultLoader:Bool,
showAnimated isShowLoaderAnimated:Bool, hideLoader isHideDefaultLoader:Bool){
// Some code here
}
but it gives me some error
I think i missed some tricks...but i don't know what was that...
So how to get rid of this error?
In Swift, use Void, not void
Dictionary in Swift is Generic, you need specify it as Dictionary<AnyObject, AnyObject> or use NSDictionary directly. You can convert NSDictionary to Swift Dictionary following this answer
Update:
Thanks to Aviel Gross, use [AnyObject: AnyObject] instead of Dictionary<AnyObject, AnyObject>
As code of WenchenHuang shows, () is the same with Void in Swift, both represent empty tuple.
func getResponseFromURL(strURL: String, withParams dictParams:NSDictionary,
Success:(operation: AFHTTPRequestOperation, responseobject:AnyObject, isSucces:Bool)->(),
Failure:(operation: AFHTTPRequestOperation, error:NSError)->(),
showLoader isShowDefaultLoader:Bool,
showAnimated isShowLoaderAnimated:Bool, hideLoader isHideDefaultLoader:Bool){
// Some code here
}
In Swift it's Void. The "V" must be uppercase.

Swift Error - extra argument 'option' in call for SimpleAuth

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

Resources