这个 Swift iPad 崩溃日志是啥意思? [复制]
Posted
技术标签:
【中文标题】这个 Swift iPad 崩溃日志是啥意思? [复制]【英文标题】:What does this Swift iPad crash log mean? [duplicate]这个 Swift iPad 崩溃日志是什么意思? [复制] 【发布时间】:2017-02-24 16:45:22 【问题描述】:应用程序在符合 9.3+ 部署目标的每台设备上都能正常运行除了 iPad2。网址很好。适用于每部 iPhone 和所有其他 iPad。崩溃发生在物理 iPad2 和模拟器 iPad2 ios 9.3 上。
doc.save(to: target, for: .forCreating, completionHandler: (success) in
if (success)
print("Save succeeded")
else
print("Save failed")
)
这是崩溃的地方。到达这一行的断点,不要到达完成处理程序中的断点或打印。同样,只有 iPad 的一种型号。
崩溃日志在我头上。这对你们中的任何人都有意义吗?谢谢。
编辑:扩展崩溃日志
【问题讨论】:
当您打开 Address Sanitizer 或 Zombie Objects(就像您在发布此问题之前应该有一样)时,您看到了什么? 很抱歉没有做我应该做的,但我不知道地址消毒剂或僵尸对象是什么。在此之前从未听说过它们,所以不知道打开/关闭它们。现在将尝试弄清楚它们是什么。 我有点生硬,但我确实想强调 Apple 提供的令人难以置信的工具。objc_retain
或 objc_release
或任何类似的保留/释放主题调用中的崩溃表明内存管理不善。在 Edit Scheme...->Run->Diagnostics 选项卡中启用 Zombie Objects 是一个不错的起点。注意:僵尸是 Cocoa 表达“悬空指针”的方式。
:) 我得到了令人难以置信的工具,尽管有时你甚至不知道它们的存在,直到你第一次遇到这种情况。 Swift 的内存使用是有道理的。我得到“悬空指针”是/c 我在 80 年代使用 C 和 MPW。但是这个对 doc.save 的调用是从 Swift 发出的,它显然调用了我没有编写的 objc 代码,这就是我迷路的地方。打开 AS 和 ZO,但还没有弄明白结果如何。确实有继续进行的计划(消除保存代码直到什么都没有......消除过程)。令人困惑的是,这只是一个 iOS 版本上的一个模型。
这里有一些猜测......它正在创建一个块并试图捕获一些对象。该对象已被释放,因此,retain
尝试引用了无效地址。你试过僵尸的建议吗? (是否有任何与UIDocument
关联的委托类型对象?调用doc.save
的控制器是否仍然有效?)
【参考方案1】:
tl;dr: 这是 Swift 数据类型中的一个错误。解决方案:在你的 UIDocument contents(forType:)
实现中,改变这个:
return data
到这里:
return NSData(data:data)
更多信息:请注意,仅将 data
转换为 NSData 无济于事:
return data as NSData
这并没有让我们更进一步,因为问题在于桥接。我们已经桥接到 NSData 并且没有帮助。您必须创建一个不是 Swift Data 对象的全新对象。
更多信息:对于前来并希望对此进行测试的后代,可以按如下方式可靠地重现崩溃。创建一个新的 Single View 项目,像往常一样使用应用程序委托和 ViewController。在 ViewController.swift 文件中,输入:
import UIKit
class WhatsUpDoc: UIDocument
var array = [String]()
override func load(fromContents contents: Any, ofType typeName: String?) throws
override func contents(forType typeName: String) throws -> Any
let data = NSKeyedArchiver.archivedData(withRootObject: array)
return data // comment out this line to avoid the crash
return NSData(data:data)
class ViewController: UIViewController
var doc : WhatsUpDoc?
override func viewDidLoad()
super.viewDidLoad()
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let baseURL = documentsDirectory.appendingPathComponent("Untitled")
let doc = WhatsUpDoc(fileURL: baseURL)
self.doc = doc
self.doc!.save(to:self.doc!.fileURL, for: .forCreating)
将您的项目配置为具有 9.0 的部署目标,并确保您手头有 9.0 模拟器 SDK。在 Window > Devices 中,给自己一个 iPad 2 模拟器。将该模拟器设置为项目的目的地。跑,然后崩溃。注释掉说注释掉的那一行,不要崩溃。
分析后问答:
等等,到底是什么错误?您不是说不能将 Swift Data 对象写入磁盘,是吗?
不,这与 UIDocument 文件保存期间写入的特殊线程性质有关。请注意,我们正在后台线程中崩溃(OP 屏幕截图中的线程 10 或 11)。而我们正在崩溃的in 是SwiftNSData
的一个方法,它是由Swift Data 包装的NSData。我们试图在这个后台线程上枚举数据的字节,但我们不能;大概这在某些设备类型上不是线程安全的,即 32 位设备。我的解决方案是彻底摆脱 Swift Data。
好的,事实证明这个错误是已知的;答案在这里给出:https://***.com/a/41163395/341994 那怎么样?
好的,但我在回答当前问题时独立解决了这个问题。直到后来,当我想到进行搜索时,我才发现其他问题和答案。因此,我已将当前问题标记为重复,但出于历史目的,我将我的答案留下,尤其是。因为它提供了一个明确的测试用例(另一个问题没有)。
顺便说一句,我不知道为什么使用NSMutableData(data:)
会比我使用NSData(data:)
的解决方案更好,但这是Apple 所说的,所以让我们把它当作福音。
【讨论】:
谢谢你,马特。我在很大程度上理解您的解释和您找到并链接的线程所讨论的解决方案,并已验证它解决了我的问题,至少在模拟器上。接下来会交给测试人员。感谢您和这个社区的帮助。 我知道你会喜欢的!我仍然认为,与其只是删除您未回答的内容,不如将该内容移到原始问题中,因为这对于允许我测试、重现和解决该错误至关重要。如果你不想做,我很乐意为你做,但我不想在没有你允许的情况下做这么大的修改。 我很高兴代码很有帮助。您的答案是孤立的。我怀疑我的代码只会使线程的阅读复杂化。真正重要的是人们可以快速找到问题的解决方案(以及一个原因,如果他们关心的话),并且接受的答案明确地提供了这一点。在它持续的时候是一个很好的脑筋急转弯。干杯。以上是关于这个 Swift iPad 崩溃日志是啥意思? [复制]的主要内容,如果未能解决你的问题,请参考以下文章