Swift - Как создать пользовательский viewForHeaderInSection, используя XIB-файл?

17

Я могу создать простой пользовательский viewForHeaderInSection в программном виде, как показано ниже. Но я хочу сделать гораздо более сложные вещи, возможно, соединение с другим классом и достичь их свойств, таких как cellView. Просто я хочу посмотреть, что я делаю.

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    if(section == 0) {

        let view = UIView() // The width will be the same as the cell, and the height should be set in tableView:heightForRowAtIndexPath:
        let label = UILabel()
        let button   = UIButton(type: UIButtonType.System)

        label.text="My Details"
        button.setTitle("Test Title", forState: .Normal)
        // button.addTarget(self, action: Selector("visibleRow:"), forControlEvents:.TouchUpInside)

        view.addSubview(label)
        view.addSubview(button)

        label.translatesAutoresizingMaskIntoConstraints = false
        button.translatesAutoresizingMaskIntoConstraints = false

        let views = ["label": label, "button": button, "view": view]

        let horizontallayoutContraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[label]-60-[button]-10-|", options: .AlignAllCenterY, metrics: nil, views: views)
        view.addConstraints(horizontallayoutContraints)

        let verticalLayoutContraint = NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0)
        view.addConstraint(verticalLayoutContraint)

        return view
    }

    return nil
}


func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 50
}

Можно ли объяснить, как я могу создать собственное представление заголовка таблицы TableView с помощью xib? Я столкнулся со старыми темами Obj-C, но я новичок в языке Swift. Если кто-то объяснит, как подробно, было бы здорово.

  

1.issue: Кнопка @IBAction не подключается к моему ViewController. <Сильный> (фиксированный)

Решено с владельцем файла, базовым классом ViewController (меню с левой кнопкой мыши).

  

2.issue: Проблема с высотой заголовка (исправлена)

Решено добавить headerView.clipsToBounds = true в viewForHeaderInSection : метод.

Для предупреждений ограничений этот ответ решил мои проблемы :

Когда я добавил ImageView даже такое же ограничение по высоте с помощью этого метода в viewController, он перетекает через таблицы tableView выглядят как изображение .

 func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 120
}

Если я использую, автоматическиAdjustsScrollViewInsets в viewDidLoad, в этом случае изображение переходит в navigationBar. -fixed -

self.automaticallyAdjustsScrollViewInsets = false
  

3.issue: Если кнопка находится под пунктом просмотра (исправлено)

@IBAction func didTapButton(sender: AnyObject) {
    print("tapped")

    if let upView = sender.superview {
        if let headerView = upView?.superview as? CustomHeader {
            print("in section \(headerView.sectionNumber)")
        }

    }
}
    
задан tobeiosdeveloper 29.04.2016 в 00:33
источник

1 ответ

40

Типичный процесс для заголовков на основе NIB:

  1. Создайте подкласс класса UITableViewHeaderFooterView , по крайней мере, для вашей метки. Возможно, вы захотите также дать ему некоторый идентификатор, с помощью которого вы можете перепроектировать, в какой раздел соответствует этот заголовок. Аналогично, вы можете указать протокол, с помощью которого заголовок может информировать контроллер событий о событиях (например, нажатие кнопки). Таким образом, в Swift 3:

    // if you want your header to be able to inform view controller of key events, create protocol
    
    protocol CustomHeaderDelegate: class {
        func didTapButton(in section: Int)
    }
    
    // define CustomHeader class with necessary 'delegate', '@IBOutlet' and '@IBAction':
    
    class CustomHeader: UITableViewHeaderFooterView {
        weak var delegate: CustomHeaderDelegate?
    
        @IBOutlet weak var customLabel: UILabel!
    
        var sectionNumber: Int!  // you don't have to do this, but it can be useful to have reference back to the section number so that when you tap on a button, you know which section you came from
    
        @IBAction func didTapButton(_ sender: AnyObject) {
            delegate?.didTapButton(in: sectionNumber)
        }
    
    }
    
  2. Создайте NIB. Лично я даю NIB то же имя, что и базовый класс, чтобы упростить управление моими файлами в моем проекте и избежать путаницы. В любом случае, ключевые шаги включают в себя:

    • Создайте представление NIB, или если вы начали с пустой NIB, добавьте представление в NIB;

    • Установите базовый класс представления как ваш подкласс UITableViewHeaderFooterView (в моем примере, CustomHeader );

    • Добавьте свои элементы управления и ограничения в IB;

    • Подключить @IBOutlet ссылок на выходы вашего кода Swift;

    • Подключите кнопку к @IBAction

  3. В viewDidLoad в контроллере представления зарегистрируйте NIB. В Swift 3:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        tableView.register(UINib(nibName: "CustomHeader", bundle: nil), forHeaderFooterViewReuseIdentifier: "CustomHeader")
    }
    

    Или в Swift 2:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        tableView.registerNib(UINib(nibName: "CustomHeader", bundle: nil), forHeaderFooterViewReuseIdentifier: "CustomHeader")
    }
    
  4. В viewForHeaderInSection отменить повторное использование с использованием того же идентификатора, который вы указали на предыдущем шаге. Сделав это, вы теперь можете использовать свою розетку, вам не нужно ничего делать с программно созданными ограничениями и т. Д. Единственное, что вам нужно сделать (для протокола работы кнопки) - указать его делегат. Например, в Swift 3:

    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "CustomHeader") as! CustomHeader
    
        headerView.customLabel.text = content[section].name  // set this however is appropriate for your app's model
        headerView.sectionNumber = section
        headerView.delegate = self
    
        return headerView
    }
    
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 44  // or whatever
    }
    

    Или, в Swift 2:

    override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let headerView = tableView.dequeueReusableHeaderFooterViewWithIdentifier("CustomHeader") as! CustomHeader
    
        headerView.customLabel.text = content[section].name
        headerView.sectionNumber = section
        headerView.delegate = self
    
        return headerView
    }
    
    override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 44  // or whatever
    }
    
  5. Очевидно, что если вы укажете контроллер представления как delegate для кнопки в представлении заголовка, вы должны соответствовать этому протоколу:

    extension ViewController: CustomHeaderDelegate {
        func didTapButton(in section: Int) {
            print("\(section)")
        }
    }
    

Все это сбивает с толку, когда я перечисляю все шаги, но это очень просто, как только вы это сделали один или два раза. Я думаю, что это проще, чем программирование заголовка.

    
ответ дан Rob 29.04.2016 в 08:29
источник