I want to call this function with a completion handler:
progressView.animate(fromAngle: 0, toAngle: 360, duration: 5, completion:
print("go to next lvl")
)
However I get the error: print produces () not the expected contextual result type ((bool) -> Void)?
I do not know what this error means. I just want to execute a function when the duration is over in the completion handler. I already tried adding (Bool) -> Void in after the completion handler but this does not work. Thank you.
The corresponding closure of the signature (Bool) -> Void) is
{ (result) -> Void in ... }
So you have to write (redundant inferred syntax is omitted)
progressView.animate(fromAngle: 0, toAngle: 360, duration: 5, completion: { result in
print("go to next lvl", result)
})
or with trailing closure syntax
progressView.animate(fromAngle: 0, toAngle: 360, duration: 5) { result in
print("go to next lvl", result)
}
Why don't you use code completion to let Xcode offer you the proper syntax?
Related
I have this function
func performNetworkRequest(timeout: Int, completion: (Result<Response, Error>) -> Void) {
// ....
}
I want to be able to call performNetworkRequest without writing the closure, but to pass an function to do the logic's over there.
something like :
func onNetwotkResponse(result: (Result<Response, Error>) -> Void) {
}
performNetworkRequest(timeout: 60, completion: onNetwotkResponse)
How can I achieve this?
Thanks
The type of closure is:
(Result<Response, Error>) -> Void
which means
A function that accepts a Result<Response, Error> and returns Void.
This means that your onNetwotkResponse function should accept Result<Response, Error>, rather than (Result<Response, Error>) -> Void:
func onNetwotkResponse(result: Result<Response, Error>) {
}
I am trying to use Moya Networking in my project. I am using this example. The example is making moya request to connect to server in view controller on Line 56 which is below and using callback methods in Line 72 and Line 78
func uploadGiphy() {
provider.request(MultiTarget(Giphy.upload(gif: Giphy.animatedBirdData)),
callbackQueue: DispatchQueue.main,
progress: progressClosure,
completion: progressCompletionClosure)
}
I want to write this function in NetworkHelper.swift instead of my view controller but, use its two callback methods (Line 72 and Line 78) in my view controller.
So I wrote the function in NetworkHelper:
static func getUsers(amount:Int=2,
gender:Gender = .Male,
success successCallback: #escaping ([UserModelMain]) -> Void,
error errorCallback: #escaping (Swift.Error) -> Void,
failure failureCallback: #escaping (Moya.MoyaError) -> Void,
progress progressClosure: #escaping (Moya.ProgressResponse) -> Void,
progressCompletion progressCompletionClosure: #escaping (Moya.Completion) -> Void)
{
provider.request(.getUsers(amount: amount, gender: gender),
callbackQueue: DispatchQueue.main,
progress: progressClosure,
completion: progressCompletionClosure)
}
Its showing error:
Cannot convert value of type '((Result) -> Void)
-> Void' to expected argument type 'Completion' (aka '(Result) -> ()')
I think I am writing my function getUsers wrong. I messed it up. I am weak at closures.
Kindly help.
Source Code of request function from Moya networking library:
/// Designated request-making method.
Returns a `Cancellable` token to cancel the request later.
#discardableResult
open func request(_ target: Target,
callbackQueue: DispatchQueue? = .none,
progress: ProgressBlock? = .none,
completion: #escaping Completion) -> Cancellable {
let callbackQueue = callbackQueue ?? self.callbackQueue
return requestNormal(target, callbackQueue: callbackQueue, progress: progress, completion: completion)
}
Moya.Completion is already a completion block. You just need to pass Moya.Completion as an argument, instead of (Moya.Completion) -> Void.
progressCompletion progressCompletionClosure: #escaping Moya.Completion)
Your current code, like the error suggest, is sending ((Result) -> Void) -> Void
UIView.animateWithDuration(0.2, animations: { () -> Void in
self.layoutIfNeeded()
}) { (finished) -> Void in
.......
.......
}
this code throws this error:
Cannot convert value of type '(_) throws -> Void' to expected argument type '((Bool) -> Void)?'
It seem that you are not closing correctly the parentheses and missing the completion argument.
The most easy way to detect this kind of errors is try to rewrite the method.
Try this:
UIView.animateWithDuration(0.2, animations: { () -> Void in
self.layoutIfNeeded()
}, completion: { (finished) -> Void in
///
})
Write like below code, this will work bcz its working at my side,
UIView.animateWithDuration(0.2, animations: { () -> Void in
//your code here
self.layoutIfNeeded()
}) { (flag : Bool) -> Void in
///
}
This is the code that generates the same xcode, try this.
UIView.animateWithDuration(0.2, animations: {
// Code for animation
}) { (finished: Bool) in
// Code for completion
}
I searched everywhere on the internet but couldn't really deal with the answers I found. So if someone could help me here, that'd be appreciated.
I wrote a function that looks like this:
func setImage(imageName: String, completion: ((String) -> Void)?) {
UIView.transitionWithView(self.myImageView, duration: 0.3, options: .CurveEaseOut, animations: {
self.lockImageView.image = UIImage(named: "\(imageName).png")
}, completion: { finished in
//execute the completionBlock that was passed
})
}
I call it like this:
setImage("lockCheck", completion: { finished in
print("done")
})
Now, how do I execute whatever was passed as completion?
In the function, in the transition's completion block, I tried something like
for x in completion {self.x}
but that didn't work.
Thanks in advance :)
You could for example execute the completion handler right away in the completionHandler of the animation block like so:
func setImage(imageName: String, completion: ((Bool) -> Void)?) {
UIView.transitionWithView(self.myImageView, duration: 0.3, options: .CurveEaseOut, animations: { () -> Void in
self.lockImageView.image = UIImage(named: "\(imageName).png")
}, completion: completion)
}
You can also run an completion handler with extra parameters like the following (I hope it is clear like this):
func setImage(imageName: String, completion: ((Bool, String) -> Void)?) {
UIView.transitionWithView(self.lockImageView, duration: 0.3, options: .CurveEaseOut, animations: { () -> Void in
self.lockImageView.image = UIImage(named: "\(imageName).png")
}) { (finished) -> Void in
// Do some things for example print
print("Hi, this is the animation completion handler")
// Notice the ? because the completion handler is an optional
completion?(finished, "some string")
}
}
I'm having a hard time understanding a problem I'm having.
To simplify, I'll use UIView method.
Basically, if I write the method
UIView.animateWithDuration(1, animations: {() in
}, completion:{(Bool) in
println("test")
})
it works fine.
Now, if I do the same method, but creating a string like so:
UIView.animateWithDuration(1, animations: {() in
}, completion:{(Bool) in
String(23)
})
It stops working. Compiler error: Missing argument for parameter 'delay' in call
Now, here's the strange part. If I do the exact same code as the one that fails, but just add a print command like so:
UIView.animateWithDuration(1, animations: {() in
}, completion:{(Bool) in
String(23)
println("test")
})
it starts to work again.
My problem is basically the same thing. My code:
downloadImage(filePath, url: url) { () -> Void in
self.delegate?.imageDownloader(self, posterPath: posterPath)
}
Doesn't work. But if I change to.
downloadImage(filePath, url: url) { () -> Void in
self.delegate?.imageDownloader(self, posterPath: posterPath)
println("test")
}
or even:
downloadImage(filePath, url: url) { () -> Void in
self.delegate?.imageDownloader(self, posterPath: posterPath)
self.delegate?.imageDownloader(self, posterPath: posterPath)
}
It works fine.
I can't understand why this is happening. I'm close to accept that it's a compiler bug.
Closures in Swift have implicit returns when they are only made up of a single expression. This allow for succinct code such as this:
reversed = sorted(names, { s1, s2 in s1 > s2 } )
In your case, when you create your string here:
UIView.animateWithDuration(1, animations: {() in }, completion:{(Bool) in
String(23)
})
you end up returning that string and that makes the signature of your closure:
(Bool) -> String
That no longer matches what's required by animateWithDuration's signature (which translates to Swift's cryptic Missing argument for parameter 'delay' in call error because it can't find an appropriate signature to match).
An easy fix is to add an empty return statement at the end of your closure:
UIView.animateWithDuration(1, animations: {() in}, completion:{(Bool) in
String(23)
return
})
Which makes your signature what it should be:
(Bool) -> ()
Your last example:
downloadImage(filePath, url: url) { () -> Void in
self.delegate?.imageDownloader(self, posterPath: posterPath)
self.delegate?.imageDownloader(self, posterPath: posterPath)
}
works because there are two expressions there, not just one; implicit returns only happen when the closure contains a single expression. So, that closure isn't returning anything and that matches its signature.