Objective-C completion block in Swift - ios

I would like to call a completion block in Swift as I have always done in Objective-C. I took a look at closures, but for some reason, I cannot get it to work...
Obj-C:
- (void)someMethodWithParam1:(NSString *)param completion:(void(^)(NSArray* arr, NSURLResponse *resp))callback
{
callback(arr, resp);
}
Swift:
func someMethodWithParam1(param: NSString, completion:((NSArray?, NSURLResponse?)->())) ->(){
^
|
/* Error: Insert ',' here */
completion(arr, resp)
}
EDIT
Okay, it was not a syntactical error, but an error from my side. The method header I used here is different from the one in my code. So this code that I originally posted should work fine.

Typealias's are your friend here, just to make the code more readable
typealias onComplete = (NSArray?, NSURLResponse?) -> ()
func someMethodWithParam1(param: NSString, completion:onComplete) -> ()
{
completion(arr, resp)
}

Related

Calling Wrapper Function From Javascript is Crashing App - React-Native

Hello I am trying to call a function in javascript that I am exporting via Objective C. When I call my function in javascript my app is crashing.
RCT_EXPORT_METHOD(getModelAsync:()
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSError *error;
NSString *contents = [[UIDevice currentDevice] model];
if (contents) {
resolve(contents);
} else {
reject(#"Test", #"Something is broken",error);
}
}
Its failing on this on the if statement with this Error: Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
if (!RCTIsIdentifierHead(**input)) {
return NO;
All help is welcome, thanks!
I came across this issue today and managed to solved it. It looks like the function argument types aren't matching up. This error seems to be triggered, when the function types aren't compatible. Something like the following code snippet, would trigger this error, because a dictionary is not compatible with type string and thus the function argument cannot be correctly cast.
Module.m
RCT_EXTERN_METHOD(myFunction: (NSDictionary)options)
Module.swift
#objc
func myFunction(_ options: String) -> Void {
...
}
To fix it, make sure you are doing something like this:
FixedModule.m
RCT_EXTERN_METHOD(myFunction: (NSDictionary)options)
FixedModule.swift
#objc
func myFunction(_ options: NSDictionary) -> Void {
...
}
I hope this helps!

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)

Calling Objective-c function in swift

Im trying to implement CometChat in my swift application. I managed to import the Objective-c framework successfully via a bridging header. But now I'm stuck trying to call Objective-C methods from swift.
This is the method from the interface i want to call:
- (void)loginWithURL:(NSString *)siteURL
username:(NSString *)username
password:(NSString *)password
success:(void(^)(NSDictionary *response))success
failure:(void(^)(NSError *error))failure;
And this is how the method is called from Objective-C:
[cometChat loginWithURL:#"localhost/cometchat/" username:usernameTextField.text password:passwordTextField.text success:^(NSDictionary *response) {
NSLog(#"SDK log : Username/Password Login Success %#",response);
[self handleLogin];
} failure:^(NSError *error) {
NSLog(#"SDK log : Username/Password Login Error%#",error);
[self handleLoginError:#[#0,error]];
}];
So far i have this:
cometChat.loginWithURL("localhost/cometchat/", username: EmailField.text, password: PasswordField.text){
(success: [NSDictionary], failure:NSError) in {
println("did i make it here?")
}
}
The problem is, it says that there is missing argument "success", but its a mystery to me how it can be an argument, when it clearly returns the response. I want to know how to put together this method call. I also used the objectivec2swift converter, but it wasn't any help. Also, i have no clue what the # means before the #[#0,error]
I know its a beginners question, but i already wasted a whole day on this, since i couldn't find any tutorials on how to call such "complex" Obj-C methods from swift.
Try this :-
cometChat.loginWithURL("localhost/cometchat/", username: "abc", password: "123", success: { (response) -> Void in
print("SDK log : Username/Password Login Success \(response)")
}) { ( error) -> Void in
print("SDK log : Username/Password Login Error \(error)")
}
When you look at the Objective-C signature, you see that the method takes two closures: success is a void function that takes a dictionary, and failure is a void function that takes an error.
In your Swift code you have only one closure: a void function that takes a dictionary and an error.
You either need to change the Objective-C method to take just one closure, or change the Swift code to provide two closures.
When you call a function, and the last parameter is a block / closure, then you can write the last parameter after the function call in { }. That applies to the last block only.
Anyway, you are trying to pass a closure with two parameters success and failure. You need to pass two closures, one as the success parameter of your function, with a parameter response, and one either as the failure parameter of your function, or following the function, with a parameter error.

Converting Obj C to Swift Error:type of expression is ambiguous without more context

I've been using an objC framework in my swift project so I'm converting an objC method to swift. The objC method is as follows:
[[MySingleton sharedInstance] provisionUserWithPIN:pin
organizationID:kOrgID
accessToken:kOrgToken
completion:^(NSString *UID, User *user) {
}];
My swift conversion is:
MySingleton.sharedInstance().provisionUserWithPIN(pin, organizationID: kOrgID, accessToken: kOrgToken) {(UID: String, user: User) in
}
I'm getting an Error:type of expression is ambiguous without more context pointed after the ( in provisionUserWithPIN.
I don't know what I'm doing wrong. Been stuck with this for hours.
Declaration:
- (void)provisionUserWithPIN:(NSString *)PIN organizationID:(NSString *)organizationID accessToken:(NSString *)accessToken completion:(void (^)(NSString *UID, User *user))completion;
You should note that a parameter declared like this in Objective-C
(NSString *)something
does not becomes this in Swift
something:String
but it actually is translated into this:
something:String!
So you can invoke your Objective-C method in Swift writing
MySingleton.sharedInstance().provisionUserWithPIN(
"pin",
organizationID: "orgID",
accessToken: "accessTken") { (UID: String!, user: User!) -> () in
}
Hope this helps.

Code formatting in Swift to use the UIAccessibilityRequestGuidedAccessSession function

I'm new to Swift code formatting and I'm trying to figure out how to use the UIAccessibilityRequestGuidedAccess function. Here's how the function is declared in Swift:
func UIAccessibilityRequestGuidedAccessSession(_ enable: Bool,
_ completionHandler: ((Bool) -> Void)!)
In Objective-C I would have used it as follows:
UIAccessibilityRequestGuidedAccessSession(YES, ^(BOOL didSucceed) {
if (didSucceed ) {
...
} else {
...
}
Any help with the syntax is appreciated.
You do it like this:
UIAccessibilityRequestGuidedAccessSession(true){
success in
println("Request guided access success \(success)")
}
YES is not valid in swift (use true/false), and if the last parameter of a function is a closure, you can use trailing closure syntax as shown above. success is the argument passed into the completion block.

Resources