Frustrated Swift Callback - swift

Recently I'm on a project that requires a lot of APIs Async interacting with the Server, I've tried delegating, but writing a lot of delegator is not very elegant. I've been following all the 'Swift Callback' threads on SO before, Still stucking.
//First try
func post(url: String, data: String, callback:(result: String) ->Void){
callback(result: "Completed")
}
func request(url: String, data: String){
post(url, data, { (result) in
println(result)
})
}
request("Hello", "World")
//prints nothing
//second try following threads
func test(txt: String, resolve: (name: String) -> Void) {
resolve(name: "Dodo")
}
test("hello", {(name: String) in
println(name)
})
What did I missed, Any help will be grateful

Your code looks fine. I run Xcode 7 and needed to make some modifications, but the code worked for me. If you are trying this in Playground, make sure it is actually executing. It often happens to me that I am expecting print statement to show something, but Playground is stuck and does not output anything due to an error.
Here is the code that worked for me (modified for Swift 2):
func post(url: String, data: String, callback:(result: String) ->Void){
callback(result: "Completed")
}
func request(url: String, data: String){
post(url, data: data, callback: { (result) in
print(result)
})
}
request("Hello", data: "World")
func test(txt: String, resolve: (name: String) -> Void) {
resolve(name: "Dodo")
}
test("hello", resolve: {(name: String) in
print(name)
})

If you'd like to run your code in a playground, you need to tell Xcode to not exit (so that it can make the request in background and execute async callbacks).
Appending this to your playground should make it work:
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely()

Related

Given the same callback implementation, abstract function calls

Assuming I have 2 functions foo and bar defined below.
func foo(completion: #escaping (Response) -> Void)
func bar(a: Int, completion: #escaping (Response) -> Void)
Then I have 2 different functions that use foo and bar
func doSomethingWithFoo() {
foo { response in
handleResponse(response)
}
}
func doSomethingWithBar() {
bar(a: 42) { response in
handleResponse(response)
}
}
doSomethingWithFoo and doSomethingWithBar are very similar. They do the exact same thing with response they get in the completion callback.
My question is: is there a way in Swift to generalize doSomethingWithFoo and doSomethingWithBar? Maybe something in line with the following.
func doSomething(<???>) {
<???> { response in
handleResponse(response)
}
}
<???> is a placeholder for passing either foo or bar or even any other function that also accepts a callback of type (Response) -> Void.
I'll appreciate any help/insights. Thanks.
You can declare a function like this :
func doSomething(fooBar: (_ completion: #escaping (String) -> Void) -> Void) -> Void {
fooBar(handleResponse)
}
Which you would call like this:
doSomething(fooBar: { bar(a: 42, completion: $0) })
doSomething(fooBar: foo)

Why does calling a function and not passing in a value with one parameter work but for more doesn't?

why does the first function call not yield any error while the second function call yields an error? I'm not invoking a function but simply calling it. The difference between the two functions are the number of parameters.
func hello(firstName: String) {
print("Hello \(firstName)")
}
hello(firstName:)
func hello(firstName: String, lastName: String) {
print("Hello \(firstName) \(lastName)")
}
hello(firstName:, lastName:)
The Swift Book does not contain a easy-to-read description, but your first code is a valid expression in Swift, which returns a closure of type (String)->Void:
func hello(firstName: String) {
print("Hello \(firstName)")
}
var closure: (String)->Void = hello(firstName:)
closure("Taro") //->Hello Taro
In your second code, hello(firstName:, lastName:) is not a valid expression in Swift, but hello(firstName: lastName:) is valid:
func hello(firstName: String, lastName: String) {
print("Hello \(firstName) \(lastName)")
}
//hello(firstName:, lastName:) //<-invalid
var closure2: (String, String)->Void = hello(firstName: lastName:)
closure2("Taro", "Yamada") //->Hello Taro Yamada
Maybe you have ever seen this sort of notations inside #selector(), but such notations can be used also outside #selector() as shown above.

Swift: Issue with closure arguments

Here is a function:
func foo(completion: (jsonData: String) -> ()) {
}
In Swift 3, you can't have argument labels. Therefore, this is the code:
func foo(completion: (String) -> ()) {
}
The issue with this, is that when I call the function it looks like this:
foo(completion: { _ in
})
So, if I want to see the value of jsonData, I can't because it's an underscore. How would I solve this issue?
It's working:
func foo(completion: (String) -> ()) {
completion("Hi")
}
foo { jsonData in
print(jsonData) // Output: Hi
}

XCTAssert with a generic method in Swift

I have two almost exactly identical assertions for a generic method on Swift's Dictionary structure, but one succeeds and the other fails. I assume that it's how XCTAssert works, but can't understand why. Does anyone have an idea why?
If the method is not generic and, for example, T is String, then both tests succeed.
extension Dictionary {
func safeElement<T>(key: Key, fallback: T) -> T {
if let value = self[key] as? T {
return value
}
return fallback
}
}
class DictionaryTests: XCTestCase {
let dict = ["foo": "bar"]
func testSafeElement() {
// This succeeds
let bar = dict.safeElement("foo", fallback: "")
XCTAssertEqual(bar, "bar")
// This fails
XCTAssertEqual(dict.safeElement("foo", fallback: ""), "bar")
}
}
Update
I was tinkering with it a little bit more, and it turns out that if you pass a type as a parameter, then both cases succeed. But I imagine this type verbosity is not that one would want.
extension Dictionary {
func safeElement<T>(key: Key, fallback: T, type: T.Type) -> T {
if let value = self[key] as? T {
return value
}
return fallback
}
}
class DictionaryTests: XCTestCase {
let dict = ["foo": "bar"]
func testSafeElement() {
// This succeeds
let bar = dict.safeElement("foo", fallback: "", type: String.self)
XCTAssertEqual(bar, "bar")
// This also succeeds
XCTAssertEqual(dict.safeElement("foo", fallback: "", type: String.self), "bar")
}
}
If you add a print statement:
func safeElement<T>(key: Key, fallback: T) -> T {
print("calling for \(T.self)")
You can see the difference in output between the two tests:
calling for String
calling for Optional<String>
This is probably because XCTAssertEqual's argument is declared as #autoclosure expression1: () -> T?, so the compiler tries to pick a version of safeElement that returns an optional, which it can do easily by making T==String?. But then your as? T does the wrong thing, since the dictionary's Value type is a non-optional String.
Sounds like a bug.

Swift - Trailing Closure Syntax

I'm diving into Swift lang by Apple and have some problems using the trailing closure syntax, example:
func test(txt: String, resolve: (name: String) -> Void) {
resolve(name: "Dodo")
}
// Errors here complaining on resolve param
test("hello", (name: String) {
println("callback")
})
How to fix it?
you have the wrong closure syntax
test("hello", {(name: String) in
println("callback")
})
or
test("hello", {
println("callback: \($0)")
})
or
test("hello") {(name: String) in
println("callback")
}
or
test("hello") {
println("callback: \($0)")
}