I have a function that looks like this, and I have tried to add a completionHandler in the code below:
func getValueFromAPI(completionHandler: (_ result: Bool) -> Void){
apii.getVehicle(id!).done {
(vehicle: Vehicle) -> Void in
print("ggg.state: \(vehicle.state!)")
print("ggg.state: \(vehicle.displayName!)")
apii.getAllData(vehicle).done { (extendedVehicle: VehicleExtended) in
let entryBattery = (extendedVehicle.chargeState?.batteryLevel)!
let entryCarState = (extendedVehicle.state)!
print("entryBattery: \(entryBattery)")
print("entryCarState: \(entryCarState)")
completionHandler(true)
}.catch { (error) in
print("ERROOOOR: \(error)")
}
}.catch { error in
print("errorr: \(error)")
}
}
I have already tried to add a complete handler, but I get the following error on these lines:
Line: apii.getVehicle(id!).done {
Error: Escaping closure captures non-escaping parameter 'completionHandler'
Line: apii.getAllData(vehicle).done { (extendedVehicle: VehicleExtended) in
Error: Escaping closure captures non-escaping parameter 'completionHandler'
What am I doing wrong here, and how can I fix this?
I am using Swift 5.
You need to declare your completionHandler to be an escaping closure. E.g.:
func getValueFromAPI(completionHandler: #escaping (Bool) -> Void) {
...
}
Note the #escaping qualifier.
I'm using Alamofire, with ObjectMapper, things were so smooth before upgrading to Swift 2.0, now,
For the following signature:
public func responseArray<T: Mappable>(completionHandler: ([T]?, ErrorType?) -> Void) -> Self
I'm calling
Alamofire.request(.GET, URL, parameters: nil)
.responseArray { (response: [MyObject]?, error: NSError?) in
}
and getting the following error:
Cannot invoke 'responseArray' with an argument list of type
(([MyObject]?, NSError?) -> ())
Any help will be super appreciated.
try this.
Alamofire.request(.GET, URL, parameters: nil)
.responseArray { (response: [MyObject]?, error) in
//your process
}
i'm trying to write a method to return a json response from an API as a string. This is my code:
func authenticateUser(completionHandler: (responseObject: String?, error: NSError?) -> ()) {
makeCall(completionHandler: completionHandler)
}
func makeCall(completionHandler: (responseObject: String?, error: NSError?) -> ()) {
Alamofire.request(.GET, loginUrlString)
.authenticate(user: "x", password: "y")
.responseString { request, response, responseObject, error in
completionHandler(responseObject: responseObject as? String, error: error)
}
}
I can't compile it, the makeCall call in authenticateUser method says "Extraneous argument label 'completionHandler' in call.
I can't see whats wrong in my code?
Try just calling makeCall(completionHandler).
From the error message, I would guess that that is what it is complaining about. Swift function label use often seems inconsistent and confusing.
In one of my app I have used block for webservice calling and getting response. Now I want to write this app in swift, but I am getting trouble to use blocks/Closure in Swift.
Here is my objective C code which I want to migrate in swift:
calling a class method of Communicator
[[Communicator sharedInstance]callWebService:WS_LOGIN withMethod:POST_METHOD andParams:params showLoader:YES completionBlockSuccess:^(id obj) {
//Do play with data
}completionBlockFailiure:^(id obj) {
//Show alert with error
}];
in communicator class
-(void)callWebService:(NSString *)serviceName withMethod:(NSString *)methodName andParams:(NSDictionary *)params showLoader:(BOOL)showLoader completionBlockSuccess:(void (^)(id))aBlock completionBlockFailiure:(void (^)(id))aFailBlock
{
if (showLoader) {
// show loader
}
[self performRequestWithServiceName:serviceName method:methodName andParams:params successblock:aBlock failureblock:aFailBlock];
}
- (void)performRequestWithServiceName:(NSString *)serviceName method:(NSString*)methodName andParams:(NSDictionary*)params
successblock:(void (^)(id obj))successBlock
failureblock:(void (^)(id obj))failBlock {
if(callSuceess){
successBlock(#"Success");
}else{
successBlock(nil);
}
}
For Swift. Use AnyObject for id objc type.
func callWebservice (serviceName: String, withMethod method: String, andParams params: NSDictionary, showLoader loader: Bool, completionBlockSuccess aBlock: ((AnyObject) -> Void), andFailureBlock failBlock: ((AnyObject) -> Void)) {
if loader {
// Show loader
}
performRequestWithServiceName(serviceName, method: method, andParams: params, success: aBlock, failure: failBlock)
}
func performRequestWithServiceName(serviceName: String, method methodName: String, andParams params: NSDictionary, success successBlock: ((AnyObject) -> Void), failure failureBlock: ((AnyObject) -> Void)) {
if callSuceess {
successBlock("Success")
}else {
successBlock(nil)
}
}
UPDATE: An example when you want call web service. See code below
callWebservice("your-service-name", withMethod: "your-method", andParams: ["your-dic-key": "your dict value"], showLoader: true/*or false*/, completionBlockSuccess: { (success) -> Void in
// your successful handle
}) { (failure) -> Void in
// your failure handle
}
Your code might look like this:
func callWebService(serviceName: String, method: String, params: [String : AnyObject], showLoader: Bool, success: (responseObject: AnyObject) -> Void, failure: (responseObject: AnyObject) -> Void) {
if showLoader {
// show loader
}
performRequest(serviceName, method: method, params: params, success: success, failure: failure)
}
func performRequest(serviceName: String, method: String, params: [String : AnyObject], success: (responseObject: AnyObject) -> Void, failure: (responseObject: AnyObject) -> Void) {
}
I replaced NSDictionary with [String : AnyObject]. If you can replace any of the uses of AnyObject with more specific types, your code will be cleaner and more stable.
For Swift Closures we have to use ( ) -> ( )
For example:
func yourFunction(success: (response: AnyObject!) -> Void, failure: (error: NSError?) -> Void) {
}
You can call it as:
yourFunction({(response) -> Void in
// Success
}) { (error) -> Void in
// Handle Errors
}
Hope it will help you to create Closures with your requirements.
In the communicator class the method that cals the webservice would be defined something like this depending on the type of object you want to return
func performRequest(serviceName: NSString, methodName: NSString,paramaters:NSDictionary, successblock: (String)->(), failureBlock: () -> ()) {
if(callSuccess) {
successblock("Success")
} else {
failureBlock()
}
We define the success and failure blocks types as by their function signatures in the case above success is defined as a method that takes a string as an input parameter and returns nothing so we can then call successBlock passing in a string. The failure block is defined above as a block that takes no parameters and returns nothing.
To call this method
func callWebService(serviceName: NSString, method: NSString and parameters: NSDictionary, showLoader: Bool, completionBlockSuccess:(String) -> (), completionBlockFailiure:() -> ()) {
if (showLoader) {
// show loader
}
performRequest(serviceName: serviceName, methodName: method, parameters, successBlock:completionBlockSuccess, failureBlock: completionBlockFailiure)
}
Finally to call this
Communicator.sharedInstance().callWebService(serviceName: WS_LOGIN , method: POST_METHOD and parameters: params, showLoader: true, completionBlockSuccess:{ returnedString in
//Do play with data
}, completionBlockFailiure:{
//Show alert with error
})
For the completion block we define a variable returnedString to allow us to manipulate that input parameter (in the above example it would be the string "Success"). I assume your data is not just returning a string though so you will probably need to play around with they type depending on what your service returns.
Also here I tried to match your method signatures by using NSString and NSDictionary though depending on your needs the Swift equivalents String and [String: AnyObject] could be more appropriate.
func processingWithAnyObject(input: String, completion: #escaping (_ result: AnyObject) -> Void) {
...
completion(response.result.value! as AnyObject)
}
processingWithAnyObject("inputString") {
(result: AnyObject) in
print("back to caller: \(result)")
}
So I have the following function defined:
public typealias RESTClosure = (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void
public func queryAllFlightsWithClosure(completionHandler : RESTClosure) {
// code ....
}
I'm able to call this function as:
func myResponseHandler(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void {
// code ...
}
rest?.queryAllFlightsWithClosure(myResponseHandler)
From my understanding of Swift, however, if the final argument of a function is a closure it can be converted into a trailing closure ... but I've run into some syntax confusion:
Attempt #1
rest?.queryAllFlightsWithClosure() {
println("Called with Closure")
}
Error:
Tuples types '(response: NSURLResponse!, data NSData!, error: NSError!)' and '()' have different number of elements (3 vs. 0)
Attempt #2
rest?.queryAllFlightsWithClosure() (RESTClosure.self) { // Xcode told me to add a .self
//...code
}
Error: Missing argument for parameter #1 in call
I know I'm close ... but anybody can help me here?
Your parameters go inside the closure, and since there's just the one argument, you can even leave out the parentheses:
rest?.queryAllFlightsWithClosure {
(response: NSURLResponse!, data: NSData!, error: NSError!) in
// code ...
}
If you're going to be accessing self or any properties inside the closure, you'll want to include self in a capture list, like this:
rest?.queryAllFlightsWithClosure {
[weak self] (response: NSURLResponse!, data: NSData!, error: NSError!) in
// code ...
// note that self is optional inside this closure b/c of [weak self]
self?.doSomething()
}
Well this seems to compile
rest?.queryAllFlightsWithClosure() { RESTClosure in
// code ...
}