首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >访问swift阵列时swift_isUniquelyReferenced_nonNull_native中的EXC_BAD_ACCESS

访问swift阵列时swift_isUniquelyReferenced_nonNull_native中的EXC_BAD_ACCESS
EN

Stack Overflow用户
提问于 2020-04-03 15:01:35
回答 1查看 3.2K关注 0票数 6

问题所在

在编写单元测试和模拟NSTimer时,我看到了一个

代码语言:javascript
运行
复制
Exception: EXC_BAD_ACCESS (code=1, address=0x8)

内部

代码语言:javascript
运行
复制
swift_isUniquelyReferenced_nonNull_native

在这里访问数组invalidateInvocations (在func invalidate()中)时会出现这种情况。

代码语言:javascript
运行
复制
class TimerMock: Timer {

    /// Timer callback type
    typealias TimerCallback = ((Timer) -> Void)

    /// The latest used timer mock accessible to control
    static var  currentTimer: TimerMock!

    /// The block to be invoked on a firing
    private var block:        TimerCallback!

    /// Invalidation invocations (will contain the fireInvocation indices)
    var invalidateInvocations: [Int] = []

    /// Fire invocation count
    var fireInvocations:       Int   = 0

    /// Main function to control a timer fire
    override open func fire() {
        block(self)
        fireInvocations += 1
    }

    /// Hook into invalidation
    override open func invalidate() {
        invalidateInvocations.append(fireInvocations)
    }

    /// Hook into the timer configuration
    override open class func scheduledTimer(withTimeInterval interval: TimeInterval,
                                            repeats: Bool,
                                            block: @escaping TimerCallback) -> Timer {
        // return timer mock
        TimerMock.currentTimer = TimerMock()
        TimerMock.currentTimer.block = block
        return TimerMock.currentTimer
    }

}

有趣的是,如果我将invalidateInvocations更改为常规的Int,则可以在不发生任何崩溃的情况下访问它。

因为访问这个变量会导致EXC_BAD_ACCESS,所以我会假设数组已经被释放,但是我不明白这是怎么发生的。

演示

您可以在此存储库中查看完整的运行和崩溃示例(分支demo/crash)

https://github.com/nomad5modules/ArcProgressViewIOS/tree/demo/crash

只需执行单元测试,就会看到它崩溃。

问题是

这是怎么回事?我已经在其他项目中观察到了swift_isUniquelyReferenced_nonNull_native内部的崩溃,我很想完全理解这个失败的原因!那么,找出这里的问题所在的过程是怎样的呢?以及如何修复它?

独立复制项目

https://drive.google.com/file/d/1fMGhgpmBRG6hzpaiTM9lO_zCZwNhwIpx/view?usp=sharing

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-09 15:50:40

崩溃是由于未初始化的成员(它是NSObject而不是常规的swift类,因此需要显式的init(),但由于这是Timer,它具有半抽象的指定初始化器,因此不允许重写)。

解决方案是显式地设置missed ivar,如下所示。

使用Xcode11.4测试并处理测试项目。

代码语言:javascript
运行
复制
override open class func scheduledTimer(withTimeInterval interval: TimeInterval,
                                        repeats: Bool,
                                        block: @escaping TimerCallback) -> Timer {
    // return timer mock
    TimerMock.currentTimer = TimerMock()
    TimerMock.currentTimer.invalidateInvocations = [Int]()   // << fix !!
    TimerMock.currentTimer.block = block
    return TimerMock.currentTimer
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61006622

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档