这是这个问题的后续。在这个例程中,
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,所以我想这可能就是问题所在;但我并不直观地知道可能出了什么问题,而且我尝试了多种策略来调试这个问题。让我最接近查明问题的是我在这里展示的内容,我可以在一行中找到它;但这对我来说似乎没什么问题......我错过了一些明显的东西吗?
@Larme 似乎走在正确的轨道上:我最终追踪到视图层的子层设置为 nil 的那一行。这就是问题所在。迭代子层(如果存在)并将它们从父层中单独删除会导致崩溃消失。
同样的问题出现在第二个视图中,也是一个 WKWebView,应用相同的解决方案导致了类似的崩溃。在这两种情况下,错误消息完全没有帮助。在第二种情况下,我只是注释掉了与子层相关的所有代码,一切工作正常。我怀疑这可能会在稍后阶段导致问题,当我需要使用其他子层信息更新视图时,但我现在无法测试它。
我现在正在旅行,无法访问我的原始项目,很抱歉没有代码显示;但是通过层的子层的基本迭代应该不会太难计算。