0
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
    }
    }

Inside UITableViewCell I add this view in 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
}

This creates a leak - let view = UINib(nibName: "CView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! CView // LEAK

I have edited, checking for nil before assigning. And I am calling initializeViews inside configure. But still seeing the leak.
Ankish Jain
  • 11,305
  • 5
  • 36
  • 34

1 Answers1

1

Your solution looks very strange. Typically you create a UITableViewCell by register it and dequeue it like that:

// 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
}

It's possible to add a subview to the contentView in the // configure cell part, but you have to ensure it's not already added before. Note that dequeueReusableCell may give you cells you already used once and scrolled out of sight (so it can be reused by system).

In any case adding subviews in UITableViewCell init is completely wrong and against the design of reusable cells.

You didn't added all code, so please check that CView::delegate is defined weak too.

Also note: It's good practice to avoid functionality inside of any init. Initializing an object should be fast. From architectural perspective there is no reason to do more than only assigning dependencies there. And from perspective of a user of your class it's completely unexpected if a simple YourClass(..) already does some magic.

ObjectAlchemist
  • 1,109
  • 1
  • 9
  • 18