在ViewController

时间:2017-04-17 20:25:46

标签: ios uitableview swift3 uistoryboard

好的,我想在UITableView中有一个自定义的UITableViewCell。

我需要每个组件尽可能模块化和可重用,所以我决定将它们全部放在不同的类中:

我的设置现在看起来像这样: 我的DataSoure有一个swift文件,我的CustomTableViewCell是一个文件,在我的故事板中,我在其他UIViees旁边有一个UITableView,我声明要使用自定义单元格。

故事板看起来像这样:

TableView(属性检查器): storyboard setup and table view attributes inspector

TableView(身份检查员): table view identity inspector

TableView(尺寸检查员): table view size inspector

TableViewCell(身份检查员): table view cell identity inspector

TableViewCell(属性检查器): table view cell attributes inspector

TableViewCell(大小检查器): table view cell size inspector

我的ViewController类如下所示:

import UIKit

class MyShitViewController: UIViewController, UITableViewDelegate {

    @IBOutlet weak var importantTableView: UITableView!
    var importantItems = [ContentItem]()

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Test data
        importantItems.append(ContentItem(contentType: 1, image: #imageLiteral(resourceName: "ContentIcon"), title: "SQL - Basics", subject: "informatics", grade: 11, progress: 35, action: ContentItem.ACTION_MORE))
        importantItems.append(ContentItem(contentType: 1, image: #imageLiteral(resourceName: "ContentIcon"), title: "SQL - Pros", subject: "informatics", grade: 12, progress: 0, action: ContentItem.ACTION_MORE))
        // Data source
        let dataSource = ContentItemDataSource(items: importantItems)
        importantTableView.rowHeight = 75
        importantTableView.dataSource = dataSource
        importantTableView.reloadData()
    }

    //MARK: Table view delegate
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // For debugging, never get's called, when some one clicks on any cell
        let row = indexPath.row
        print(row)
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        print("height")
        return 48
    }

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        print("estimated height")
        return 48
    }
}

我的CustomTableViewCell类:

import UIKit

class ContentItemView: UITableViewCell {

    //MARK: Properties
    var contentItem: ContentItem?

    private var contentImageView: UIImageView?
    private var primaryTextView: UILabel?
    private var secondaryTextView: UILabel?
    private var progressView: UILabel?
    private var actionView: UIButton?
    private var verifiedIcon: UIImageView?

    private var layoutConstraints: [NSLayoutConstraint] = []

    //MARK: Initialisation
    func setContent(item: ContentItem) {
        self.contentItem = item
        setContent()
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        print(style)
        setUpView()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        print("coder")
        setUpView()
    }

    //MARK: Set Up
    private func setUpView() {
        self.backgroundView?.backgroundColor = Colors.biology
        self.textLabel?.text = "Test"
        // Create views
        contentImageView = UIImageView()
        primaryTextView = UILabel()
        secondaryTextView = UILabel()
        progressView = UILabel()
        actionView = UIButton()
        verifiedIcon = UIImageView()
        // Add Content to views
        primaryTextView?.font = getFont(withSize: 14)
        primaryTextView?.textColor = Colors.toolbarColor
        secondaryTextView?.font = getFont(withSize: 12)
        secondaryTextView?.textColor = Colors.toolbarColor
        progressView?.font = getFont(withSize: 12)
        progressView?.textColor = Colors.toolbarColor
        // Add sub views
        self.contentView.addSubview(contentImageView!)
        self.contentView.addSubview(primaryTextView!)
        self.contentView.addSubview(secondaryTextView!)
        self.contentView.addSubview(progressView!)
        self.contentView.addSubview(actionView!)
        self.contentView.addSubview(verifiedIcon!)
        // Apply Constraints
        makeViewConstraints()
    }

