如何在Swift中的泛型类上实现NSCoding? [英] How to implement NSCoding on a generic class in Swift?

查看:121
本文介绍了如何在Swift中的泛型类上实现NSCoding?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Swift(XCode beta 5)中遇到了泛型类和NSCoding问题。具体来说,这个示例代码很好用:

  class Foo:NSObject,NSCoding 
{
let bar:字符串
init(bar:String){
self.bar = bar;

$ b func encodeWithCoder(aCoder:NSCoder!){
aCoder.encodeObject(bar,forKey:bar)
}
所需的init(编码器aDecoder:NSCoder!){
self.bar = aDecoder.decodeObjectForKey(bar)as String
super.init()
}




let foo = Foo(bar:hello,world)

NSKeyedArchiver.archiveRootObject(foo,toFile:test.dat)

但是,当我尝试相同的代码并添加一个通用参数时;当我尝试编码对象时;我得到一个'无法识别的选择器发送到实例'错误:

  class Foo< T> :NSObject,NSCoding 
{
let bar:String
init(bar:String){
self.bar = bar;

$ b func encodeWithCoder(aCoder:NSCoder!){
aCoder.encodeObject(bar,forKey:bar)
}
所需的init(编码器aDecoder:NSCoder!){
self.bar = aDecoder.decodeObjectForKey(bar)as String
super.init()
}




let foo = Foo< String>(bar:hello,world)

NSKeyedArchiver.archiveRootObject(foo,toFile:test.dat)

以下是错误详细信息和堆栈跟踪:

<$无法识别的选择器发送到实例0x7f8890ee4080
2014-08-16 10:43:54.632 SafeId [1778:32501] ***由于未被捕获的终止应用程序异常'NSInvalidArgumentException',原因:' - [_TtC6SafeId14ArrayContainer00007F8893418E58 encodeWithCoder:]:无法识别的选择器发送到实例0x7f8890ee4080'
***第一次抛出调用堆栈:

0 CoreFoundation 0x0000000103a6e3e5 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010371e967 objc_exception_throw + 45
2 CoreFoundation 0x0000000103a754fd - [NSObject(NSObject)doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00000001039cd5ff ___forwarding___ + 495
4 CoreFoundation 0x00000001039cd388 _CF_forwarding_prep_0 + 120
5 Foundation 0x00000001032eaa75 _encodeObject + 1120
6 Foundation 0x0000000103326bf5 + [NSKeyedArchiver archiveRootObject:toFile:] + 241

当我读到这个时,当类是通用类时,Swift无法调用encodeWithCoder的实现。它是否正确 ?我怎样才能解决这个问题,以便在泛型类上使用NSCoding?

解决方案

与Objective-C不兼容。 NSCoder的所有东西都发生在Objective-C中,它不能再访问你的类。



请注意,还有其他一些使类为通用的结果。例如,如果您要添加description属性,则还会收到编译时错误:

  //错误:'@objc'获取非'@ objc'属性
覆盖var description:String {
returnFoo:\(bar)
}


I am having trouble with generic classes and NSCoding in Swift (XCode beta 5). Specifically, this example code works nicely:

class Foo : NSObject, NSCoding
{
    let bar: String
    init(bar: String){
        self.bar = bar;
    }

    func encodeWithCoder(aCoder: NSCoder!){
        aCoder.encodeObject(bar, forKey: "bar")
    }
    required init(coder aDecoder: NSCoder!){
        self.bar = aDecoder.decodeObjectForKey("bar") as String
        super.init()
    }


}

let foo = Foo(bar: "hello, world")

NSKeyedArchiver.archiveRootObject(foo, toFile: "test.dat")

However, when I try the same code, and add a generic parameter; when I try to encode the object; I get a 'unrecognized selector sent to instance' error:

class Foo<T> : NSObject, NSCoding
{
    let bar: String
    init(bar: String){
        self.bar = bar;
    }

    func encodeWithCoder(aCoder: NSCoder!){
        aCoder.encodeObject(bar, forKey: "bar")
    }
    required init(coder aDecoder: NSCoder!){
        self.bar = aDecoder.decodeObjectForKey("bar") as String
        super.init()
    }


}

let foo = Foo<String>(bar: "hello, world")

NSKeyedArchiver.archiveRootObject(foo, toFile: "test.dat")

Here is the error details and stack trace:

[_TtC6SafeId14ArrayContainer00007F8893418E58 encodeWithCoder:]: unrecognized selector sent to instance 0x7f8890ee4080
2014-08-16 10:43:54.632 SafeId[1778:32501] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_TtC6SafeId14ArrayContainer00007F8893418E58 encodeWithCoder:]: unrecognized selector sent to instance 0x7f8890ee4080'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000103a6e3e5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010371e967 objc_exception_throw + 45
    2   CoreFoundation                      0x0000000103a754fd -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x00000001039cd5ff ___forwarding___ + 495
    4   CoreFoundation                      0x00000001039cd388 _CF_forwarding_prep_0 + 120
    5   Foundation                          0x00000001032eaa75 _encodeObject + 1120
    6   Foundation                          0x0000000103326bf5 +[NSKeyedArchiver archiveRootObject:toFile:] + 241

As I read this, Swift is unable to call the implementation of encodeWithCoder when the class is generic. Is this correct ? How can I work around this in order to use NSCoding on generic classes ?

解决方案

The moment you make the class generic, it becomes non-compatible with Objective-C. The NSCoder stuff all happens in Objective-C which can no longer access your class.

Note there are other consequences of making the class generic as well. For example, if you were to add a description property, you'll also get a compile-time error:

// Error: '@objc' getter for non-'@objc' property
override var description: String {
    return "Foo: \(bar)"
}

这篇关于如何在Swift中的泛型类上实现NSCoding?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