How to use an Swift object method as a closure? - swift

I'd like to use an object method as a closure because I need to reuse the same closure multiple times in different places in an object. Let's say I have the following:
class A {
func launch(code: Int) -> Bool { return false }
}
And I need a closure that is of type Int -> Bool in the same object. How would I be able to use the launch method as the closure? I'd rather not do something like { self.launch($0) } if I can just directly reference the method.

Instance methods are curried functions which take the instance
as the first argument. Therefore
class A {
func launch(code: Int) -> Bool { return false }
func foo() {
let cl = A.launch(self)
// Alternatively:
let cl = self.dynamicType.launch(self)
// ...
}
}
gives you a closure of the type Int -> Bool.

Related

Pass in argument predefined or custom function in swift

I want to pass to setter as argument one of predefined functions (in enum maybe or static) or custom function in closure.
like UIColor to UIView.backgroundColor (i can set .black or UIColor(...)). How can I do it with my custom class?
class MyClass {
var fun: ((String)->Void)?
}
var obj = MyClass()
obj.fun = {print($0)} . // It works now
obj.fun = .predefinedFunc // It's how i want to be able do
What you seem to want to do is "implicit member access". Unfortunately, this is not possible on closure types like (String) -> Void, because it only works on enums, as well as types with static members. (String) -> Void doesn't and can't have any static members.
It seems like what you want is simply a bunch of predefined functions. This can be done with an enum:
enum Function {
case predefinedFunc1
case predefinedFunc2
case predefinedFunc3 // name these properly!
var closure: (String) -> Void {
switch self {
case .predefinedFunc1: return { print($0) }
case .predefinedFunc2: ...
case .predefinedFunc3: ...
}
}
}
And then you'll be able to do:
class MyClass {
var fun: Function?
}
var obj = MyClass()
obj.func = .predefinedFunc1
If you also want to include an option to use a custom function, add an extra case with an associated value:
enum Function {
...
case custom((String) -> Void)
var closure: (String) -> Void {
switch self {
case .predefinedFunc1: return { print($0) }
...
case .custom(let f): return f
}
}
}
view.backgroundColor = .black
works because black is a static property of struct UIColor. The right-hand side is called an “implicit member expression,” see for example What is the Swift syntax " .bar" called?.
Function types are neither classes nor structs, and you cannot define a static property for a function type. Therefore an identical syntax is not possible.
What you can do is to define a “wrapper” struct for the function, with static properties for the predefined functions. Here is a simple example:
struct Fun {
let f: (String) -> Void
init(_ f: #escaping (String) -> Void) {
self.f = f
}
// Predefined functions:
static var printer = Fun( { print($0) } )
// ...
}
class MyClass {
var fun: Fun?
}
And then you can do
let obj = MyClass()
obj.fun = Fun( { print($0) } ) // set to custom function
obj.fun = .printer // set to predefined function
This approach also allows to extend the wrapper type by more predefined functions:
extension Fun {
static var printReversed = Fun( { print($0.reversed()) } )
}
// ...
obj.fun = .printReversed
Please define the func same as you callback func or nameless fun, then you can pass it as an argument.
class MyClass {
var fun: ((String)->Void)?
}
//MARK:- you have to provide the same param and return type in your predefined func.
func printer(Str :String)->Void{
print(Str)
}
var obj = MyClass()
obj.fun = {print($0)}
obj.fun = printer

How to pass a function as an optional parameter Swift

