[NSDecimalNumber 保留]:消息发送到已释放实例 0x174222220,但为啥呢?
Posted
技术标签:
【中文标题】[NSDecimalNumber 保留]:消息发送到已释放实例 0x174222220,但为啥呢?【英文标题】:[NSDecimalNumber retain]: message sent to deallocated instance 0x174222220, but why?[NSDecimalNumber 保留]:消息发送到已释放实例 0x174222220,但为什么呢? 【发布时间】:2017-01-03 15:37:40 【问题描述】:我似乎遇到了这个错误。
*** -[NSDecimalNumber retain]: message sent to deallocated instance 0x174222220
我第一次运行应用程序时,代码执行良好,但如果我回到那个 VC,应用程序会崩溃并显示上面的消息。我做了一些研究,我认为这意味着一些 NSDecimal 是如何发布的。这很奇怪,因为我还有 3 个其他小数的设置方式完全相同。
小数点存储在 Core Data 中,然后在我的 VC 中的 cellForIndexAt 方法中设置为标签。
print("\(historyEntry.newAmount) new amount")
我第一次取回正确的金额。但是第二次或者如果我尝试移动表格视图,应用程序会因上面的消息而崩溃。什么会导致小数释放自己?
编辑
我有一个 CoreDataStack swift 文件,并且 managedContext 是这样创建的:
lazy var managedContext: NSManagedObjectContext =
return self.storeContainer.viewContext
()
我正在获取这样的对象:
// load the data
let fetchRequest: NSFetchRequest<Statement> = Statement.fetchRequest()
fetchRequest.predicate = NSPredicate(format:"person.name == %@ AND amountOwed >= 0", personName)
let sort = NSSortDescriptor(key: #keyPath(Statement.amountOwed), ascending: true)
fetchRequest.sortDescriptors = [sort]
positiveFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.managedContext, sectionNameKeyPath: nil, cacheName: nil)
do
try positiveFetchedResultsController.performFetch()
catch let error as NSError
print("Fetching error: \(error), \(error.userInfo)")
positiveFetchedResultsController.delegate = self
我认为将我正在使用的获取的对象传递给另一个 ViewController 并像这样访问它的属性:
print("\(historyEntry.changeAmount) change amount") // gives me back the correct amount that was saved evrytime.
这个属性在第一次之后崩溃
print("\(historyEntry.newAmount) new amount") // first time correct, after that error message from above.
编辑
这里是 CoreDataStack 类
import Foundation
import CoreData
class CoreDataStack
private let modelName: String
init(modelName: String)
self.modelName = modelName
lazy var managedContext: NSManagedObjectContext =
return self.storeContainer.viewContext
()
private lazy var storeContainer: NSPersistentContainer =
let container = NSPersistentContainer(name: self.modelName)
container.loadPersistentStores (storeDescription, error) in
if let error = error as NSError?
print("Unresolved error \(error), \(error.userInfo)")
return container
()
func saveContext ()
guard managedContext.hasChanges else return
do
try managedContext.save()
catch
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
【问题讨论】:
可以设置异常断点看看 我不确定我是否知道如何创建异常断点 您向已释放实例发送消息。这就是你的应用崩溃的原因 为什么会被释放? 你有一个正在被释放的对象的引用。这被称为“僵尸”。自从 Apple 引入 ARC(这是 Swift 的唯一选择)以来,这些就不太常见了。你有没有声明为不安全而不是弱的变量?通常 Swift 负责清零弱引用,所以你得到一个 nil 而不是僵尸。发布有关您的 NSDecimalNumbers 声明及其创建/发布方式的信息。 【参考方案1】:您的 NSDecimalNumber 属性的名称是什么?如果任何属性名称以“new”开头,则会混淆 ARC 并导致此类问题。
引用Apple's Introduction to ARC,
您不能为访问者指定以 new 开头的名称。这反过来 意味着你不能,例如,声明一个名字 除非您指定不同的 getter,否则以 new 开头。
【讨论】:
【参考方案2】:我会尝试确保在您重新进入 VC 时托管对象上下文没有被解除分配和重新分配。这可以解释为什么您的 MOC 会被释放。
除此之外,我会在 Product/Scheme/Edit Scheme/Run/Diagnostics 下启用“Zombie Objects”,看看是否提供了更多提示。
【讨论】:
如何检查托管对象上下文是否正在被释放?我确实启用了 Zombie Objects,没有太大帮助,只是告诉我 NSDecimal 对象已被释放。 它不会告诉您NSDecimalNumber
被释放的位置吗?任何有用的堆栈跟踪?关于被释放的 MOC,您应该检查您的代码以了解 - 也许您正在创建第二个 MOC 并将其分配给相同的引用 - 另外,请尝试记录其地址以查看它是否更改...以上是关于[NSDecimalNumber 保留]:消息发送到已释放实例 0x174222220,但为啥呢?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 ARC 中发送消息会导致保留周期警告,但属性集不会?
[UINavigationController 保留]:发送到已释放实例的消息