How we write own function in swift with completionHandler - swift

in objective c i write a method
-(void)loginApi:(NSMutableDictionary*)dict completion:(void(^)(NSDictionary *json,BOOL sucess))completion {
how we write same method

func loginApi(dict: NSMutableDictionary, completion: (json:NSDictionary,success: Bool) -> Void){
//Do whatever you want to do here
completion(json: dict, success: true) //This is just an example of how you can call
}
Give this a try. I think it should work. If not,let me know.

func loginApi(completion : (json: [Dictionary<String, String>, success: Bool]) -> [Dictionary<String Int>]) {
...
completion(...)
}

Although Previous answers will work I would suggest to alias it instead of typing the declaration every time (it also concern Objective c).
typealias CompletionHandlerType = (error:NSError ,response:AnyObject?) -> Void

Related

Swift - Call completion handler from a second function

thanks for reading this, i hope you can understand my problem. Basically what i would like to do is this:
private func doGet(path:String, body:Dictionary, completion: #escaping (JSON?, Bool) -> Void) {
completion(data, bool)
}
func getData(body){
return doGet("/api/data", body: body)
}
// The function gets called in another class
getData(data){ (data, bool)
// do something with data
}
I know this code doesnt work but thats what i would like to do. I dont want to call doGet from the other class i want to have a function in between. Maybe this is not possible. Please let me know if i didnt make myself clear and thanks in advance. :)
getData also needs to have a completion handler parameter, since it too returns the results asynchronously.
So, you'd have something like this:
getData(body: SomeType, completion: #escaping (Data, Bool) -> Void) {
doGet(path: "/api/data", body: body) { (param1, param2) in
// turns param1 and param2 into parameters to invoke
// the completion handler with
completion(data, true)
}
}

how to pass a callback function in another function in swift?

so i'm doing my first app,
and i want to do a function that will be a uniform funciton to sevral places in the system, and not belong to only one specific class.
Is there a way for me to pass a callback function as a parameter to another function ?
here is just a demonstration of what i mean.
ClassA {
func classAcallbackFunction (displayString: String) {
print (displayString)
}
ClassB().classBFunction(classAcallbackFunction())
}
ClassB {
func classBfunction (myCallbackfunc: func) {
mycallbackfunc("all is working !!!")
}
}
The parameter you have declared is not correct. Replace it with something like this:
func classBFunction(_ completion: (String) -> Void) {
completion("all working")
}
Like shared by regina_fallangi in the comments, callbacks are usually called completion handlers, which is why I replaced the names accordingly.
Extra Credit:
If you only want to optionally pass a function, you could do this:
func classBFunction(_ completion: ((String) -> Void)? = nil) {
completion?("all working")
}
Now you could also just call classBFunction().

Swift 3: Inheritance from non-named type

I have the following SSCIE:
protocol Foo {
associatedtype Bar
associatedtype Baz: (Self.Bar) -> Void
var currentValue: Bar { get }
}
That I want to use like this:
func call<T: Foo>(foo: T, callback: #escaping T.Baz) {
DispatchQueue.main.async {
callback(foo.currentValue)
}
}
But it fails to compile, with the error:
Inheritance from non-named type '(`Self`.Bar)'
This also fails to compile when I use (Bar) -> Void and (Foo.Bar) -> Void.
Sadly, Googling this didn't come up with any useful results.
Does anyone have any idea what this error means, what I'm doing wrong, and how to correct it?
Associated types in Swift 3 can only be "is-a"-constrained. So your Bar is required to be an Any. Which, by the way, is not much of a constraint ;). In other words, you can remove it.
However, (Self.Bar) -> Void is a function type and you can't constrain an associated type like this.
If you want to define a callback type, you can use a typealias:
protocol Foo
{
associatedtype Bar
typealias Callback = (Self.Bar) -> Void
var currentValue: Bar { get }
func f(callback: Callback) -> Void
}
Using #escaping does not currently work in a typealias (see SR-2316 and its various duplicates). This is a bug that was supposed to have a fix soon (as of August 2016). So you will have to spell it out for now:
func call<T: Foo>(foo: T, callback: #escaping (T.Bar) -> Void) {
DispatchQueue.main.async {
callback(foo.currentValue)
}
}
Update: As Hamish suggested, I filed SR-4967. I'll update this post as soon as there is any news about it.
As already mentioned, function types can't be used as associated types.
Try this instead:
func call<T: Foo>(foo: T, callback: #escaping (T.Bar) -> Void) {
...
}
and using this design you can mix-and-match function types (for the callback arg) for each specific helper function (call in your example) you come up with.

