Swift class 属性在由 Objective C 代码构造时未初始化
Swift class properties not initialized when constructed by Objective C code
我正在尝试在 Swift 3 中创建一个 class 来实现 Cordova 插件。我有这座建筑和 运行,但只要访问 class 的任何属性,应用程序就会崩溃。我尝试了两种初始化 class:
的方法
@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
class 包含一条评论,指出 initWithWebViewEngine
不应被覆盖(实际上我似乎 able覆盖此方法,因为虽然它在 CDVPlugin.m
文件中声明,但在 CDVPlugin.h
中未提及,因此 Swift 编译器似乎不知道它),但是相反,初始化代码应该放在一个名为 pluginInitialize
的方法中。但是,如果我这样做,我会收到编译器错误 ("Class DSFMediaCentre has no initializers").
此外,如果我将我的 init()
方法放回去并将其设置为调用 pluginInitialize()
,如下所示:
override init () {
super.init(); // necessary otherwise next line is an error
pluginInitialize();
}
override func pluginInitialize() {
players = [:];
}
然后错误变为 "Property 'self.players' not initialized at super.init call"。
如何使这个 class 正确初始化?
语言要求的严格初始化系统与您正在使用的框架使用的过程不匹配。
Swift 要求 a) 将属性初始化为对象构造的一部分,以及 b) 将构造链接到类型的超类型。但是 CDVPlugin
类型正在代表您进行构造;你没有能力定制它。 (这在 ObjC 中更有意义,因为它没有与 Swift 相同的编译时限制。)
这种情况类似于从 nib 文件中解压对象。在那种情况下,因为构建对象的是 nib 加载系统,所以您无法自定义初始化程序。您的类型将始终由 init(coder:)
构造。在某种意义上,您的初始化点进一步向下移动,到 awakeFromNib()
,除此之外,这强制将存档中其他对象的出口声明为可选的,通常隐式解包。
相同的解决方案在这里应该对您有用。您应该将 pluginInitialize()
视为您的初始化点。然后该语言要求属性是可选的,因为它们不会在 its 初始化点填充。因此,使 属性 成为 IUO:
@objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players :[UUID:DSFPlayerHandler]!
override func pluginInitialize() {
players = [:];
}
}
一切都会好起来的。
另一个解决方案是使用 lazy 关键字
lazy var players :[UUID:DSFPlayerHandler] = [:]
因此,您无需在初始化程序中初始化玩家,但仍要确保玩家始终不可为空
我正在尝试在 Swift 3 中创建一个 class 来实现 Cordova 插件。我有这座建筑和 运行,但只要访问 class 的任何属性,应用程序就会崩溃。我尝试了两种初始化 class:
的方法@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
class 包含一条评论,指出 initWithWebViewEngine
不应被覆盖(实际上我似乎 able覆盖此方法,因为虽然它在 CDVPlugin.m
文件中声明,但在 CDVPlugin.h
中未提及,因此 Swift 编译器似乎不知道它),但是相反,初始化代码应该放在一个名为 pluginInitialize
的方法中。但是,如果我这样做,我会收到编译器错误 ("Class DSFMediaCentre has no initializers").
此外,如果我将我的 init()
方法放回去并将其设置为调用 pluginInitialize()
,如下所示:
override init () {
super.init(); // necessary otherwise next line is an error
pluginInitialize();
}
override func pluginInitialize() {
players = [:];
}
然后错误变为 "Property 'self.players' not initialized at super.init call"。
如何使这个 class 正确初始化?
语言要求的严格初始化系统与您正在使用的框架使用的过程不匹配。
Swift 要求 a) 将属性初始化为对象构造的一部分,以及 b) 将构造链接到类型的超类型。但是 CDVPlugin
类型正在代表您进行构造;你没有能力定制它。 (这在 ObjC 中更有意义,因为它没有与 Swift 相同的编译时限制。)
这种情况类似于从 nib 文件中解压对象。在那种情况下,因为构建对象的是 nib 加载系统,所以您无法自定义初始化程序。您的类型将始终由 init(coder:)
构造。在某种意义上,您的初始化点进一步向下移动,到 awakeFromNib()
,除此之外,这强制将存档中其他对象的出口声明为可选的,通常隐式解包。
相同的解决方案在这里应该对您有用。您应该将 pluginInitialize()
视为您的初始化点。然后该语言要求属性是可选的,因为它们不会在 its 初始化点填充。因此,使 属性 成为 IUO:
@objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players :[UUID:DSFPlayerHandler]!
override func pluginInitialize() {
players = [:];
}
}
一切都会好起来的。
另一个解决方案是使用 lazy 关键字
lazy var players :[UUID:DSFPlayerHandler] = [:]
因此,您无需在初始化程序中初始化玩家,但仍要确保玩家始终不可为空