好的,我想在UITableView中有一个自定义的UITableViewCell。
我需要每个组件尽可能模块化和可重用,所以我决定将它们全部放在不同的类中:
我的设置现在看起来像这样: 我的DataSoure有一个swift文件,我的CustomTableViewCell是一个文件,在我的故事板中,我在其他UIViees旁边有一个UITableView,我声明要使用自定义单元格。
故事板看起来像这样:
我的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
的代码。
答案 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