行代码在lldb`p`中工作,代码在托管单元测试中失败

时间:2018-04-02 02:53:35

标签: objective-c swift frameworks lldb djinni

我发现了很多关于NSArray element failed to match the Swift Array Element type错误的帖子。但是,我仍然无法让这个工作。 我怀疑问题与我制作的目标C框架绑定有关,而不是投射问题。其中,我不明白的一件事是为什么代码在lldb p指令内工作而不是在主机ios应用程序中执行的单元测试(我无法测试它,否则代码需要B- LE无法从iphone模拟器获得。)

class onceFirstMuseConnected: IXNMuseListener {
    let museManager: IXNMuseManager
    let callback: (_ muse: IXNMuse) -> Void

    init(museManager: IXNMuseManager, callback: @escaping (_ muse: IXNMuse) -> Void) {
        self.museManager = museManager
        self.callback = callback
        museManager.setMuseListener(self)
        museManager.startListening()
    }

    func museListChanged() {
        let muses: [IXNMuse] = museManager.getMuses()
        guard muses.count > 0 else {
            return
        }
        let _ = muses.first!.getName() // <<<< `muses.first` fails as well as any other
                                       //      kind of array's item access with "Fatal
                                       //      error: NSArray element failed to match the
                                       //      Swift Array Element type"
    }
}

奇怪的是,我能够使线路在lldb中工作,如下图所示。

lldb works

编辑:由于我有多个downvote,我很感激为什么lldb行在主要执行崩溃时在注释中起作用的解释。我认为lldb行如果是类型转换问题就不会起作用。我找到的相关问题都没有回答这个问题。我承认我是一个快速的/ objc新手,如果不是与objc-swift框架映射过程相关的问题,我可能不明白我不明白。

getMuses函数由djinni使用我编写的模块映射包装,以将专有的目标C框架绑定到swift。这是我写的模块图。我对其他函数绑定没有任何问题(参见注释)。删除[system]属性不会触发任何其他警告。

module Muse [system] {
    header "Muse.framework/Headers/Muse.h"
    export *
}

djinni产生的声明:

public func getMuses() -> [IXNMuse]

最初的objc声明:

 - (nonnull NSArray<IXNMuse *> *)getMuses;

由于框架是专有的,因此该定义不可用。

返回的指针不太可能为null或指出错误的内存地址,因为如果是这样,对截图中显示的对getName方法的lldb-made调用将无法给出正确的结果。

1 个答案:

答案 0 :(得分:1)

编辑回答

Muse.framework 静态框架。 XCTests构建在主机应用程序中嵌入的包中。在我的设置中,涉及3个目标:我开发的框架,测试的主机应用程序和XCTest包。

静态框架嵌入在目标二进制文件中使用的符号

为了避免重复的符号问题,静态框架应仅链接到目标框架**,而不是xctest包或测试主机应用程序,它通过链接目标框架来过渡链接符号。

为确保目标框架嵌入其静态链接框架依赖关系的所有符号, -force_load标志后跟静态依赖关系路径必须添加到目标框架链接选项(OTHER_LDFLAGS)

原始答案

积分转到OOPer以获取问题评论的帮助。

由于某种原因我不明白,我得到了我的IXNMuse类的双重定义。两个定义之间的快速冲突是我遇到NSArray element failed to match the Swift Array Element type错误的原因。

修复程序

当我执行以下程序时,问题消失了:

A。在测试以下代码时

let muses: NSArray = museManager.getMuses() as NSArray
let muse: IXNMuse = muses.firstObject! as! IXNMuse

我在运行时收到了

Could not cast value of type 'IXNMuse' (0x103cfa180) to 'IXNMuse' (0x103e965e0).

B。我有两个import Muse语句,一个在我的测试文件中,一个在我的框架目标源文件中。 从测试文件中删除import Muse语句(使用相关代码)。这样就可以通过删除双IXNMuse定义来传递测试。

C。我从测试目标的Muse.framework中删除了Link Binary with Libraries,因为它已经包含在我测试的框架目标中。我从测试文件中放回了import Muse语句(带有相关代码,因为我仍然需要它)我刚刚删除了。 即使在两个目标源文件中都进行双重Muse导入,测试仍然通过。

D。我将Muse.framework放回我测试目标的Link Binary with Libraries(我认为两个目标都链接相同的框架并不是一个错误具有三角形依赖性)。因此,我首先回到了一个类似于我所处的状态的状态。问题没有再出现,测试仍然通过。

结论

我仍然有点困惑,为什么我一开始就遇到这个问题。有可能我并没有完全处于相同的状态我虽然我在这个过程中做了一些事情,同时改变了我不记得的链接配置。