- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在尝试创建一个简单的协议(protocol)来说明对象是处于“打开”状态还是“关闭”状态。对那是什么的解释取决于实现对象。对于 UISwitch
,它是开关是打开还是关闭(duh)。对于 UIButton
,可能是按钮是否处于 selected
状态。对于 Car
,它可能是汽车的引擎是否打开,甚至是它是否在移动。所以我着手创建这个简单的协议(protocol):
protocol OnOffRepresentable {
func isInOnState() -> Bool
func isInOffState() -> Bool
}
现在我可以像这样扩展上述 UI 控件:
extension UISwitch: OnOffRepresentable {
func isInOnState() -> Bool { return on }
func isInOffState() -> Bool { return !on }
}
extension UIButton: OnOffRepresentable {
func isInOnState() -> Bool { return selected }
func isInOffState() -> Bool { return !selected }
}
现在我可以创建一个包含这些类型对象的数组并循环检查它们是打开还是关闭:
let booleanControls: [OnOffRepresentable] = [UISwitch(), UIButton()]
booleanControls.forEach { print($0.isInOnState()) }
太棒了!现在我想制作一个将这些控件映射到 UILabel
的字典,这样我就可以在控件更改状态时更改与控件关联的标签的文本。所以我去声明我的字典:
var toggleToLabelMapper: [OnOffRepresentable : UILabel] = [:]
// error: type 'OnOffRepresentable' does not conform to protocol 'Hashable'
哦!正确的!傻我。好的,让我使用协议(protocol)组合更新协议(protocol)(毕竟,我想在这里使用的控件都是 Hashable:UISwitch、UIButton 等):
protocol OnOffRepresentable: Hashable {
func isInOnState() -> Bool
func isInOffState() -> Bool
}
但是现在我得到了一组新的错误:
error: protocol 'OnOffRepresentable' can only be used as a generic constraint because it has Self or associated type requirements
error: using 'OnOffRepresentable' as a concrete type conforming to protocol 'Hashable' is not supported
好的...所以我做了一些堆栈溢出挖掘和搜索。我发现很多文章看起来很有前途,比如 Set and protocols in Swift , Using some protocol as a concrete type conforming to another protocol is not supported ,我看到那里有一些关于 type erasure
的好文章,它们似乎正是我需要的:http://krakendev.io/blog/generic-protocols-and-their-shortcomings , http://robnapier.net/erasure , 和 https://realm.io/news/type-erased-wrappers-in-swift/仅举几例。
不过这是我卡住的地方。我已经尝试通读所有这些内容,并尝试创建一个 Hashable
类并且还符合我的 OnOffRepresentable
协议(protocol),但我想不通了解如何将它们连接起来。
最佳答案
我不知道我是否必须使 OnOffRepresentable
协议(protocol)继承自 Hashable
。它似乎并不像您想要表示为开或关的东西必须也是可散列的。因此,在我下面的实现中,我仅将 Hashable
一致性添加到类型删除包装器。这样,您可以尽可能直接引用 OnOffRepresentable
项目(没有“只能在通用约束中使用”警告),并且只将它们包装在 HashableOnOffRepresentable
类型橡皮擦中当您需要将它们放在集合中或将它们用作字典键时。
protocol OnOffRepresentable {
func isInOnState() -> Bool
func isInOffState() -> Bool
}
extension UISwitch: OnOffRepresentable {
func isInOnState() -> Bool { return on }
func isInOffState() -> Bool { return !on }
}
extension UIButton: OnOffRepresentable {
func isInOnState() -> Bool { return selected }
func isInOffState() -> Bool { return !selected }
}
struct HashableOnOffRepresentable : OnOffRepresentable, Hashable {
private let wrapped:OnOffRepresentable
private let hashClosure:()->Int
private let equalClosure:Any->Bool
var hashValue: Int {
return hashClosure()
}
func isInOnState() -> Bool {
return wrapped.isInOnState()
}
func isInOffState() -> Bool {
return wrapped.isInOffState()
}
init<T where T:OnOffRepresentable, T:Hashable>(with:T) {
wrapped = with
hashClosure = { return with.hashValue }
equalClosure = { if let other = $0 as? T { return with == other } else { return false } }
}
}
func == (left:HashableOnOffRepresentable, right:HashableOnOffRepresentable) -> Bool {
return left.equalClosure(right.wrapped)
}
func == (left:HashableOnOffRepresentable, right:OnOffRepresentable) -> Bool {
return left.equalClosure(right)
}
var toggleToLabelMapper: [HashableOnOffRepresentable : UILabel] = [:]
let anySwitch = HashableOnOffRepresentable(with:UISwitch())
let anyButton = HashableOnOffRepresentable(with:UIButton())
var switchLabel:UILabel!
var buttonLabel:UILabel!
toggleToLabelMapper[anySwitch] = switchLabel
toggleToLabelMapper[anyButton] = buttonLabel
关于ios - 创建一个表示可以打开或关闭的可散列对象的协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39048963/
我是一名优秀的程序员,十分优秀!