Search code examples
iosswiftuitableviewuiviewcontrollerswift5

Setting tableView datasource is causing app to crash


I am trying to create a table view with custom cells however whenever i Incorporate the datasource in the viewcontroller the app crashes, i know its this thats crashing the app beacuse when i comment out EventsList.EventsList_Table.datasource = self the app runs but the custom cells dont show i have also tried inherting from just UITableViewController but this also crashes the app or at least doesnt load and shows a black screen.

CustomCell.swift

class CustomCell: UITableViewCell {



override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    
    self.layer.masksToBounds = false
    self.backgroundColor = .white
    self.layer.shadowOpacity = 0.15
    self.layer.shadowRadius = 6
    self.layer.shadowColor = UIColor.lightGray.cgColor
    self.layer.cornerRadius = 6

    
}

override func layoutSubviews() {
    super.layoutSubviews()
    
    self.frame = self.frame.inset(by: UIEdgeInsets(top: 15, left: 10, bottom: 15, right: 10))
    
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}

EventsListViewController.swift

class EventsListViewController: UIViewController , UITableViewDataSource, UITableViewDelegate {

var ListView: EventsListView!

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = .white
        ListView = EventsListView(frame: CGRect(x: 0, y: 0, width: screenSize().width, height: screenSize().height))
        ListView.EventsList_Table.register(CustomCell.self, forCellReuseIdentifier: "EventsCell")
        ListView.EventsList_Table.separatorStyle = UITableViewCell.SeparatorStyle.none
        ListView.EventsList_Table.delegate = self
        ListView.EventsList_Table.dataSource = self
    self.view.addSubview(ListView)
}

func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    
    }

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let Cell =  ListView.EventsList_Table.dequeueReusableCell(withIdentifier: "EventsCell", for : indexPath) as! CustomCell
            Cell.selectionStyle = .none
            Cell.layoutSubviews()
        return Cell
}

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 5
}

}

This is the code for the view if this is any help at diagnosing the problem

class EventsListView: UIView {


var Events_Title: UILabel = {
    var Title = UILabel()
    Title.translatesAutoresizingMaskIntoConstraints = false
    Title.textColor = UIColor(red: 70/256, green: 56/256, blue: 83/256, alpha: 1.0)
    Title.textAlignment = .left
    Title.font = UIFont(name: "GTEestiDisplay-Medium", size: 36)
    Title.text = "Events"
    return Title
}()

var EventsList_Table: UITableView = {
    var Table = UITableView()
    Table.translatesAutoresizingMaskIntoConstraints = false
    Table.backgroundColor = .white
    return Table
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    
    self.addSubview(Events_Title)
    
    Events_Title.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
    Events_Title.topAnchor.constraint(equalTo: self.topAnchor, constant: 50).isActive = true
    Events_Title.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 30).isActive = true
    
    self.addSubview(EventsList_Table)
    
    EventsList_Table.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
    EventsList_Table.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.9).isActive = true
    EventsList_Table.topAnchor.constraint(equalTo: Events_Title.bottomAnchor, constant: 25).isActive = true
    
    
    
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}

Solution

  • You are causing your app to hang in an infinite loop because you are setting your cell's frame in layoutSubviews. Setting the frame will invalidate the cell's layout and cause layoutSubviews to be called again, where you set the frame and so on.

    Commenting the line

    self.frame = self.frame.inset(by: UIEdgeInsets(top: 15, left: 10, bottom: 15, right: 10))
    

    prevents the infinite loop.

    I strongly suggest that you adopt auto layout through constraints consistently throughout your app.

    When using constraints you should use the leading and trailing anchors rather than left and right as this will enable your app to accomodate right-to-left locales automatically. Only use left and right when you need something laid out on the left or right regardless of locale.