Home > Blockchain >  generic function with binding generic variable in Swift
generic function with binding generic variable in Swift

Time:12-15

can anyone explain what exactly does below generic class "Active" works with this - bind variable ? Below are 3 examples mentioned also but I'm really not clear how does it work

class Active<T> {

    var bind :(T) -> () = { _ in }

    var value :T {
        didSet {
            bind(value)
        }
    }

    init(_ v :T) {
        value = v
    }
}

Example :

  1. var user = Active("")
  2. var count = Active(64)
  3. var status = Active(true)

Exact example shown in below link

https://levelup.gitconnected.com/2-ways-to-execute-mvvm-ios-5c47d60ebcd0

CodePudding user response:

You give examples where you instantiate Active with different types of values (illustrating the generic behavior). But you are not availing yourself of the “observer” pattern that Active affords.

Let’s see how you would use Active:

let foo = Active(0)
foo.bind = { value in
    print(value)
}
foo.value = 1          // the closure will be called, printing the value
foo.value = 42         // the closure will be called again

The idea is that you instantiate the object, replace the bind closure with your own, and then the closure will be called every time you change the value.

The virtue of this “observer” pattern is that Active is providing a mechanism (a simple closure in this primitive example) to allow other objects to observe changes to the value. This is one of the central precepts of MVVM (as that article you quote is attempting to convey), namely, that you can write code that, for example, automatically updates a view based upon changes to a model.

CodePudding user response:

If you're familiar with completion handlers, then this will make perfect sense to you. Consider a function with a barebones completion handler:

func someFunction(completion: () -> Void) {
    completion()
}

someFunction {
    print("completion")
}

The completion handler has no parameters and so it is called with completion() and the closure's capture list someFunction { ... } is empty. However, if we were to add a parameter to this completion handler, then it would be called with the parameter completion(true) and the closure would have to define its capture list someFunction { (done) in ... }.

func someFunction(completion: (_ done: Bool) -> Void) {
    completion(true)
}

someFunction { (done) in
    print(done)
}

And if we didn't care about the boolean in the completion handler then we could ignore it in the closure's capture list:

someFunction { _ in
    print("completion")
}

And this is what bind is, a closure with a single parameter with a capture list that doesn't care about the parameter it was passed.

var bind: (T) -> Void = { _ in }

So the idea is to instantiate Active, with a value, and then give bind a closure to execute whenever the value changes. And so when it changes, you have bound some task to the changing of that value.

// instantiate
var count = Active(64)

// bind its change to a closure
count.bind = { _ in
    // perhaps update the UI?
}

// later when the value changes, the closure is called and
// whatever task you had in the closure is executed
count.value = 128

And, as a side note, T is just an arbitrary letter (it could be

  • Related