convert obj-c block to swift 2 closure - closures

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.

Related

Error after converting objective-c code to swift 3.0.2 Google Drive Rest API

The problem is quite simple.I have a code that works fine in Objective-C, but I need the same code to work in swift.With the code below I am uploading file named"photo.png" to my Google Drive from Documents folder on iPhone.(I deleted the part with setting Documents directory folder to save some space)
Here is the original code:
-(void)uploadPhoto{
metadata.parents = ids;
GTLRUploadParameters *uploadParameters;
uploadParameters = [GTLRUploadParameters uploadParametersWithData:photoData MIMEType:#"image/png"];
uploadParameters.shouldUploadWithSingleRequest = TRUE;
GTLRDriveQuery_FilesCreate *query = [GTLRDriveQuery_FilesCreate queryWithObject:metadata
uploadParameters:uploadParameters];
query.fields = #"id";
[self.service executeQuery:query completionHandler:^(GTLRServiceTicket *ticket,
GTLRDrive_File *file,
NSError *error) {
if (error == nil) {
NSLog(#"File photo ID %#", file.identifier);
} else {
NSLog(#"An error occurred: %#", error);
}
}];
}
Most of it I got form Google developers.IN Objective - Its working fine!
Here is what In got in swift:
func uploadPhotos()
{
var ids : NSArray!
metadata.parents = ident as! [String]?
var uploadParameters = GTLRUploadParameters(data:photoData! as Data,mimeType:"image/png")
uploadParameters.shouldUploadWithSingleRequest = true
var query :GTLRDriveQuery_FilesCreate
query = GTLRDriveQuery_FilesCreate.query(withObject: metadata, uploadParameters: uploadParameters)
query.fields = "id"
let vc:DriveListTableViewController
self.service.executeQuery(query,completionHandler :{(ticket: GTLRServiceTicket!,
file: GTLRDrive_File!,
error: Error!)-> Void in
if error == nil {
print("File photo ID \(file.identifier)")
}
else {
print("An error occurred: \(error)")
}
})
}
The Error I get is in the the line with self.service.exequteQuery
swift:314:59: Cannot convert value of type '(GTLRServiceTicket!, GTLRDrive_File!, Error!) -> Void' to expected argument type 'GTLRServiceCompletionHandler?'
Please help me solve that Error! Have tried different variants!
Refer with this SO thread. You may try changing the unwrapping of the parameters in the closure. Maybe this is required to match what the Objective-C implementation of the function is expecting.
You may also check this additional references:
Swift 2 to Swift 3: Cannot convert value of type '(Data?, NSError?) -> Void' to to expected argument type 'GTMSessionFetcherCompletionHandler?'
As per SE-0112, NSError is now bridged to Swift as the Error protocol. In fact, if you ⌥ + click on the GTMSessionFetcherCompletionHandler type in Swift, you'll see exactly how it's bridged:
typealias GTMSessionFetcherCompletionHandler = (Data?, Error?) -> Void
Swift error Cannot convert value of type '(AFHTTPRequestOperation?, AnyObject?) -> ()
Cannot convert value of type (PFUser!, NSError) void to expected argument type PFUserResultBlock

How do I convert this line of code to swift 2.0?

I am a new programmer. I started learning swift 2.0 without objective c, which I guess was a mistake.
I am trying to integrate quickblox into my swift app, however this line of code is really confusing me. I was wondering if someone could give me a hand
- (void (^)(QBResponse *response, QBUUser *user))successBlock
{
return ^(QBResponse *response, QBUUser *user) {
// Login succeeded
};
}
The function returns a block function, which gets two parameters: the response and the user. Its return type is void.
So in swift, it should basically look like this:
func successBlock() -> (QBResponse, QBUUser) -> Void {
return { (response, user) in
//Login succeeded.
}
}
It could also be converted to a computed property as it does not have side effects and does not rely on any parameters:
var successBlock: (QBResponse, QBUUser) -> Void {
return { (response, user) in
//Login succeeded.
}
}

using objective-c with swift : cannot invoke 'function' with an argument list of type

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.

How can I rewrite in Swift this block?

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

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