Ios 在ViewController中使用带有外部数据源和UITableView的自定义UITableViewCell
好的,我想在UITableView中有一个自定义UITableViewCell 我需要每个组件尽可能模块化和可重用,因此我决定将它们都放在不同的类中: 我的设置现在如下所示: 我有一个用于我的数据源的swift文件,一个用于我的CustomTableViewCell的文件,在我的故事板中,我在其他UIvie旁边有一个UITableView,我声明使用自定义单元格 情节提要如下所示:Ios 在ViewController中使用带有外部数据源和UITableView的自定义UITableViewCell,ios,uitableview,swift3,uistoryboard,Ios,Uitableview,Swift3,Uistoryboard,好的,我想在UITableView中有一个自定义UITableViewCell 我需要每个组件尽可能模块化和可重用,因此我决定将它们都放在不同的类中: 我的设置现在如下所示: 我有一个用于我的数据源的swift文件,一个用于我的CustomTableViewCell的文件,在我的故事板中,我在其他UIvie旁边有一个UITableView,我声明使用自定义单元格 情节提要如下所示: import UIKit class MyShitViewController: UIViewControlle
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
}
}
TableView(属性检查器):
TableView(身份检查器):
TableView(尺寸检查器):
TableViewCell(身份检查器):
TableViewCell(属性检查器):
TableViewCell(尺寸检查器):
我的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
}
}
最后是我的数据源:
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
}
}
我不知道为什么它不工作,可能数据源没有按预期工作,或者将数据源分配给TableView
CustomTableViewCell应该没有问题,因为它以前工作过,我更改了视图添加到self.contentView
的代码
实际产量:
预期产出:
数据源被定义为弱:
weak open var dataSource: UITableViewDataSource?
您的代码:
let dataSource = ContentItemDataSource(items: importantItems)
importantTableView.dataSource = dataSource
您不持有引用,所以在方法结束后它将再次为零
解决方案:定义一个类变量并根据需要保留它
var dataSource: UITableViewDataSource!
以及:
顺便说一句:你没有设置importantattableview.delegate=self。哦,好的一点:D我有一段时间在里面了:)但是我使用了一个插座,因为我尝试了很多方法让它工作,并且认为这可能解决问题,正如我在其他项目中看到的那样。你猜怎么着:这并不是非常感谢你,我甚至没有想到这个事实。你把我的房间弄得乱七八糟,因为它终于为我解决了:你似乎对编写可重用组件感兴趣。也许你对这个链接感兴趣:这是编写应用程序的一种非常有趣的方式:D我将在下一个项目中记住它:)