【问题标题】:Swift class properties not initialized when constructed by Objective C code由 Objective C 代码构造时未初始化的 Swift 类属性
【发布时间】:2023-03-19 09:37:01
【问题描述】:

我正在尝试在 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(实际上我似乎无法能够重写此方法,因为虽然它在 @ 中声明987654327@ 文件,CDVPlugin.h 中没有提到它,所以 Swift 编译器似乎不知道它),而是应该将初始化代码放在一个名为 pluginInitialize 的方法中。但是,如果这样做,我会收到编译器错误(“Class DSFMediaCentre 没有初始化程序”)。

此外,如果我将 init() 方法放回原处并将其设置为调用 pluginInitialize(),如下所示:

override init () {
    super.init();    // necessary otherwise next line is an error
    pluginInitialize(); 
}
override func pluginInitialize() {
    players = [:];
}

然后错误变为“属性 'self.players' 未在 super.init 调用时初始化”。

如何让这个类正确初始化?

【问题讨论】:

  • 也许您使用的是 Swift 4,并且需要在从 Objective-C 访问的 class + ivars 前加上 @objc?
  • 不,我正在使用 swift 3。将其添加到问题中;还没看过swift 4呢。

标签: objective-c swift cordova swift3


【解决方案1】:

语言所需的严格初始化系统与您正在使用的框架使用的过程不匹配。

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 = [:];
    }
}

一切都会好起来的。

【讨论】:

    【解决方案2】:

    另一种解决方案是使用惰性关键字

       lazy var players :[UUID:DSFPlayerHandler] = [:]
    

    因此,您无需在初始化程序中初始化玩家,但仍要确保玩家始终不可为空

    【讨论】:

      猜你喜欢
      • 2020-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 2021-03-07
      • 2014-10-09
      • 2019-07-31
      • 1970-01-01
      相关资源
      最近更新 更多