从 NSObject 派生时,Swift iOS 内存泄漏指示 XCode8
Posted
技术标签:
【中文标题】从 NSObject 派生时,Swift iOS 内存泄漏指示 XCode8【英文标题】:Swift iOS Memory Leak Indicated XCode8 when Derived from NSObject 【发布时间】:2016-10-14 13:44:10 【问题描述】:Xcode8 显示仪器和内存图存在内存泄漏。我已将其缩小到这一点:从 NSObject 派生会产生泄漏指示。我不知道为什么。
我需要一个 NSObject 以便稍后使用 @objc 指令。
存储在 mDict Dictionary 中的 Test 实例在 Xcode 中被指示为泄漏。
这是作为 ios Single-View-Application 项目在运行 iOS10.0 的 iPhone5s 模拟器中运行的
import Foundation
class Test: NSObject // <-- derived from NSObject produces leak indication below
static var cTest: Test! = nil
var mDict: [String : Test] = Dictionary<String, Test>()
static func test() -> Void
cTest = Test()
cTest.mDict["test"] = Test() // <-- alleged leak
class Test // <-- NOT derived from NSObject, NO leak indication
static var cTest: Test! = nil
var mDict: [String : Test] = Dictionary<String, Test>()
static func test() -> Void
cTest = Test()
cTest.mDict["test"] = Test() // <-- NO leak
// from AppDelegate didFinishLaunchingWithOptions
// ...
Test.test()
// ...
【问题讨论】:
尝试在NSObject
示例中将 mDict 声明为 weak var
。我怀疑在使用后没有释放 mDict 的情况下发生了一个强大的内存循环。
谢谢@Danoram。当我尝试得到“弱”时,可能仅适用于类和类绑定协议类型,而不是“字典swift 中的内存管理与类的目标 c 有点不同。比起class Test: NSObject
,你可能会错过这个特性。
如果您尝试class Test: AnyObject
,您必须解决您的问题。
或者尝试使用deinit
在您使用它的每一刻
class Test: NSObject // <-- using deinit
static var cTest: Test! = nil
var mDict: [String : Test] = Dictionary<String, Test>()
static func test() -> Void
cTest = Test()
cTest.mDict["test"] = Test() // <-- alleged leak
deinit
但最佳实践将其声明为 weak
变量,例如 weak var test: Test?
在您的情况下
【讨论】:
谢谢@Achron。是的。泄漏指示器不见了但是我需要从 NSObject 继承才能使用@@objc。当您从 AnyObject 继承时,这是不可能的。其他想法/解决方案? 也许如果你在对象上使用deinit
,你会解决的。如果仍然无法正常工作,请尝试使用init
。
谢谢@Achron。不幸的是 init() 和 deist 没有帮助。在我的示例中, deinit 永远不会被调用。泄漏仍然存在。
刚刚将这一行添加到答案中。尝试将变量声明为weak
谢谢@Achron。你的意思是 var mDict 作为弱 var mDict,对吧?之前的一张海报也提到了这一点。不幸的是,它会产生编译器错误。 (见上文。)如果理解正确,请告诉我,如果理解正确,正确的代码语法是什么?【参考方案2】:
这似乎已在 Xcode 发行版 8.2 (8C38) 中得到修复。不再显示泄漏。
【讨论】:
其实我还是发现了一个问题。【参考方案3】:这与原始问题基本相同。这是我有类似问题的测试代码。 YMMV。在 iPad air 上运行 iOS 10.1 版本 8.2 (8C38)
import UIKit
class Thing
class Test: NSObject
static let shared = Test()
var dictionary: [String: Thing] = [:]
func method()
dictionary = ["value": Thing()]
class ViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
Test.shared.method()
print("Leaky leaky... click on the memory visualizer to see issues.")
如果您删除 NSObject,问题就会消失。我为它的价值提交了一份雷达。
如果我作为命令行工具运行并使用命令行leaks
命令进行检查,我看不到问题。
【讨论】:
以上是关于从 NSObject 派生时,Swift iOS 内存泄漏指示 XCode8的主要内容,如果未能解决你的问题,请参考以下文章
没有在 NSObject 类 ios swift 中获取委托方法的回调
IOS - 啥是 Swift 字符类型的 ObjC NSObject 等价物?