【问题标题】:generic function with binding generic variable in Swift在 Swift 中具有绑定泛型变量的泛型函数
【发布时间】:2021-12-14 16:27:49
【问题描述】:

任何人都可以解释通用类“Active”下面的具体作用是什么 - 绑定变量?下面也提到了 3 个例子,但我真的不清楚它是如何工作的

class Active<T> {

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

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

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

例子:

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

具体示例如下链接所示

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

【问题讨论】:

  • 您是否理解bind 是一个闭包?
  • 如果您要重新编写该代码,您必须创建 3 个类。一个所有提及T 的地方都替换为String。另一个所有提及T 的地方都替换为Int。另一个所有提及都替换为Bool。 Swift 具有泛型,因此可以创建 1 个类而不是 3 个。&lt;T&gt; 仅表示任何类型。 &lt;&gt; 中的任何内容都类似于占位符类型。如果您使用&lt;T:Equatable&gt;,那么它只是意味着 any 也恰好符合Equatable 协议。有关更多信息,请参阅docs
  • 旁注:didSet 不应在 init 上调用,因此实际上 binding 可能无法按预期工作。
  • 这个类是一个包装器,只要值改变就简单地调用bind函数。
  • @Larme,@Honey - 绑定闭包实际上是做什么的?关闭时没有什么可以执行的?

标签: swift variables generics


【解决方案1】:

如果您熟悉完成处理程序,那么这对您来说非常有意义。考虑一个带有准系统完成处理程序的函数:

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

someFunction {
    print("completion")
}

完成处理程序没有参数,因此使用completion() 调用,而闭包的捕获列表someFunction { ... } 为空。但是,如果我们要向这个完成处理程序添加一个参数,那么它将使用参数completion(true) 调用,并且闭包必须定义其捕获列表someFunction { (done) in ... }

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

someFunction { (done) in
    print(done)
}

如果我们不关心完成处理程序中的布尔值,那么我们可以在闭包的捕获列表中忽略它:

someFunction { _ in
    print("completion")
}

这就是bind 的含义,一个带有单个参数的闭包和一个不关心传递的参数的捕获列表。

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

所以想法是用一个值来实例化Active,然后给bind一个闭包,以便在值发生变化时执行。因此,当它发生变化时,您已经将一些任务绑定到该值的变化上。

// 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

并且,作为旁注,T 只是一个任意字母(可能是?),用作当此对象时实际使用的任何类型(即IntBool)的占位符被实例化。无论T 是什么,在此对象的整个使用过程中都必须是相同的类型。

【讨论】:

    【解决方案2】:

    您给出了使用不同类型的值实例化 Active 的示例(说明了一般行为)。但是您并没有利用 Active 提供的“观察者”模式。

    让我们看看你会如何使用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
    

    想法是你实例化对象,用你自己的闭包替换bind,然后每次更改值时都会调用闭包。

    这种“观察者”模式的优点是Active 提供了一种机制(在这个原始示例中是一个简单的闭包)来允许其他对象观察值的变化。这是 MVVM 的核心原则之一(正如您引用的那篇文章试图传达的那样),即您可以编写代码,例如,根据模型的更改自动更新视图。

    【讨论】:

    • 感谢您的解释和示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 2022-01-04
    • 2022-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多