使用协议的Swift中的通用观察者模式给出了分段错误

时间:2017-03-26 06:21:02

标签: swift segmentation-fault

import Foundation
class IProtocol {
     func meth1(arg: Int){}
}
class IObserver: IProtocol {
    private var className: String
    init(name: String) {
        className = name
    }
    override func meth1(arg: Int) {
        print(className, ":", arg)
    }
}
class Notifier<T> {
    private var listOfObservers = NSMutableArray()
    func addObserver(observer: T) {
        listOfObservers.add(observer)
    }
    func callObservers<ARG, RET>(function: (T)->(ARG)->RET, arg: ARG) {
        for obj in listOfObservers {
            let observer = obj as! T
            _ = function(observer)(arg)
        }
    }
}
let a = IObserver(name: "First I Observer")
let b = IObserver(name: "Second I Observer")
let n = Notifier<IProtocol>()
n.addObserver(observer: a)
n.addObserver(observer: b)
n.callObservers(function: IProtocol.meth1, arg: Int(1))

输出
首先我观察:1 第二个观察员:1

上面的示例失败,并且由于信号错误导致命令失败:分段错误:11 ,当我从 IProtocol 更改为协议时>类即可。我有不同的协议和不同的观察者类确认这些协议。我正在尝试实现一个Notifier类,它通过从协议中获取方法以及为该方法传递的参数来通知观察者。
如果有人可以解释我做错了什么,那将是很棒的!

我正在使用 Swift 3 Xcode 8.2

1 个答案:

答案 0 :(得分:0)

截至今天, Swift不处理对协议方法的直接引用

protocol IProtocol {
    func meth1()
}
class IObserver: IProtocol {
    func meth1() { print("success") }
}
let x = IProtocol.meth1 // This causes the compiler crash
x(IObserver())()

我的问题的解决方案是传递闭包而不是方法。这是它的外观:

import Foundation
protocol IProtocol {
    func meth1(arg: Int)
}
class IObserver: IProtocol {
    private var className: String
    init(name: String) {
        className = name
    }
    func meth1(arg: Int) {
        print(className, ":", arg)
    }
}
class Notifier<T> {
    private var listOfObservers = NSMutableArray()
    func addObserver(observer: T) {
        listOfObservers.add(observer)
    }
    func callObservers<ARG>(function: (T, ARG) -> (), arg: ARG) {
        for obj in listOfObservers {
            let observer = obj as! T
            function(observer, arg)
        }
    }
}
let a = IObserver(name: "First I Observer")
let b = IObserver(name: "Second I Observer")
let n = Notifier<IProtocol>()
n.addObserver(observer: a)
n.addObserver(observer: b)
n.callObservers(function: {obs, ar in
    obs.meth1(arg: ar)
}, arg: Int(1))