New to Swift and I am currently getting around passing a function as an optional parameter in the following way:
import Foundation
func foo()
{
print("Foo")
}
func bar()
{
print("Bar")
}
func dummy()
{
return
}
func myFunc()
{
myFunc(callBack: dummy())
}
func myFunc(callBack: (Void))
{
foo()
callBack
}
myFunc()
myFunc(callBack: bar())
i.e. exploiting polymorphism
This seems like an inelegant way to do this, is there a better way,
Thanks,
Tom
edit:
I am aware I could shorten this by doing:
import Foundation
func foo()
{
print("Foo")
}
func bar()
{
print("Bar")
}
func dummy()
{
return
}
func myFunc(callBack: (Void) = dummy())
{
foo()
callBack
}
myFunc()
myFunc(callBack: bar())
But I would still say this is an inelegant solution
You can easily define a default value for a function as parameter:
func foo(completion: () -> Void = { }) {
completion()
}
You could also have it be nil by default:
func foo(completion: (() -> Void)? = nil) {
When it's an optional closure, you'll have to call it like this:
completion?()
Your are referring to default arguments:
You can define a default value for any parameter in a function by assigning a value to the parameter after that parameter’s type. If a default value is defined, you can omit that parameter when calling the function.
So you need something like:
func myfunc (callback: ()->void = dummy) {
LinusGeffarth notes that callbacks in Swift are called completion, or closure as avismara notes.
Full code with answer applied:
import Foundation
func foo()
{
print("Foo")
}
func bar()
{
print("Bar")
}
func myFunc(completion: () -> Void = { })
{
foo()
completion()
}
myFunc()
myFunc(completion: bar)
Umm, are you passing function as an optional parameter, though? It looks like you have written a method that accepts Void, you have a function that accepts Void and you are just calling that method. I don't see any trace of polymorphism here except probably that the myFunc has multiple signatures. This method is an inelegant solution not because it is inelegant, but because it isn't a solution.
Here is a correct example of polymorphism in functional systems:
func printA() {
print("A")
}
func printB() {
print("B")
}
//This method accepts a function as a parameter
func higherOrderPrinter(with print: () -> Void ) {
print() //Can be anything, depends on the method you send here. Polymorphism much? :)
}
higherOrderPrinter(with: printA) //Prints A. See carefully how I am NOT doing printA()
higherOrderPrinter(with: printB) //Prints B
//In fact...
higherOrderPrinter {
print("C")
} //Prints C

How to pass closure with argument as argument and execute it?

Initializer of class A takes an optional closure as argument:
class A {
var closure: ()?
init(closure: closure()?) {
self.closure = closure
self.closure()
}
}
I want to pass a function with an argument as the closure:
class B {
let a = A(closure: action(1)) // This throws the error: Cannot convert value of type '()' to expected argument type '(() -> Void)?'
func action(_ i: Int) {
//...
}
}
Class A should execute the closure action with argument i.
I am not sure about how to write this correctly, see error in code comment above. What has to be changed?
Please make your "what-you-have-now" code error free.
Assuming your class A like this:
class A {
typealias ClosureType = ()->Void
var closure: ClosureType?
init(closure: ClosureType?) {
self.closure = closure
//`closure` would be used later.
}
//To use the closure in class A
func someMethod() {
//call the closure
self.closure?()
}
}
With A given above, you need to rewrite your class B as:
class B {
private(set) var a: A!
init() {
//initialize all instance properties till here
a = A(closure: {[weak self] in self?.action(1)})
}
func action(i: Int) {
//...
}
}
The problem is that closure()? is not a type. And ()? is a type, but it is probably not the type you want.
If you want var closure to have as its value a certain kind of function, you need to use the type of that function in the declaration, e.g.
var closure: (Int) -> Void
Similarly, if you want init(closure:) to take as its parameter a certain kind of function, you need to use the type of that function in the declaration, e.g.
init(closure: (Int) -> Void) {
Types as Parameters
In Swift, every object has a type. For example, Int, String, etc. are likely all types you are extremely familiar with.
So when you declare a function, the explicit type (or sometimes protocols) of any parameters should be specified.
func swallowInt(number: Int) {}
Compound Types
Swift also has a concept of compound types. One example of this is Tuples. A Tuple is just a collection of other types.
let httpStatusCode: (Int, String) = (404, "Not Found")
A function could easily take a tuple as its argument:
func swallowStatusCode(statusCode: (Int, String)) {}
Another compound type is the function type. A function type consists of a tuple of parameters and a return type. So the swallowInt function from above would have the following function type: (Int) -> Void. Similarly, a function taking in an Int and a String and returning a Bool would have the following type: (Int, String) -> Bool.
Function Types As Parameters
So we can use these concepts to re-write function A:
class A {
var closure: (() -> Void)?
init(closure: (() -> Void)?) {
self.closure = closure
self.closure()
}
}
Passing an argument would then just be:
func foo(closure: (Int) -> Void) {
// Execute the closure
closure(1)
}
One way to do what I think you're attempting is with the following code:
class ViewController: UIViewController {
override func viewDidLoad() {
let _ = A.init(){Void in self.action(2)}
}
func action(i: Int) {
print(i)
}
}
class A: NSObject {
var closure : ()?
init(closure: (()->Void)? = nil) {
// Notice how this is executed before the closure
print("1")
// Make sure closure isn't nil
self.closure = closure?()
}
}

How to generate and use Swift object method signature list?

I realized that I could generate a list of methods:
class A {
let methodList: [A -> Int -> Bool] = [methodA, methodB]
func methodA(val: Int) -> Bool { return true }
func methodB(val: Int) -> Bool { return false }
}
That's great. How do I create a loop that can call these methods? The obvious, like obj.methodList[0](1) doesn't work.
You could do this:
let a = A()
let result = a.methodList[0](a)(1)
since your method probably needs an instance to resolve properly.

Write a custom access operator in Swift

I implemented a helper to have an array of unowned references:
class Unowned<T: AnyObject>
{
unowned var value : T
init (value: T) { self.value = value }
func get() -> T { return self.value }
}
Now, it is possible to do [ Unowned<Foo> ]. However, I'm not satisfied with having the additional get() method to retrieve the underlying object. So, I wanted to write a custom binary operator, e.g. --> for being able to do
for unownedFoo in ArrayOfUnownedFoos
{
var bar : Int = unownedFoo-->method()
}
My current approach is to define
infix operator --> { }
func --><T> (inout lhs: Unowned<T>, inout rhs: () -> Int) -> Int
{
}
The idea I had behind this is:
lhs is obvisouly the object I get out of the array, on which I want to perform the call on
rhs is the method I desire to call. In this case method() would not take no parameters and return an Int, and therefore
The return value is int.
However, the following problems / uncertainties arise:
Is this the correct approach?
Are my assumptions above correct?
How can I call the provided closure rhs on the instance of the extracted Unowned<T>, e.g. (pseudocode) lhs.value.rhs(). If method() was static, I could do T.method(lhs.value), but then I would have to extract the name of the method somehow to make it more generic.
Maybe, a postfix operator is rather simple.
postfix operator * {}
postfix func *<T>(v:Unowned<T>) -> T {
return v.value
}
// Usage:
for unownedFoo in ArrayOfUnownedFoos {
var bar : Int = unownedFoo*.method()
}
Use something like:
func --> <T:AnyObject, V> (lhs: Unowned<T>, rhs: (T) -> V) -> V
{
return rhs (lhs.get())
}
and then use it as:
for unownedFoo in ArrayOfUnownedFoos
{
var bar : Int = unownedFoo-->{ (val:Int) in return 2*val }
}
Specifically, you don't want to use method() as that itself is a function call - which you probably don't want unless method() is actually returning a closure.