Can I define a function header directly with a typealist tuple?

Just for fun.
For example I have different actions on user which I want to separate intentionally in different functions.
request friendship
block friendship
cancel friend request
...
And all this functions (because I want to make them distinct) receive the same parameters
nickname
a completionBlock
so in general I would have a lot of this functions:
class func requestFriend(nickName : String, withCompletitionHandler completitionHandler : (status : Bool) -> Void)
class func acceptFriend(nickName : String, withCompletitionHandler completitionHandler : (status : Bool) -> Void)
...
Now what would be really nice to be able to do, would be something like:
typealias UserActionTupleParameter = (nickName : String, completitionHandler : (status : Bool) -> Void)
Define the function maybe as :
class func acceptFriend => UserActionTupleParameter
{
}
And use as:
acceptFriend(myTupleVariable)
Instead of having the function def:
class func acceptFriend(parametersTuple : UserActionTupleParameter)
that will only result in calling the function as:
class func acceptFriend((myString, myBlock))
Maybe I'm missing something, or I messed with parameters naming which does not let me pass the parameters without the tuple "()", but I cannot make the Xcode 7 Swift 2 accepting my intention.
I specifically intend to enforce using the tuple typealias definition as a func parameter in the func definition.
Because I know I can define the func like:
func test (string : String, block : Block)
and then create the tuple as:
let tuple = (myString, myBlock)
and call the function as:
test(tuple)
Some ideas?
Is this what you are looking for?
typealias UserAction = (nickname: String, completionHandler: Bool -> Void)
func testA(userAction: UserAction) -> Void {
NSLog("testA called for user \(userAction.nickname)")
userAction.completionHandler(true)
NSLog("testA exited")
}
func testB(userAction: UserAction) -> Void {
NSLog("testB called for user \(userAction.nickname)")
userAction.completionHandler(false)
NSLog("testB exited")
}
let myAction = UserAction("Willy") {
status in NSLog("myAction status is \(status)")
}
Here is how it runs in my Playground.

Completion Handlers in Swift

I'm fairly new at swift development and trying to get a handle on closures and completion handlers. I have a function with the following declaration inside a struct called ObjectData
func getData(id1:Int, id2:Int, completion: (dataObject? -> Void))
I am trying to call this function like
ObjectData.getData(1, id2: 2){
(let myObject) in
}
but i get the following error
Cannot invoke 'getData' with an argument list of type '(NSNumber, id2:
NSNumber, (_) -> _)'
Please can someone help
For better readability, change the header to this. Remember that you have to declare types, not variable names:
func getData(id1:Int, id2:Int, completion: (ObjectData?) -> (Void))
Now I personally use this syntax to use closures:
self.getData(1, id2: 1) { (data) -> (Void) in
// Some code executed in closure
}
If you want to study further, you can find full syntax of closures here (notice appropriate name of the website).
Hope it helps!
Far away from my Mac now, so I can't test, but try this:
ObjectData.getData(1, id2: 2, (dataObject) -> {
...code...
});
Also can't check now, but I think this also should work:
ObjectData.getData(1, id2: 2)(dataObject){
...code...
}
try to initialize your class first (ex. var objectData = ObjectData()) , and then call function with objectData.getData... it should work that way ..
In SWIFT 3,It is known as completion closure.
func getData(id1:Int, id2:Int, completion:#escaping(dataObject?) -> (Void)) {
//Do the stuff before calling completion closure
completion(value as? dataObject)
}
ObjectData.getData(id1:1, id2: 2,completion:{(data) -> (Void) in
//Do the completion stuff here
}