iOS Swift create Table View and Custom Cell programmatically

iOS Swift create Table view programmatically
Displaying a list is one of the most important layout tools needed for any programming. This is where UITableView comes to help so that structured and organized data can be rendered and by customizing the UITableViewCell you gain full control of the individual row layout.

In this example we will create a UITableView with auto layout so that when you switch between portrait and landscape modes it renders the screen properly. Also we will create a custom Cell View for displaying our company data in multiple sections and rows. We are just using a JSON data string for input but in reality most of the time this data will come from a Web Service request.
iOS Swift create custom cell view programmatically

UITableView Controller Source


import UIKit

struct Company: Codable {
    var name: String
    var employees: [Employee]
}

struct Employee: Codable {
    var name: String
    var image: String
    var years: Int
    var salary: Double
}


class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    private var myTableView: UITableView!
    private var companies: [Company]!
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        self.navigationItem.title = "Main View"
        
        //get data for display, this can be WEB Service API as well
        companies = getCompanyData()
        
        myTableView = UITableView()
        myTableView.register(MyTableViewCell.self, forCellReuseIdentifier: "MyCell")
        myTableView.dataSource = self
        myTableView.delegate = self
        
        //for auto layout rendering
        myTableView.translatesAutoresizingMaskIntoConstraints = false
        
        //hide extra lines
        myTableView.tableFooterView = UIView()
        
        //add to layout
        self.view.addSubview(myTableView)
        
        //auto layout for the table view
        let views = ["view": view!, "tableView" : myTableView]
        var allConstraints: [NSLayoutConstraint] = []
        allConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[tableView]|", options: [], metrics: nil, views: views as [String : Any])
        allConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[tableView]|", options: [], metrics: nil, views: views as [String : Any])
        NSLayoutConstraint.activate(allConstraints)
        
        
    }
    
    //when user taps on the row
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("Company Selected: \(companies[indexPath.section].name)")
        print("Employee Selected: \(companies[indexPath.section].employees[indexPath.row].name)")
    }
    
    //no of sections for the list
    func numberOfSections(in tableView: UITableView) -> Int {
        return companies.count
    }
    
    //section heading
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        if section < companies.count {
            return companies[section].name
        }
        return nil
    }
    
    //number of rows for that section
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return companies[section].employees.count
    }
    
    //render the cell and display data
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyTableViewCell
        
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        
        let employee = companies[indexPath.section].employees[indexPath.row]
        cell.employeeImage.image = UIImage(named: employee.image)
        cell.employeeName.text = "\(employee.name)"
        cell.yearsInService.text = "\(employee.years) years in service"
        cell.salary.text = formatter.string(from: NSNumber(value: employee.salary))
        return cell
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
    }
    
    //get JSON data into object for display
    func getCompanyData() -> [Company] {
        
        var companies: [Company] = [Company]()
        let myJsonData = """
            [{
                    "name": "ABC Company",
                    "employees": [{
                            "years": 12,
                            "name": "Joe",
                            "image": "apple.png",
                            "salary": 110000
                        },
                        {
                            "years": 15,
                            "name": "John",
                            "image": "apple.png",
                            "salary": 150000
                        }
                    ]
                },
                {
                    "name": "XYZ Company",
                    "employees": [{
                        "years": 22,
                        "name": "Jake",
                        "image": "apple.png",
                        "salary": 220000.5
                    }]
                }
            ]
            """
        
        //Decode JSON Data String to Swift Objects
        if let jsonData = myJsonData.data(using: .utf8) {
            let decoder = JSONDecoder()
            do {
                companies = try decoder.decode([Company].self, from: jsonData)
                for company in companies {
                    print("===")
                    print(company.name)
                    for employee in company.employees {
                        print("---")
                        print(employee.name)
                        
                    }
                    
                }
                
            } catch {
                //do nothing
            }
            
            
        }
        
        return companies
        
    }
    
}

Custom Cell View Source


import UIKit

class MyTableViewCell: UITableViewCell {
    
    let employeeImage = UIImageView()
    let employeeName = UILabel()
    let yearsInService = UILabel()
    let salary = UILabel()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        employeeImage.translatesAutoresizingMaskIntoConstraints = false
        employeeName.translatesAutoresizingMaskIntoConstraints = false
        yearsInService.translatesAutoresizingMaskIntoConstraints = false
        salary.translatesAutoresizingMaskIntoConstraints = false
        
        contentView.addSubview(employeeImage)
        contentView.addSubview(employeeName)
        contentView.addSubview(yearsInService)
        contentView.addSubview(salary)
        
        let views = [
            "image" : employeeImage,
            "name"  : employeeName,
            "years" : yearsInService,
            "salary": salary,
            ]
        
        var allConstraints: [NSLayoutConstraint] = []
        allConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-[image(50)]", options: [], metrics: nil, views: views)
        allConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:[salary]-|", options: [], metrics: nil, views: views)
        allConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-[name]-[years]-|", options: [], metrics: nil, views: views)
        allConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[image(50)]-[name]-|", options: [], metrics: nil, views: views)
        allConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[image]-[years]-[salary]-|", options: [], metrics: nil, views: views)
        
         NSLayoutConstraint.activate(allConstraints)
        
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
    
}

No comments:

Post a Comment

NO JUNK, Please try to keep this clean and related to the topic at hand.
Comments are for users to ask questions, collaborate or improve on existing.