    // MARK: Layout
    private func setContent() {
        contentImageView?.image = contentItem?.image
        primaryTextView?.text = contentItem?.title
        secondaryTextView?.text = (contentItem?.done)! ? "DONE" : (contentItem?.subject)! + " - " + getLocalizedGrade(_for: (contentItem?.grade)!)
        progressView?.text = contentItem?.progress != nil ? "\(String(describing: contentItem?.progress))%" : ""
        if (contentItem?.verified)! { verifiedIcon?.image = #imageLiteral(resourceName: "verified") }
        else { verifiedIcon?.image = nil }
        let actionImage = getActionImage()
        actionView?.setImage(actionImage, for: .normal)
    }

    private func makeViewConstraints() {
        // Clear constraints
        self.contentView.removeConstraints(layoutConstraints)
        layoutConstraints.removeAll()
        // Force elements to exist
        let imageView = self.contentImageView!
        let primaryTextView = self.primaryTextView!
        let secondaryTextView = self.secondaryTextView!
        let progressView = self.progressView!
        let actionView = self.actionView!
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.widthAnchor.constraint(equalToConstant: 48)
        imageView.heightAnchor.constraint(equalToConstant: 48)
        layoutConstraints.append(
            NSLayoutConstraint(item: imageView, attribute: .leading, relatedBy: .equal,
                           toItem: self.contentView, attribute: .leading, multiplier: 1, constant: 0))
        layoutConstraints.append(
            NSLayoutConstraint(item: imageView, attribute: .centerY, relatedBy: .equal,
                           toItem: self.contentView, attribute: .centerY, multiplier: 1, constant: 0))
        primaryTextView.translatesAutoresizingMaskIntoConstraints = false
        layoutConstraints.append(
            NSLayoutConstraint(item: primaryTextView, attribute: .leading, relatedBy: .equal,
                           toItem: imageView, attribute: .trailing, multiplier: 1, constant: 16))
        layoutConstraints.append(
            NSLayoutConstraint(item: primaryTextView, attribute: .top, relatedBy: .equal,
                           toItem: self.contentView, attribute: .top, multiplier: 1, constant: 8))
        secondaryTextView.translatesAutoresizingMaskIntoConstraints = false
        layoutConstraints.append(
            NSLayoutConstraint(item: secondaryTextView, attribute: .leading, relatedBy: .equal,
                           toItem: imageView, attribute: .trailing, multiplier: 1, constant: 16))
        layoutConstraints.append(
            NSLayoutConstraint(item: secondaryTextView, attribute: .bottom, relatedBy: .equal,
                           toItem: self.contentView, attribute: .bottom, multiplier: 1, constant: -8))
        progressView.translatesAutoresizingMaskIntoConstraints = false
        layoutConstraints.append(
            NSLayoutConstraint(item: progressView, attribute: .centerX, relatedBy: .equal,
                           toItem: imageView, attribute: .centerX, multiplier: 1, constant: 0))
        layoutConstraints.append(
            NSLayoutConstraint(item: progressView, attribute: .centerY, relatedBy: .equal,
                           toItem: imageView, attribute: .centerY, multiplier: 1, constant: 0))
        actionView.translatesAutoresizingMaskIntoConstraints = false
        layoutConstraints.append(
            NSLayoutConstraint(item: actionView, attribute: .trailing, relatedBy: .equal,
                           toItem: self.contentView, attribute: .trailing, multiplier: 1, constant: 0))
        layoutConstraints.append(
            NSLayoutConstraint(item: actionView, attribute: .centerY, relatedBy: .equal,
                           toItem: self.contentView, attribute: .centerY, multiplier: 1, constant: 0))
        self.contentView.addConstraints(layoutConstraints)
    }

    // MARK: Additional Helpers
    private func getActionImage() -> UIImage? {
        if contentItem?.action == ContentItem.ACTION_MORE {
            return #imageLiteral(resourceName: "ic_more_horiz_white")
        }
        if contentItem?.action == ContentItem.ACTION_ADD {
            return #imageLiteral(resourceName: "ic_add_circle_outline_white")
        }
        if contentItem?.action == ContentItem.ACTION_REMOVE {
            return #imageLiteral(resourceName: "ic_remove_circle_outline_white")
        }
        return nil
    }
}

最后我的DataSource:

import UIKit

class ContentItemDataSource: NSObject, UITableViewDataSource {
    var items = [ContentItem]()

    init(items: [ContentItem]) {
        self.items = items
    }

    // MARK: - Table view data source

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let item = items[indexPath.row]
        guard let cell = tableView.dequeueReusableCell(withIdentifier: Config.CONTENT_ITEM_CELL, for: indexPath) as? ContentItemView else {
            fatalError("The dequeued cell is not an instance of ContentItemView.")
        }
        cell.setContent(item: item)
        return cell
    }
}

我不知道它为什么不起作用,可能DataSource没有按预期工作或将dataSource分配给TableView ......

CustomTableViewCell应该没有问题,因为它之前有效,我更改了我的视图添加到self.contentView的代码。

实际输出: actual output

预期产量: expected output

1 个答案:

答案 0 :(得分:1)

数据源定义为弱:

weak open var dataSource: UITableViewDataSource?

您的代码:

let dataSource = ContentItemDataSource(items: importantItems)
importantTableView.dataSource = dataSource

您没有参考,因此在方法结束后它将再次为零。

解决方案:定义一个类var并根据需要保留它。

var dataSource: UITableViewDataSource!

let dataSource = ContentItemDataSource(items: importantItems)
importantTableView.dataSource = dataSource
self.dataSource = dataSource