Set function as variable in function declaration - ios

I want to have function as variable in function declaration and than call that variable within declared function. How to do it in Swift?
Pseudo code:
let something = 0
func one() {
print("one")
}
// Definition
func two( funcVariable: Void, number: Int) {
print("\(number)")
funcVariable() // here I want to call variable function
}
// Call
two(funcVariable: one(), number: somethhing)
How to do it?
Example code appreciated.

Here is how you do it:
let something = 0
func one() {
print("one")
}
// Definition
func two(funcVariable: () -> Void, number: Int) {
print("\(number)")
funcVariable()
}
// Call
two(funcVariable: one, number: something)

Related

swift question about "#escaping" inside class

I am a newbie and maybe this is a silly question but I need some help.
I have this code like below but I wonder that should I remove "#escaping" inside the checkSignedIn function.
Class A{
public func checkSignedIn(complete: #escaping (Bool) -> Void) {
_ = Amplify.Auth.fetchAuthSession { (result) in
do {
let session = try result.get()
complete(session.isSignedIn)
} catch {
print("Fetch auth session failed with error - \(error)")
complete(false)
}
}
}
I imagine that using "#escaping" will escape the return value from closure if I assign complete() to a variable like below.
Class A{
var complete: (() -> Void)?
public func checkSignedIn(complete: #escaping (Bool) -> Void) {
_ = Amplify.Auth.fetchAuthSession { (result) in
do {
let session = try result.get()
self.complete = complete(session.isSignedIn)
} catch {
print("Fetch auth session failed with error - \(error)")
self.complete = complete(false)
}
}
}
Then I can call A.complete again.
Am I wrong? I appreciate it if you teach me about this.
No, they won't be the same.
The complete: #escaping (Bool) -> Void defines this:
a function (or a callback) that takes 1 argument (Bool), and returns nothing (Void). It's an equivalent of function that looks like this:
func complete(_ value: Bool) { }
this function escapes the scope of the function it's passed to, as it runs asynchronously (that's #escaping keyword meaning)
And then this function is called with complete(session.isSignedIn), where session.isSignedIn is a boolean argument you pass in, just as function's definition states, and function returns nothing
The statement self.complete = complete(session.isSignedIn) won't compile:
You defined self.complete as (() -> Void) type - that is a function or callback that takes no arguments, and returns nothing. It's an equivalent of function:
func y() { }
So complete(session.isSignedIn) returns Void type as we know. Assigning Void type to (() -> Void) type is not going to work.
If you want to save the escaping function / callback to be used elsewhere, you can do this:
// Make sure signature of the variable matches that of a function argument
var complete: ((Bool) -> Void)?
public func checkSignedIn(complete: #escaping (Bool) -> Void) {
// Save callback at the start of the function
self.complete = complete
// Then continue to a asynch part of the code:
_ = Amplify.Auth.fetchAuthSession { (result) in
// Inside this callback, you still can use the function argument
complete(session.isSignedIn)
...
}
// But in another function, you have to use self.complete, e.g.:
func x() {
// Use saved callback. You don't have to say `self` here, just using it for clarity
self.complete(true)
}

Swift: Call closure complete method in a different function

I'd like to use a method that return a result asynchronously using the delegate pattern within a closure.
Is it possible to reference the complete block within another function within the same class?
class A {
func performASyncTask(input:String, complete:(result:String) -> Void) {
let obj = Loader()
obj.delegate = self
obj.start()
// Loader() returns loaderCompleteWithResult(result:String) when completed
}
func loaderCompleteWithResult(result:String){
// Call complete function in performASyncTask .e.g
complete(result); // Calls the complete function in performASyncTask
}
}
I don't really understand what do you want to achieve. But you can declare function property and use it later:
class A {
var closureSaver: ((result:String) -> Void)?
func performASyncTask(input:String, complete:(result:String) -> Void) {
let obj = Loader()
obj.delegate = self
obj.start()
closureSaver = complete
complete(result: "a")
}
func loaderCompleteWithResult(result:String){
closureSaver?(result:result)
}
}

Having Trouble executing function but not for loop it is in

I am trying to create a function that can take in a function and an Int(numberOfTimes) and then call on doFunctionXTimes() a certain number of times. However, it only prints out "Hello Ethan" once opposed to five times. Here is my code:
func doFunctionXTimes(numberOfTimes: Int,function: Any) {
for _ in 1...numberOfTimes {
function
}
}
func sayHello(name: String) {
print("Hello \(name)")
}
doFunctionXTimes(5, function: sayHello("Ethan"))
//this code prints "Hello Ethan"
However, if change _ to i in the for loop in doFunctionXTimes() and then add a print(i) statement either above or below where I call the function, it will print out all of the numbers from 1 to 5. How can I make it so the function is called on as many times as the print(i) statement is called on and printed. Thank you. Here is my edited code printing i.
func doFunctionXTimes(numberOfTimes: Int,function: Any) {
for i in 1...numberOfTimes {
print(i)
function
// or the print(i) statement can here. It does not affect the output.
}
}
func sayHello(name: String) {
print("Hello \(name)")
}
doFunctionXTimes(5, function: sayHello("Ethan"))
// this code prints out "Hello Ethan" and then 1 2 3 4 5
Any help or advice is great and I hope this helps future viewers.
Have a look at the following code:
doFunctionXTimes(5, function: sayHello("Ethan"))
The sayHello("Ethan") part is a function call. So when the line of code runs, it first calls this function - before entering doFunctionXTimes. Then inside your code, you have:
function
This doesn't actually call the function (it's similar to putting 0 on a line by itself). To achieve what you want, you need a closure, which will "wrap around" the function that you want to call:
func doFunctionXTimes(numberOfTimes: Int,function: (() -> Void)) {
for _ in 1...numberOfTimes {
function()
}
}
func sayHello(name: String) {
print("Hello \(name)")
}
doFunctionXTimes(5, function: { sayHello("Ethan") })
Now function is passed as { sayHello("Ethan") }, and sayHello won't be called until the function is called.
Note that function is now defined as () -> Void, which means it's a func that takes no parameters and returns no value. (I put extra braces around the definition because I find it improves clarity)
You can also set it up so that you can add to the number of times it repeats simply by repeating a var set to the function.
func sayHello(name: String)
{
print("Hello \(name)")
}
func repeatDoFunctionXTimes(number: Int, forFunction function:(()-> Void))-> (() ->Int) {
var runFor = number
var i = 0;
func repeater() -> Int {
while i < runFor {
print(i)
function()
i++
}
runFor += 1
return runFor
}
return repeater
}
var repeatFive = repeatDoFunctionXTimes(5, forFunction: {sayHello("Ethan")})
repeatFive()
If you type in repeatFive() again it will print 6 times and so forth.

Gameplaykit GKState, swift func with two parameters

I'm sure that is a simple question for you.
How can I write a func with two parameters with one GKState?
UPDATE
Apple use
func willExitWithNextState(_ nextState: GKState)
If I use somefunc(state:GKState) works fine
while somefunc(state:GKState, string:String) does't work, why???
Other example
I've tried this:
class Pippo:GKState {}
//1
func printState (state: GKState?) {
print(state)
}
printState(Pippo) //Error cannot convert value of type '(Pippo).Type' (aka 'Pippo.Type') to expected argument type 'GKState?'
//2
func printStateAny (state: AnyClass?) {
print(state)
}
printStateAny(Pippo) //NO Error
//3
func printStateGeneral <T>(state: T?) {
print(state)
}
printStateGeneral(Pippo) //No Error
//4
func printStateAnyAndString (state: AnyClass?, string:String) {
print(state)
print(string)
}
printStateAnyAndString(Pippo/*ExpectedName Or costructor*/, string: "Hello") //ERROR
printStateAnyAndString(Pippo()/*ExpectedName Or costructor*/, string: "Hello") //ERROR cannot convert value of type 'Pippo' to expected argument type 'AnyClass?'
SOLUTION THANKS #0x141E
func printStateAnyAndString (state: GKState.Type, string:String) {
switch state {
case is Pippo.Type:
print("pippo")
default:
print(string)
}
}
printStateAnyAndString(Pippo.self, string: "Not Pippo")
Thanks for reply
If you want a parameter to be a class, use Class.Type or AnyClass
func printState (state: AnyClass, string:String) {
print(state)
print(string)
}
and use Class.self as the argument
printState(Pippo.self, string:"hello pippo")
Update
If your function definition is
func printState (state:GKState, string:String) {
if state.isValidNextState(state.dynamicType) {
print("\(state.dynamicType) is valid")
}
print(state)
print(string)
}
you'll need to pass in an instance of GKState (or a subclass of GKState) as the first argument, not the class/subclass itself. For example,
let pippo = Pippo()
printState (pippo, "Hello")
Throughout your sample code you have used AnyClass, whereas you should (probably) be using AnyObject. AnyClass refers to a class definition, whereas AnyObject is an instance of a class.
class MyClass { }
func myFunc1(class: AnyClass)
func myFunc2(object: AnyObject)
let myObject = MyClass() // create instance of class
myFunc1(MyClass) // myFunc1 is called with a class
myFunc2(myObject) // myFunc2 is called with an instance
You have also made most of your parameters Optionals with the "?", whereas it doesn't look required. For example:
printState(nil) // What should this do?

Sending a function to another function as a parameter

I want to send a func as a parameter to another func but I know how to do it only in case the func being sent has an input and an output parameters:
aFunc (sentFunc: Int -> String) {
...
}
But I want to achieve something like the following code where the function being sent does not have parameters:
func firstFunc(<i want to declare paramenter for a function here that itself does not have any parameters>) {
if (servicedCities != nil) {
<execute sent fuction>
} else {
objectMapper().getServicedCitiesifAvailable()
<execute sent fuction>
}
}
the func calling the above func should look like
func secondFunc() {
func myNestedFunction() {
....
}
....
firstFunc(myNestedFunction())
....
}
func firstFunc(passedFunc:()->()) {
passedFunc()
}
func secondFunc() {
func myNestedFunction() {
print("hi")
}
firstFunc(myNestedFunction)
}
secondFunc()
will ouput
hi
in the context of the firstFunc call.
Note that you have to omit the () in the last line after the myNestedFunction because you dont want to call the method but pass the method itself.
func firstFunc(sentFunc: () -> ()) {
sentFunc()
}
or
func firstFunc(sentFunc: Void -> Void) {
sentFunc()
}
I think you are looking for Swift closures.
Check this Swift closures and functions
func someFunc(paramFunc: () -> ()) {
paramFunc()
}
...
self.someFunc { () -> () in
//Do some code here;
}

Resources