Swift 中的奇怪崩溃,与将子层设置为 nil 相关

问题描述 投票:0回答:1

这是这个问题的后续。在这个例程中,

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    Tracker.track("getting row \(indexPath.row)")
    let ptv = tableView as? NovilloTableView
    if ptv!.uiType == .textTable {
        let gp = Projects.currentProject?.getPaths(type: PaletteView.getCurrentPane())
        GitPaths.currentGitPath = gp![indexPath.row]
//            NotificationCenter.default.post(name: NNames.updateWebText.nn(), object: nil)
        return
    }
    let svgs = Projects.currentProject!.getPaths(type : PaletteView.getCurrentPane())
    var gitPath = svgs[indexPath.row]
    Tracker.track("gitpath is \(gitPath)")
    var gitPaths = GitPaths.getMediaBoundingBoxes(paths: [gitPath])
    guard let pathArrays = gitPath.parseForRegBeziers() else { return }
    let rslt = pathArrays.0
    let regBeziers = pathArrays.1
    gitPath.boundingBox = gitPath.getBoundsParamsForPaths(src: regBeziers.isEmpty ? rslt : regBeziers)
    GitPaths.currentGitPath = gitPath
//        Tracker.track("sending notification")
    NotificationCenter.default.post(name: NNames.updateMedia.nn(), object: nil, userInfo: ["path" : gitPath])
    Tracker.track("completed didSelect")
    return
}

…我遵循的主线程逻辑路径是在底部以

Tracker.track("completed didSelect")
结束的路径。如果我执行通知调用,我会崩溃,并抛出以下信息:

