【发布时间】:2018-10-22 17:14:51
【问题描述】:
我一直在开发一个没有情节提要的新应用。一切都很顺利,直到我用 Instruments 测试了我的应用程序:每次我将字符串分配给标签时,它都会泄漏。当我使用故事板时,我没有这样的泄漏。
我已阅读以下资源以找到答案:
Instruments show "_NSContiguousstring" memory leak when scrolling UITableView
- UILabel and memory leak
- Generating UILabel inside a UIView / Memory leak
最流行的观点是这是一个 Instruments 错误,但对我来说这似乎是一个太明显的方法。
泄漏在一个空的应用程序中重现。在根视图控制器中:
class ViewController: UIViewController {
var label: UILabel?
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel()
view.addSubview(label!)
var textForLabel: String? = "Hello"
label?.text = textForLabel
//attempt to free the memory
textForLabel = nil
label = nil
//EDIT: added after @J.Doe and @Sh-Khan answers, but it's still leaking
label.removeFromSuperview()
}
}
在真实设备 (iPhone SE 11.2) 上的 Instruments 中测试此应用时,我看到以下内容:
当我单击 _NSContiguousString 时,我看到 [UILabel setText:] 中出现内存泄漏。
我尝试将标签设置为弱,但是当我尝试将其添加为子视图时它变为 nil。
所以,我的问题是:
- 现在和将来如何消除这种内存泄漏?
- 出于这个原因,我应该只在 .xib/.storyboard 文件中创建 UI 元素吗?
我是 iOS 开发的新手,所以我认为我遗漏了一些明显的东西。我将非常感谢任何帮助或建议。
编辑:根据@Sh-Khan 和@J.Doe 的回答(非常感谢你们!),我添加了label.removeFromSuperview(),但仍然存在泄漏。
EDIT2:在@J.Doe 的帮助下,我了解到 UILabel 通过调用removeFromSuperview 并将其设置为 nil 从内存中释放。 Instruments 中的内存泄漏仍然存在,但我将他的回答标记为已接受,因为这是我想知道的。
PS:根据讨论,在阅读了NSString retain count 之后,我认为内存泄漏的原因可能是我使用了无法释放的字符串文字。
【问题讨论】:
-
如果将 var 语句移动到 viewDidLoad 中会发生什么?如果您仍然有泄漏,那么它可能不是来自标签,因为它会在函数结束时被取消初始化。
-
@Zyntx 谢谢!是的,根据 Instruments 的说法,泄漏就在那里。但是应用程序中没有任何代码,除了我在上面发布的(以及 AppDelegate 将 rootViewController 设置为窗口)。一个几乎是空的应用程序中怎么会有任何泄漏?我很困惑。
-
你可以将 textForLabel 设置为 let 吗? -- 让 textForLabel: String = "Hello"
-
@Zyntx 是的,谢谢!我也试过了。事实上,这不是 UILabel 错误,事实证明:它是 Swift._NSContiguousString 泄漏(1 泄漏 48 字节),而且只有一次。我不确定,但我猜测泄漏的原因可能是与 NSString 桥接(我还看到堆栈跟踪顶部的 [_SwiftNativeNSStringBase retain])。你觉得会是这样吗?
-
希望,是吗?!老实说,我有限地使用它来处理不良情况,并且不会抓住这个。
标签: ios swift memory-leaks uilabel