Как создать кодом подобие static TableView


#1

Добрый день!
Хочу узнать, каким образом я могу создать такое окно с 4 ячейками через код?


#2
class ViewController: UIViewController {
    
    private let tableView = UITableView(frame: .zero, style: .plain)
    private var dataSource: TableViewStaticDataSource!
    
    override func loadView() {
        view = tableView
        view.frame.size = UIScreen.main.bounds.size
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let items: [(title: String, placeholder: String)] = [
            ("Name", "Place name"),
            ("Location", "Place location"),
            ("Type", "Place type")
        ]
        dataSource = TableViewStaticDataSource(cells: items.map { TableViewCell(title: $0.title, placeholder: $0.placeholder) })
        tableView.dataSource = dataSource
        
        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width * 0.65))
//        imageView.image = ...
        tableView.tableHeaderView = imageView
    }
}

class TableViewCell: UITableViewCell {
    convenience init(title: String, placeholder: String) {
        self.init()
        selectionStyle = .none
        
        let label = UILabel()
        label.font = .boldSystemFont(ofSize: 15)
        label.text = title
        label.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(label)
        
        let textField = UITextField()
        textField.font = .systemFont(ofSize: 12)
        textField.placeholder = placeholder
        textField.borderStyle = .roundedRect
        textField.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(textField)
        
        NSLayoutConstraint.activate([
            label.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 15),
            label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
            contentView.rightAnchor.constraint(equalTo: label.rightAnchor, constant: 15),
            textField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 15),
            textField.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 8),
            contentView.rightAnchor.constraint(equalTo: textField.rightAnchor, constant: 15),
            contentView.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 8)
        ])
    }
}

class TableViewStaticDataSource: NSObject, UITableViewDataSource {
    private let cells: [UITableViewCell]
    init(cells: [UITableViewCell]) {
        self.cells = cells
        super.init()
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cells.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return cells[indexPath.row]
    }
}


#3

Спасибо за ответ, но я не могу понять как мне добавить картинку к этой реализации)


#4

Картинку можно в tableHeaderView добавить. Исправил код.


#5

А как потом поймать данные, введенные в эти поля?


#6

Так же как и обычно, делегатом, или так например:

class ViewController: UIViewController {
    
    private let tableView = UITableView(frame: .zero, style: .plain)
    private var dataSource: TableViewStaticDataSource!
    
    override func loadView() {
        view = tableView
        view.frame.size = UIScreen.main.bounds.size
    }
    
    private typealias Item = (
        title: String,
        placeholder: String,
        text: String
    )
    
    private var items = [
        Item(title: "Name", placeholder: "Place name", text: ""),
        Item(title: "Location", placeholder: "Place location", text: ""),
        Item(title: "Type", placeholder: "Place type", text: "")
    ] {
        didSet {
            print(items)
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        dataSource = TableViewStaticDataSource(cells: items.enumerated().map { [weak self] item in
            TableViewCell(title: item.element.title, placeholder: item.element.placeholder) { self?.items[item.offset].text = $0 }
        })
        tableView.dataSource = dataSource
        
        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width * 0.65))
        //        imageView.image = ...
        tableView.tableHeaderView = imageView
    }
}

class TableViewCell: UITableViewCell {
    private var changeText: ((String) -> Void)!
    
    convenience init(title: String, placeholder: String, changeText: @escaping (String) -> Void) {
        self.init()
        self.changeText = changeText
        selectionStyle = .none
        
        let label = UILabel()
        label.font = .boldSystemFont(ofSize: 15)
        label.text = title
        label.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(label)
        
        let textField = UITextField()
        textField.font = .systemFont(ofSize: 12)
        textField.placeholder = placeholder
        textField.borderStyle = .roundedRect
        textField.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(textField)
        textField.addTarget(self, action: #selector(changeTextAction(_:)), for: .editingChanged)
        
        NSLayoutConstraint.activate([
            label.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 15),
            label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
            contentView.rightAnchor.constraint(equalTo: label.rightAnchor, constant: 15),
            textField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 15),
            textField.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 8),
            contentView.rightAnchor.constraint(equalTo: textField.rightAnchor, constant: 15),
            contentView.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 8)
        ])
    }
    
    @objc private func changeTextAction(_ textField: UITextField) {
        changeText(textField.text!)
    }
}

class TableViewStaticDataSource: NSObject, UITableViewDataSource {
    private let cells: [UITableViewCell]
    init(cells: [UITableViewCell]) {
        self.cells = cells
        super.init()
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cells.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return cells[indexPath.row]
    }
}

#7

Большое спасибо, за развернутый ответ! =)


#8

Извиняюсь за излишнюю назойливость, но не могли бы вы подсказать как поменять цвет у ячеек?
Я все перепробовал, но так и не получилось поменять цвет(

Update:
Я догнал)) Спасибо, не нужно)