Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/108.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios KVO观察不适用于Swift泛型_Ios_Generics_Swift_Key Value Observing - Fatal编程技术网

Ios KVO观察不适用于Swift泛型

Ios KVO观察不适用于Swift泛型,ios,generics,swift,key-value-observing,Ios,Generics,Swift,Key Value Observing,如果我使用KVO观察属性,如果观察者是泛型类,那么我会收到以下错误: 对象的-observeValueForKeyPath:更改:上下文:消息为 已收到但未处理 下面的设置简洁地演示了这个问题。定义一些简单的类: var context = "SomeContextString" class Publisher : NSObject { dynamic var observeMeString:String = "Initially this value" } class Subscr

如果我使用KVO观察属性,如果观察者是泛型类,那么我会收到以下错误:

对象的-observeValueForKeyPath:更改:上下文:消息为 已收到但未处理

下面的设置简洁地演示了这个问题。定义一些简单的类:

var context = "SomeContextString"

class Publisher : NSObject {
    dynamic var observeMeString:String = "Initially this value"
}

class Subscriber<T> : NSObject {
    override func observeValueForKeyPath(keyPath: String,
                    ofObject object: AnyObject,
                    change: [NSObject : AnyObject],
                    context: UnsafeMutablePointer<Void>) {
        println("Hey I saw something change")
    }
}
var context=“SomeContextString”
类发布者:NSObject{
dynamic var observeMeString:String=“最初为该值”
}
类订户:NSObject{
重写函数observeValueForKeyPath(键路径:字符串,
ofObject对象:任何对象,
更改:[NSObject:AnyObject],
上下文:unsafemeutablepointer){
println(“嘿,我看到了一些变化”)
}
}
实例化它们并尝试使用订阅服务器观察发布服务器,如下所示(在空白项目的UIViewController子类中完成):

var pub=Publisher()
var sub=订户()
重写func viewDidLoad(){
super.viewDidLoad()
pub.addObserver(sub,forKeyPath:“observeMeString”,选项:。新建,上下文:&上下文)
pub.observeMeString=“现在该值”
}
如果我从类定义中删除泛型类型T,那么一切都可以正常工作,但否则我会得到“已接收但未处理的错误”。我是不是漏掉了什么明显的东西?我还需要做些什么,或者泛型不应该与KVO一起使用吗?

解释 一般来说,有两个原因可以阻止特定的Swift类或方法在Objective-C中使用

第一个是纯Swift类使用C++风格的vtable分派,Objective-C不理解这一点。这在大多数情况下可以通过使用
dynamic
关键字来克服,正如您显然理解的那样

第二个是,一旦引入泛型,Objective-C就失去了查看泛型类的任何方法的能力,直到它到达继承层次结构中祖先不是泛型的点为止。这包括引入的新方法以及覆盖

class Watusi : NSObject {
    dynamic func watusi() {
        println("watusi")
    }
}

class Nguni<T> : Watusi {
    override func watusi() {
       println("nguni")
    }
}

var nguni = Nguni<Int>();

这是因为
Subscriber
本身不是泛型的,只是它的
init
方法。闭包用于对Objective-C“隐藏”泛型类型参数。

不同的问题,但原因相同:
class Watusi : NSObject {
    dynamic func watusi() {
        println("watusi")
    }
}

class Nguni<T> : Watusi {
    override func watusi() {
       println("nguni")
    }
}

var nguni = Nguni<Int>();
class Subscriber : NSObject {
    private let _observe : (String, AnyObject, [NSObject: AnyObject], UnsafeMutablePointer<Void>) -> Void

    required init<T: NSObject>(obj: T, observe: ((T, String) -> Void)) {
        _observe = { keyPath, obj, changes, context in
            observe(obj as T, keyPath)
        }
    }
    override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
        _observe(keyPath, object, change, context)
    }
}

class Publisher: NSObject {
    dynamic var string: String = nil
}

let publisher = Publisher()
let subscriber = Subscriber(publisher) { _, _ in println("Something changed!") }
publisher.addObserver(subscriber, forKeyPath: "string", options: .New, context: nil)
publisher.string = "Something else!"