我制定了一个协议:
protocol SomeProtocol {
func getData() -> String
}
我创建了一个符合它的结构:
struct SomeStruct: SomeProtocol {
func getData() -> String {
return "Hello"
}
}
现在我希望每个UIViewController
都有一个名为source
的属性,所以我可以做类似......
class MyViewController : UIViewController {
override func viewDidLoad() {
self.title = source.getData()
}
}
为实现这一目标,我创建了一个协议来定义属性:
protocol SomeProtocolInjectable {
var source: SomeProtocol! { get set }
}
现在我只需要使用以下属性扩展视图控制器:
extension UIViewController: SomeProtocolInjectable {
// ???
}
如何将存储的属性与协议类型一起破解?
什么没有用:
var source: SomeProtocol!
显然无效,因为扩展程序没有存储属性还有其他建议吗?
答案 0 :(得分:3)
您可以使用静态和视图控制器hash
:
struct SomeProtocol {/*....*/}
struct DataProxy {
var data: [Int: SomeProtocol]
}
protocol SomeProtocolInjectable {
var source: SomeProtocol! { get set }
}
extension UIViewController: SomeProtocolInjectable {
static var dataProxy = DataProxy(data: [:])
var source: SomeProtocol! {
get{
return UIViewController.dataProxy.data[self.hashValue]
}
set{
UIViewController.dataProxy.data[self.hashValue] = newValue
}
}
}
答案 1 :(得分:3)
任何协议对象都可以转换为类型擦除类。构建AnySomeProtocol
并存储该内容。
private var sourceKey: UInt8 = 0
final class AnySomeProtocol: SomeProtocol {
func getData() -> String { return _getData() }
init(_ someProtocol: SomeProtocol) { _getData = someProtocol.getData }
private let _getData: () -> String
}
extension UIViewController: SomeProtocolInjectable {
var source: SomeProtocol! {
get {
return objc_getAssociatedObject(self, &sourceKey) as? SomeProtocol
}
set(newValue) {
objc_setAssociatedObject(self, &sourceKey, AnySomeProtocol(newValue), .OBJC_ASSOCIATION_RETAIN)
}
}
}
class MyViewController : UIViewController {
override func viewDidLoad() {
self.title = source.getData()
}
}
调用者只能使用它来访问协议方法。你不能用as
强制它恢复原来的类型,但无论如何你应该避免这种情况。
作为旁注,我建议source
返回SomeProtocol?
而不是SomeProtocol!
。这里没有任何承诺source
将被设定。你甚至不能在viewDidLoad
之前设置它。
答案 2 :(得分:0)
如何为> percent(c(0.123,0.00234))
[1] "12.3%" "0.2%"
添加默认实现,为协议提供虚拟结构实现,并将其用作getData()
变量的默认值:
source
我冒昧地扩展protocol SomeProtocol {
func getData() -> String
}
extension SomeProtocol {
func getData() -> String {
return "Hello"
}
}
protocol SomeProtocolInjectable {
var source: SomeProtocol { get set }
}
struct DummyProtocolImplementation: SomeProtocol {
}
class MyViewController : UIViewController {
var _source: SomeProtocol = DummyProtocolImplementation()
override func viewDidLoad() {
self.title = source.getData()
}
}
extension MyViewController: SomeProtocolInjectable {
var source: SomeProtocol { get { return _source } set { _source = newValue } }
}
而不是MyViewController
,因为后者无论如何都不知道协议。