【问题标题】:Self type as argument in closure自类型作为闭包中的参数
【发布时间】:2019-08-28 04:35:04
【问题描述】:

UIView 的实例是否可以调用执行闭包的方法,并在该闭包内部引用同一个实例?这是非通用版本:

import UIKit

public extension UIView {
    func layout(from: (UIView) -> ()) {
        from(self)
    }
}

例如,当我使用 UILabel 调用它时,我无法访问例如文本对齐。是否有可能在闭包内我可以参考 UILabel?我希望这样的事情会起作用:

func layout(from: (Self) -> ()) {
    from(self)
}

但它不能编译。有解决方法吗?这就是我想要的:

let label = UILabel(frame: .zero)

label.layout { $0.textAlignment = .natural } // Currenly not working, since $0 = UIView.

【问题讨论】:

  • 为什么不直接使用label 而不是$0
  • @MoAbdul-Hameed 这是一个更大的简化版本,所以不要介意实际代码:)
  • func layout<T>(from: (T) -> ()) where T == Self 有效吗?
  • @Alexander 不,它不会编译
  • 请参阅stackoverflow.com/a/42356615/2976878 - 您目前可以使用协议扩展来解决此限制,直到它被实施 (SR-10121)。

标签: swift generics


【解决方案1】:

不同的方法:具有关联类型的协议扩展。

protocol Layout {
    associatedtype View : UIView = Self
    func layout(from: (View) -> ())
}

extension Layout where Self : UIView {
    func layout(from: (Self) -> ()) {
        from(self)
    }
}

extension UIView : Layout {}

let label = UILabel(frame: .zero)
label.layout { $0.textAlignment = .natural }

【讨论】:

  • 您无需声明associatedtype 即可使用(或任何协议要求)。您还可以将协议声明为 protocol Layout : UIView 以将其限制为符合 UIView (然后从扩展中删除约束)。
【解决方案2】:

有不同的方法来做到这一点。

首先,您可以使用closures' variable capturing system 来直接使用闭包内的变量,而无需将其作为参数传递。

public extension UIView {
    func layout(from: () -> ()) {
        from()
    }
}

label.layout { label.textAlignment = .natural }

否则,如果您想传递一个通用的 UIView 并相应地更改特定的行为 - 因为看起来您确定自己正在处理什么类型 - 您可以使用向下转换:

public extension UIView {
    func layout(from: (UIView) -> ()) {
        from(self)
    }
}

let label = UILabel(frame: .zero)

label.layout { ($0 as! UILabel).textAlignment = .natural }

不管怎样,你为什么要这样做:

label.layout { $0.textAlignment = .natural }

代替:

label.textAlignment = .natural

有什么特别的理由不这样做吗?我想在幕后有更大的东西,我只是好奇。

【讨论】:

  • 您好,感谢您的回复。问题中的代码不是真正的代码,而是简化版本。当使用您在答案顶部描述的闭包方法时,我没有得到self 类型的参数(这是问题)。
  • 您好!我明白了,答案的第二部分呢?我的意思是,沮丧的人。是不是太了?
  • 是的,我不想每次使用都沮丧,但仍然感谢您的解释和回答:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
  • 1970-01-01
  • 2019-11-10
  • 2011-08-06
  • 2021-11-02
  • 1970-01-01
相关资源
最近更新 更多