iOS 内存泄漏与 nib

Posted

技术标签:

【中文标题】iOS 内存泄漏与 nib【英文标题】:iOS Memory leak with nib 【发布时间】:2018-02-15 14:31:00 【问题描述】:
class CView: UIView 

    // MARK: - class

    class func nibView(frame: CGRect, assertion: Assertion?,contentReference: ContentReference?, delegate : AssertionViewDelegate? = nil) -> CView 
        let view =  UINib(nibName: "CView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! CView // LEAK
        view.delegate = delegate
        if let assertion = assertion 
            view.configure(for: assertion, contentReference: contentReference)
        
        return view
    
    

在 UITableViewCell 中,我在 init 中添加了这个视图

func initializeViews()
 if cview == nil 
    self.isOpaque = true
    let view = CView.nibView(frame: CGRect(x: 0, y: 0, width: Int(self.bounds.width), height: 0), assertion: nil, contentReference: nil)
    self.contentView.addSubview(view)
    self.cview = view

    self.cview.translatesAutoresizingMaskIntoConstraints = false
    self.cview.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor).isActive = true
    self.cview.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor).isActive = true
    self.cview.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true
    self.cview.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true




func configureAssertion()
    initializeViews()
    assertionView.tag = self.tag
   self.cview.configure() // configure with model

这会造成泄漏 - let view = UINib(nibName: "CView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! CView // 泄漏

I have edited, checking for nil before assigning. And I am calling initializeViews inside configure. But still seeing the leak.

【问题讨论】:

你的问题是什么?另外,您认为为什么会造成泄漏? 仪器泄漏分析显示此处存在内存泄漏。 @mag_zbc 单元格被重复使用...如果您每次请求单元格时都调用initializeViews(),看起来您正在添加另一个子视图每次。 【参考方案1】:

您的解决方案看起来很奇怪。通常,您通过注册 UITableViewCell 并将其出列来创建它:

// in your UIViewController class
func viewDidLoad() 
    super.viewDidLoad()
    // a) register a cell defined by nib
    tableView.register(UINib(nibName: "MyCellNibName", bundle: Bundle.main), forCellReuseIdentifier: "MyCellIdentifier")
    // b) register a cell defined by code
    tableView.register(MyCellClassName.cellClass, forCellReuseIdentifier: "MyCellIdentifier")


// in your tableView's datasource implementing class (maybe your UIViewController class)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellIdentifier", for: indexPath) as! MyCellClassName
    // configure cell
    return cell

可以在// configure cell 部分的 contentView 中添加子视图,但您必须确保之前没有添加它。请注意,dequeueReusableCell 可能会为您提供您已经使用过一次并滚动到视线之外的单元格(因此它可以被系统重用)。

在任何情况下,在 UITableViewCell init 中添加子视图都是完全错误的,并且违反了可重用单元格的设计。

您没有添加所有代码,因此请检查 CView::delegate 是否也被定义为弱。

另请注意:最好避免在任何 init 中使用功能。初始化对象应该很快。从架构的角度来看,除了在那里分配依赖关系之外,没有理由做更多的事情。从您的班级用户的角度来看,如果一个简单的 YourClass(..) 已经产生了一些魔力,那是完全出乎意料的。

【讨论】:

感谢您的回复。我已经编辑了代码,请检查,但仍然看到泄漏。

以上是关于iOS 内存泄漏与 nib的主要内容,如果未能解决你的问题,请参考以下文章

可插拔自定义视图 Nibs (Nib-in-a-Nib):内存泄漏 - 为啥?

iOS XML Parser 内存泄漏与 KissXML

内存泄漏与溢出

iOS 或 MonoTouch 中的固有内存泄漏?

使用 Android Studio 检测内存泄漏与解决内存泄漏问题

内存溢出和内存泄漏分别是啥意思?