libobjc.A.dylib`objc_msgSend:
    0x18002ec00 <+0>:   cmp    x0, #0x0
    0x18002ec04 <+4>:   b.le   0x18002ec6c               ; <+108>
    0x18002ec08 <+8>:   ldr    x14, [x0]
    0x18002ec0c <+12>:  and    x16, x14, #0x7ffffffffffff8
    0x18002ec10 <+16>:  mov    x15, x16
->  0x18002ec14 <+20>:  ldr    x10, [x16, #0x10]
    0x18002ec18 <+24>:  lsr    x11, x10, #48
    0x18002ec1c <+28>:  and    x10, x10, #0xffffffffffff
    0x18002ec20 <+32>:  and    w12, w1, w11
    0x18002ec24 <+36>:  add    x13, x10, x12, lsl #4
    0x18002ec28 <+40>:  ldp    x17, x9, [x13], #-0x10
    0x18002ec2c <+44>:  cmp    x9, x1
    0x18002ec30 <+48>:  b.ne   0x18002ec3c               ; <+60>
    0x18002ec34 <+52>:  eor    x17, x17, x16
    0x18002ec38 <+56>:  br     x17
    0x18002ec3c <+60>:  cbz    x9, 0x18002eea0           ; _objc_msgSend_uncached
    0x18002ec40 <+64>:  cmp    x13, x10
    0x18002ec44 <+68>:  b.hs   0x18002ec28               ; <+40>
    0x18002ec48 <+72>:  add    x13, x10, w11, uxtw #4
    0x18002ec4c <+76>:  add    x12, x10, x12, lsl #4
    0x18002ec50 <+80>:  ldp    x17, x9, [x13], #-0x10
    0x18002ec54 <+84>:  cmp    x9, x1
    0x18002ec58 <+88>:  b.eq   0x18002ec34               ; <+52>
    0x18002ec5c <+92>:  cmp    x9, #0x0
    0x18002ec60 <+96>:  ccmp   x13, x12, #0x0, ne
    0x18002ec64 <+100>: b.hi   0x18002ec50               ; <+80>
    0x18002ec68 <+104>: b      0x18002eea0               ; _objc_msgSend_uncached
    0x18002ec6c <+108>: b.eq   0x18002ec90               ; <+144>
    0x18002ec70 <+112>: and    x10, x0, #0x7
    0x18002ec74 <+116>: asr    x11, x0, #55
    0x18002ec78 <+120>: cmp    x10, #0x7
    0x18002ec7c <+124>: csel   x12, x11, x10, eq
    0x18002ec80 <+128>: adrp   x10, 232550
    0x18002ec84 <+132>: add    x10, x10, #0xa00          ; objc_debug_taggedpointer_classes
    0x18002ec88 <+136>: ldr    x16, [x10, x12, lsl #3]
    0x18002ec8c <+140>: b      0x18002ec10               ; <+16>
    0x18002ec90 <+144>: mov    x1, #0x0
    0x18002ec94 <+148>: movi   d0, #0000000000000000
    0x18002ec98 <+152>: movi   d1, #0000000000000000
    0x18002ec9c <+156>: movi   d2, #0000000000000000
    0x18002eca0 <+160>: movi   d3, #0000000000000000
    0x18002eca4 <+164>: ret    
    0x18002eca8 <+168>: nop    
    0x18002ecac <+172>: nop    
    0x18002ecb0 <+176>: nop    
    0x18002ecb4 <+180>: nop    
    0x18002ecb8 <+184>: nop    
    0x18002ecbc <+188>: nop   

根据 Stackoverflow 中的另一篇文章,当 Objective-C 需要可见的函数未用 @objc 标记时,就会出现该消息,但如您所见,这是(如下)。

一开始并没有发生这种情况,我也不知道为什么,但是通知调用的函数是这样的:

@objc func updateMedia(notification : Notification) {
    let path = (notification.userInfo?["path"] ??  GitPaths.currentGitPath!) as? GitPaths
    Tracker.track("sublayers: \(mediaDisplay!.layer.sublayers == nil)")
    mediaDisplay!.layer.sublayers = nil
    mediaDisplay!.mask = nil
//        Tracker.track("render beziers for \(path)")
//        path!.renderBeziers(tgt: mediaDisplay!, path : path) //, data:["style" : "media"])
//        refreshMediaInfo()
//        updateSelectedMedia( src : GitPaths.currentGitPath! )
//        return
}

我已经评论了大多数行,以查看在哪里可以引发崩溃,这就是行

mediaDisplay!.layer.sublayers = nil
。如果我注释掉这一行,该函数将正确执行;如果我包含它,它会崩溃,但不会在该行执行时崩溃;整个函数将返回,并且崩溃发生在首先调用通知的函数的末尾,也就是本文顶部的函数。
Tracker.track()
只是一种以格式化方式打印消息的方法,并不是对此的贡献者;所以基本上,通知返回后,不会发生任何其他事情;如果我单步执行,它会到达函数的最后一个括号,然后将控制权返回给用户。

我已经检查了对象

mediaDisplay
是否存在,它确实存在,因为它实际上正在执行所要求的操作;当未注释掉时,未注释的
path!.renderBeziers(tgt: mediaDisplay!, path : path) 
行正在将一堆贝塞尔路径绘制到该视图中,正如崩溃后拍摄的屏幕截图所示,它已成功完成。换句话说,当我取消注释并运行相同的代码时,导致崩溃的行并不会阻止
path!.renderBeziers(tgt: mediaDisplay!, path : path)
后面的所有其他代码完成其工作。顺便说一句,调色板中的表格是启动这一切的对象。

视图上挂着一个大问号;它是 WKWebView 的子类,这是这里的一个很大的变化。我在这里使用它作为常规 UIView 功能,充当一堆 CAShapeLayers 的容器。这和以前一样,当它是 UIView 时。

更改的原因是我希望能够在与 CAShapeLayers 相同的视图中显示 html 内容,作为在屏幕上不同绘制元素之间交错 html 的一种方式;想想后面有深紫色形状、前面有浅色形状的文本。在此,我正在关注我提出的一个问题,该问题已在这里得到解答

无论如何,引用下一行中掩码设置为 nil 的容器不会导致崩溃;所以这似乎与 WKWebView 的层及其子层有关。它们存在,我已经检查过,但将它们设置为零似乎会以这种奇怪的方式炸毁它。

我确信我错过了一些东西;我以前没有使用过 WebViews,所以我想这可能就是问题所在;但我并不直观地知道可能出了什么问题,而且我尝试了多种策略来调试这个问题。让我最接近查明问题的是我在这里展示的内容,我可以在一行中找到它;但这对我来说似乎没什么问题......我错过了一些明显的东西吗?

ios swift notifications wkwebview layer
1个回答
0
投票

@Larme 似乎走在正确的轨道上:我最终追踪到视图层的子层设置为 nil 的那一行。这就是问题所在。迭代子层(如果存在)并将它们从父层中单独删除会导致崩溃消失。

同样的问题出现在第二个视图中,也是一个 WKWebView,应用相同的解决方案导致了类似的崩溃。在这两种情况下,错误消息完全没有帮助。在第二种情况下,我只是注释掉了与子层相关的所有代码,一切工作正常。我怀疑这可能会在稍后阶段导致问题,当我需要使用其他子层信息更新视图时,但我现在无法测试它。

我现在正在旅行,无法访问我的原始项目,很抱歉没有代码显示;但是通过层的子层的基本迭代应该不会太难计算。

© www.soinside.com 2019 - 2024. All rights reserved.