【问题标题】:How can I define a function/closure which returns a Binding?如何定义返回绑定的函数/闭包?
【发布时间】:2021-11-19 01:12:54
【问题描述】:

当我在某些情况下必须初始化 Binding 时,我想制作一个让我的打字更容易的函数!

代码如下:

func bindingFunction(value: inout CGFloat) -> Binding<CGFloat> {
    return Binding(get: { return value }, set: { newValue in value = newValue })
}

我从 xCode 收到 2 个错误:

  1. 参数“value”被声明为“inout”

转义闭包捕获'inout'参数'value'

我的目标是首先解决这些错误,最后我想让我的函数也通用,因为你看到我的函数适用于我的绑定 CGFloat想让它通用,然后我可以在需要 Binding Bool 时使用它。

【问题讨论】:

  • inout 在这里不起作用的相关信息:stackoverflow.com/a/39572470/560942
  • 那么我的目标是不可能的,对吧?
  • 如果您的要求之一是使用inout,这似乎不太可能(尽管也许有人知道一些疯狂的技巧来让它工作)。您可能可以通过将转义闭包作为返回值的参数而不是 inout 参数来使其工作,但在这一点上,真的没有理由不首先编写 Binding。
  • 正如我所说的打字问题会更好。
  • 但是如果你使用了闭包,你需要提供两个闭包——一个用来获取值,一个用来设置值,这正是 Binding 首先要做的。所以,它不会为你节省任何东西。

标签: swift swiftui


【解决方案1】:

正如您在 cmets 中看到的那样,没有一个好的通用解决方案。如果您有 ReferenceWritableKeyPath 可以使用(这意味着没有值类型,例如您的 CGFloat),您真的可以让它变得更容易。

一般来说,没有人需要这个,因为我们都在使用ObservableObjects + @Published

final class Model {
  var leaves = "?"
}

let model = Model()
let fallenLeaves = "?"
@Binding(model, keyPath: \.leaves) var leaves;
leaves = fallenLeaves
XCTAssertEqual(model.leaves, fallenLeaves)
public extension Binding {
  init(
    accessors: (
      get: () -> Value,
      set: (Value) -> Void
    )
  ) {
    self.init(get: accessors.get, set: accessors.set)
  }

  init<Root>(
    _ root: Root,
    keyPath: ReferenceWritableKeyPath<Root, Value>
  ) {
    self.init(accessors: keyPath.accessors(root))
  }
}
public extension ReferenceWritableKeyPath {
  /// Partially-applied `get` and `set` accessors for this key path.
  ///
  /// Typical usage: `accessors(root)`
  var accessors: (Root) -> (
    get: () -> Value,
    set: (Value) -> Void
  ) {
    { root in
      ( get: { root[keyPath: self] },
        set: { root[keyPath: self] = $0 }
      )
    }
  }
}

【讨论】:

  • 感谢您的宝贵时间,当我尝试使用您给定的代码时,看起来我应该为它提供 2 个闭包以开始工作,但是我无法使用它。所以我可以对获取和设置的原始绑定初始化做同样的事情!你的代码在哪里有用?在我的问题中也是在我的代码中,我尝试至少使打字部分比原始绑定更短更容易。
  • 好的,我会再试一次,谢谢。
  • 我再次查看了 XCTest 示例,我认为它需要类或自定义类才能工作,因为我的代码或函数不需要类,我无法利用您的回答,但感谢您的帮助。
  • 没错。我添加了一个括号。
猜你喜欢
  • 2022-01-23
  • 2018-03-29
  • 1970-01-01
  • 2018-04-16
  • 2020-02-28
  • 2011-12-19
  • 1970-01-01
  • 2017-02-26
  • 2019-10-31
相关资源
最近更新 更多