可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I\'m trying to create a custom table view cell from a nib. I\'m referring to this article here. I\'m facing two issues.
I created a .xib file with a UITableViewCell object dragged on to it. I created a subclass of UITableViewCell
and set it as the cell\'s class and Cell as the reusable identifier.
import UIKit
class CustomOneCell: UITableViewCell {
@IBOutlet weak var middleLabel: UILabel!
@IBOutlet weak var leftLabel: UILabel!
@IBOutlet weak var rightLabel: UILabel!
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
In the UITableViewController I have this code,
import UIKit
class ViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
var items = [\"Item 1\", \"Item2\", \"Item3\", \"Item4\"]
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - UITableViewDataSource
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let identifier = \"Cell\"
var cell: CustomOneCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomOneCell
if cell == nil {
tableView.registerNib(UINib(nibName: \"CustomCellOne\", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomOneCell
}
return cell
}
}
This code complies with no errors but when I run it in the simulator, it looks like this.
In the UITableViewController in the storyboard I haven\'t done anything to the cell. Blank identifier and no subclass. I tried adding the Cell identifier to the prototype cell and ran it again but I get the same result.
Another error I faced is, when I tried to implement the following method in the UITableViewController.
override func tableView(tableView: UITableView!, willDisplayCell cell: CustomOneCell!, forRowAtIndexPath indexPath: NSIndexPath!) {
cell.middleLabel.text = items[indexPath.row]
cell.leftLabel.text = items[indexPath.row]
cell.rightLabel.text = items[indexPath.row]
}
As shown in the article I mentioned I changed the cell
parameter\'s type form UITableViewCell
to CustomOneCell
which is my subclass of UITableViewCell. But I get the following error,
Overriding method with selector \'tableView:willDisplayCell:forRowAtIndexPath:\' has incompatible type \'(UITableView!, CustomOneCell!, NSIndexPath!) -> ()\'
Anyone have any idea how to resolve these errors? These seemed to work fine in Objective-C.
Thank you.
EDIT: I just noticed if I change the simulator\'s orientation to landscape and turn it back to portrait, the cells appear! I still couldn\'t figure out what\'s going on. I uploaded an Xcode project here demonstrating the problem if you have time for a quick look.
回答1:
You should try the following code for your project:
(syntax for Swift 3+)
CustomOneCell.swift
import UIKit
class CustomOneCell: UITableViewCell {
// Link those IBOutlets with the UILabels in your .XIB file
@IBOutlet weak var middleLabel: UILabel!
@IBOutlet weak var leftLabel: UILabel!
@IBOutlet weak var rightLabel: UILabel!
}
TableViewController.swift
import UIKit
class TableViewController: UITableViewController {
let items = [\"Item 1\", \"Item2\", \"Item3\", \"Item4\"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: \"CustomOneCell\", bundle: nil), forCellReuseIdentifier: \"CustomCellOne\")
}
// MARK: - UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(\"CustomCellOne\", forIndexPath: indexPath) as! CustomOneCell
cell.middleLabel.text = items[indexPath.row]
cell.leftLabel.text = items[indexPath.row]
cell.rightLabel.text = items[indexPath.row]
return cell
}
}
The image below shows a set of constraints that work with the provided code without any constraints ambiguity message from Xcode.
回答2:
Here\'s my approach using Swift 2 and Xcode 7.3. This example will use a single ViewController to load two .xib files -- one for a UITableView and one for the UITableCellView.
For this example you can drop a UITableView right into an empty TableNib.xib file. Inside, set the file\'s owner to your ViewController class and use an outlet to reference the tableView.
and
Now, in your view controller, you can delegate the tableView as you normally would, like so
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
...
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Table view delegate
self.tableView.delegate = self
self.tableView.dataSource = self
...
To create your Custom cell, again, drop a Table View Cell object into an empty TableCellNib.xib file. This time, in the cell .xib file you don\'t have to specify an \"owner\" but you do need to specify a Custom Class and an identifier like \"TableCellId\"
Create your subclass with whatever outlets you need like so
class TableCell: UITableViewCell {
@IBOutlet weak var nameLabel: UILabel!
}
Finally... back in your View Controller, you can load and display the entire thing like so
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// First load table nib
let bundle = NSBundle(forClass: self.dynamicType)
let tableNib = UINib(nibName: \"TableNib\", bundle: bundle)
let tableNibView = tableNib.instantiateWithOwner(self, options: nil)[0] as! UIView
// Then delegate the TableView
self.tableView.delegate = self
self.tableView.dataSource = self
// Set resizable table bounds
self.tableView.frame = self.view.bounds
self.tableView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
// Register table cell class from nib
let cellNib = UINib(nibName: \"TableCellNib\", bundle: bundle)
self.tableView.registerNib(cellNib, forCellReuseIdentifier: self.tableCellId)
// Display table with custom cells
self.view.addSubview(tableNibView)
}
The code shows how you can simply load and display a nib file (the table), and second how to register a nib for cell use.
Hope this helps!!!
回答3:
Swift 4
Register Nib
tblMissions.register(UINib(nibName: \"MissionCell\", bundle: nil), forCellReuseIdentifier: \"MissionCell\")
In TableView DataSource
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: \"MissionCell\", for: indexPath) as? MissionCell else { return UITableViewCell() }
return cell
}
回答4:
For fix the \"Overriding method... has incompatible type...\" error I\'ve changed the function declaration to
override func tableView(tableView: (UITableView!),
cellForRowAtIndexPath indexPath: (NSIndexPath!))
-> UITableViewCell {...}
(was -> UITableViewCell!
-- with exclamation mark at the end)
回答5:
Another method that may work for you (it\'s how I do it) is registering a class.
Assume you create a custom tableView like the following:
class UICustomTableViewCell: UITableViewCell {...}
You can then register this cell in whatever UITableViewController you will be displaying it in with \"registerClass\":
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(UICustomTableViewCell.self, forCellReuseIdentifier: \"UICustomTableViewCellIdentifier\")
}
And you can call it as you would expect in the cell for row method:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(\"UICustomTableViewCellIdentifier\", forIndexPath: indexPath) as! UICustomTableViewCell
return cell
}
回答6:
Simple take a xib with class UITableViewCell. Set the UI as per reuirement and assign IBOutlet. Use it in cellForRowAt() of table view like this:
//MARK: - table method
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayFruit.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:simpleTableViewCell? = tableView.dequeueReusableCell(withIdentifier:\"simpleTableViewCell\") as? simpleTableViewCell
if cell == nil{
tableView.register(UINib.init(nibName: \"simpleTableViewCell\", bundle: nil), forCellReuseIdentifier: \"simpleTableViewCell\")
let arrNib:Array = Bundle.main.loadNibNamed(\"simpleTableViewCell\",owner: self, options: nil)!
cell = arrNib.first as? simpleTableViewCell
}
cell?.labelName.text = self.arrayFruit[indexPath.row]
cell?.imageViewFruit.image = UIImage (named: \"fruit_img\")
return cell!
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 100.0
}
100% working without any issue (Tested)
回答7:
You did not register your nib as below:
tableView.registerNib(UINib(nibName: \"CustomCell\", bundle: nil), forCellReuseIdentifier: \"CustomCell\")
回答8:
swift 4.1.2
xib.
Create ImageCell2.swift
Step 1
import UIKit
class ImageCell2: UITableViewCell {
@IBOutlet weak var imgBookLogo: UIImageView!
@IBOutlet weak var lblTitle: UILabel!
@IBOutlet weak var lblPublisher: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
step 2 . According Viewcontroller class
import UIKit
class ImageListVC: UIViewController,UITableViewDataSource,UITableViewDelegate {
@IBOutlet weak var tblMainVC: UITableView!
var arrBook : [BookItem] = [BookItem]()
override func viewDidLoad() {
super.viewDidLoad()
//Regester Cell
self.tblMainVC.register(UINib.init(nibName: \"ImageCell2\", bundle: nil), forCellReuseIdentifier: \"ImageCell2\")
// Response Call adn Disply Record
APIManagerData._APIManagerInstance.getAPIBook { (itemInstance) in
self.arrBook = itemInstance.arrItem!
self.tblMainVC.reloadData()
}
}
//MARK: DataSource & delegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrBook.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
[enter image description here][2]
let cell = tableView.dequeueReusableCell(withIdentifier: \"ImageCell2\") as! ImageCell2
cell.lblTitle.text = self.arrBook[indexPath.row].title
cell.lblPublisher.text = self.arrBook[indexPath.row].publisher
if let authors = self.arrBook[indexPath.row].author {
for item in authors{
print(\" item (item)\")
}
}
let url = self.arrBook[indexPath.row].imageURL
if url == nil {
cell.imgBookLogo.kf.setImage(with: URL.init(string: \"\"), placeholder: UIImage.init(named: \"download.jpeg\"))
}
else{
cell.imgBookLogo.kf.setImage(with: URL(string: url!)!, placeholder: UIImage.init(named: \"download.jpeg\"))
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 90
}
}