我正在尝试在Swift 3中创建一个类来实现Cordova插件。我有这个构建并运行,但只要访问该类的任何属性,应用程序就会崩溃。我尝试了两种初始化类的方法:
@objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players = [UUID:DSFPlayerHandler] ();
...
}
和
@objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players :[UUID:DSFPlayerHandler];
override init () {
players = [:];
}
...
}
但是,当使用我的players
属性时,结果是EXC_BAD_ACCESS异常,其地址看起来像空指针取消引用。
该对象是由Objective C代码创建的,这是一种我根本不熟悉的语言,但我认为这是创建它的行:
obj = [[NSClassFromString(className)alloc] initWithWebViewEngine:_webViewEngine];
CDVPlugin
类包含一条注释,指出initWithWebViewEngine
不应该被覆盖(事实上我似乎能够覆盖此方法,因为它虽然是在CDVPlugin.m
文件中声明,CDVPlugin.h
中没有提到它,因此Swift编译器似乎不知道它,而是初始化代码应该放在一个名为{{1的方法中相反。但是,如果我这样做,我会收到编译器错误(“类DSFMediaCentre没有初始值设定项”)。
此外,如果我重新使用pluginInitialize
方法并将其设置为init()
,请执行以下操作:
pluginInitialize()
错误然后更改为“属性'self.players'未在super.init调用中初始化。”
如何正确初始化此类?
答案 0 :(得分:1)
您在语言所需的严格初始化系统与您正在使用的框架所使用的过程之间存在不匹配。
Swift要求a)属性被初始化为对象构造的一部分,b)构造被链接到类型的超类型。但是init(coder:)
类型正代表您进行构建;你没有能力自定义它。 (这在ObjC中更有意义,因为它没有与Swift相同的编译时限制。)
这种情况类似于从nib文件中解压缩对象。在这种情况下,因为它是构造对象的笔尖加载系统,所以您无法自定义初始化程序。您的类型将始终由awakeFromNib()
构建。在某种意义上,您的初始化点会进一步向下移动到pluginInitialize()
,以及强制存档中其他对象的出口被声明为可选的,通常是隐式展开的。
同样的解决方案应该在这里使用。您应该将@objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players :[UUID:DSFPlayerHandler]!
override func pluginInitialize() {
players = [:];
}
}
视为初始化点。然后,该语言要求属性是可选的,因为它们未在其初始化点填充。因此,将属性设为IUO:
{{1}}
一切都应该好。
答案 1 :(得分:1)
另一个解决方案是使用lazy keyword
lazy var players :[UUID:DSFPlayerHandler] = [:]
所以,你不需要在初始化程序中初始化玩家,但仍然确保玩家总是不合法