首页 文章

将文本分配给UILabel(iOS,Swift 4,XCode9)时内存泄漏

提问于
浏览
4

我一直在开发一款没有故事板的新应用 . 一切顺利,直到我用仪器测试我的应用程序:每次我将一个字符串分配给标签时它就泄露了 . 当我使用故事板时,我没有那样的泄漏 .

我已阅读以下资源以找到答案:

最流行的观点是,这是一个仪器错误,但对我来说它看起来是一个太明显的方法 .

泄漏在空的应用程序中重现 . 在根视图控制器中:

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)上的仪器中测试此应用程序时,我看到以下内容:

enter image description here

当我点击_NSContiguousString时,我发现内存泄漏出现在[UILabel setText:]中 .

enter image description here

我试图将标签设置为弱,但是当我尝试将其添加为子视图时它变为零 .

所以,我的问题是:

  • 如何才能消除现在和未来的内存泄漏?

  • 我应该仅在.xib / .storyboard文件中创建UI元素吗?

我是iOS开发的新手,所以我认为我缺少一些明显的东西 . 我将非常感谢任何帮助或建议 .

编辑:根据@Sh-Khan@J.Doe答案(非常感谢你们!),我添加了 label.removeFromSuperview() ,但仍然存在泄漏 .

编辑2:在@ J.Doe的帮助下,我了解到UILabel通过调用 removeFromSuperview 从内存中释放并在之后将其设置为nil . 仪器中的内存泄漏仍然存在,但我接受了他的回答,因为这是我想知道的 .

PS:根据讨论,在阅读了有关NSString retain count之后,我认为内存泄漏的原因可能是因为我使用了无法发布的字符串文字 .

2 回答

  • 1

    也许我错了,但我想这个:

    弱不会增加参考计数器 . 因此,将对象标签分配给弱var标签是没有意义的 . 这是因为弱var标签将为nil,因为您创建的对象没有任何引用(因此它将取消初始化)

    让我们计算您的代码中有多少引用到您创建的对象Label .

    label = UILabel() // 1
    view.addSubview(label!) // 2
    var textForLabel: String? = "Hello"
    label?.text = textForLabel
    
    //attempt to free the memory
    textForLabel = nil
    label = nil // 1
    

    在视图中,您的对象标签还有1个引用 . 在你做label = nil之前,调用label?.removeFromSuperview() . 我想比你有0个引用 - >它会去掉 .

    编辑:

    将UILabel的以下子类添加到您的代码中:

    class MyLabel: UILabel {
        deinit {
            print("I am gone!")
        }
    }
    

    var label: UILabel? 更改为 var label: MyLabel?

    label = UILabel()label = MyLabel()

    并检查日志 . 你看到印刷品“我走了!”?

    Edit2:打印出“我走了!”在一个空项目中只有代码:

    import UIKit
    
    class ViewController: UIViewController {
    
        var label: MyLabel?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            label = MyLabel()
            view.addSubview(label!)
            let textForLabel: String? = "Hello"
            label?.text = textForLabel
    
            //EDIT: added after @J.Doe and @Sh-Khan answers, but it's still leaking
            label?.removeFromSuperview()
            label = nil
    
    
        }
    }
    
    class MyLabel: UILabel {
        deinit {
            print("I am gone!")
        }
    }
    
  • 2

    第一次设定

    textForLabel = nil
    

    不会删除或使标签文本为零,因为标签已经复制了它

    第二个设定

    label = nil
    

    你还不够

    label.removeFromSuperview()
    

相关问题