从Swift中的nib定制UITableViewCell

时间:2014-08-28 06:05:28

标签: ios uitableview swift ios8

我正在尝试从笔尖创建自定义表格视图单元格。我指的是这篇文章here。我面临两个问题。

我创建了一个.xib文件,其中拖动了一个UITableViewCell对象。我创建了一个UITableViewCell的子类,并将其设置为单元格的类,将 Cell 设置为可重用的标识符。

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
    }

}

在UITableViewController中我有这段代码,

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
    }
}

此代码不符合任何错误,但当我在模拟器中运行时,它看起来像这样。

enter image description here

在故事板中的UITableViewController中,我没有对单元格做任何事情。空标识符,没有子类。我尝试将 Cell 标识符添加到原型单元格中并再次运行它,但我得到了相同的结果。

我遇到的另一个错误是,当我尝试在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]
}

如我在文章中所提到的,我将cell参数的类型形式UITableViewCell更改为CustomOneCell,这是我的UITableViewCell的子类。但我收到以下错误,

使用selector'tableView覆盖方法:willDisplayCell:forRowAtIndexPath:'具有不兼容的类型'(UITableView!,CustomOneCell!,NSIndexPath!) - > ()'

任何人都知道如何解决这些错误?这些似乎在Objective-C中工作正常。

谢谢。

编辑:我刚注意到,如果我将模拟器的方向更改为横向并将其转回肖像,则单元格会出现!我仍然无法弄清楚发生了什么。我上传了一个Xcode项目here来证明问题,如果你有时间快速浏览一下。

12 个答案:

答案 0 :(得分:179)

您应该为您的项目尝试以下代码: (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
    }
}

下图显示了一组使用所提供代码的约束,而没有来自Xcode的任何约束歧义消息。

enter image description here

答案 1 :(得分:27)

这是我使用Swift 2和Xcode 7.3的方法。此示例将使用单个ViewController加载两个.xib文件 - 一个用于UITableView,另一个用于UITableCellView。

enter image description here

对于此示例,您可以将UITableView权限拖放到空的 TableNib .xib文件中。在里面,将文件的所有者设置为ViewController类,并使用插座引用tableView。

enter image description here

enter image description here

现在,在视图控制器中,您可以像往常一样委托tableView,如此

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

        ...

要创建自定义单元格,请再次将表格视图单元格对象拖放到空 TableCellNib .xib文件中。这次,在单元格.xib文件中,您不必指定“所有者”,但您需要指定自定义类标识符,如“TableCellId”

enter image description here enter image description here

使用您需要的任何插座创建子类

class TableCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!

}

最后......回到View Controller中,您可以加载并显示整个内容

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)

}

代码显示了如何简单地加载和显示nib文件(表),以及如何注册nib以供单元使用。

希望这有帮助!!!

答案 2 :(得分:11)

Swift 4

注册Nib

tblMissions.register(UINib(nibName: "MissionCell", bundle: nil), forCellReuseIdentifier: "MissionCell")

在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
    }

答案 3 :(得分:4)

带有屏幕截图的详细解决方案

  1. 创建一个空的用户界面文件并将其命名为MyCustomCell.xib

enter image description here

  1. 添加UITableViewCell作为xib文件和所需的任何其他可视组件的根。

enter image description here

  1. 以类名MyCustomCell作为UITableViewCell的子类创建可可触摸类文件。

enter image description here enter image description here

  1. 为自定义表格视图单元格设置自定义类和重用标识符。

enter image description here enter image description here

  1. 打开助手编辑器,然后ctrl+drag为视觉组件创建插座。

enter image description here

  1. 配置UIViewController以使用您的自定义单元格。
class MyViewController: UIViewController {

    @IBOutlet weak var myTable: UITableView!

    override func viewDidLoad {
        super.viewDidLoad()

        let nib = UINib(nibName: "MyCustomCell", bundle: nil)
        myTable.register(nib, forCellReuseIdentifier: "MyCustomCell")
        myTable.dataSource = self
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell") as? MyCustomCell {
            cell.myLabel.text = "Hello world."
            return cell
        }
        ...
    }
}

答案 4 :(得分:3)

另一种可能对你有用的方法(就是我这样做的方法)是注册一个类。

假设您创建一个自定义tableView,如下所示:

class UICustomTableViewCell: UITableViewCell {...}

然后你可以在任何你将用“registerClass”显示它的UITableViewController中注册这个单元格:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.registerClass(UICustomTableViewCell.self, forCellReuseIdentifier: "UICustomTableViewCellIdentifier")
}

你可以像在行单元格中所期望的那样调用它:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("UICustomTableViewCellIdentifier", forIndexPath: indexPath) as! UICustomTableViewCell
    return cell
}

答案 5 :(得分:3)

您没有按以下方式注册笔尖:

--use_public_ips

答案 6 :(得分:2)

要修复"覆盖方法...具有不兼容的类型..." 错误我已将功能声明更改为

override func tableView(tableView: (UITableView!), 
                        cellForRowAtIndexPath indexPath: (NSIndexPath!)) 
    -> UITableViewCell {...}

-> UITableViewCell! - 末尾有感叹号)

答案 7 :(得分:1)

雨燕4.1.2

xib。

创建ImageCell2.swift

第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)
    }

}

步骤2。根据Viewcontroller类

  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
    } 

}

答案 8 :(得分:0)

使用类 UITableViewCell 简单地获取xib。根据要求设置UI并分配IBOutlet。在表视图的cellForRowAt()中使用它,如下所示:

//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
}

enter image description here

100%正常工作(经过测试)

答案 9 :(得分:0)

我必须确保在创建出口时指定我要钩住单元,而不是对象的所有者。当菜单显示名称时,您必须在“对象”下拉菜单中选择它。当然,您也必须将单元格声明为您的类,而不仅仅是“ TableViewCellClass”。否则,我将继续使该类不符合密钥要求。

答案 10 :(得分:0)

此行添加到TableView单元格中:

static var nib  : UINib{

           return UINib(nibName: identifier, bundle: nil)

       }

       static var identifier : String{

           return String(describing: self)

       }

    

And register in viewcontroller like



//This line use in viewdid load

tableview.register(TopDealLikedTableViewCell.nib, forCellReuseIdentifier: TopDealLikedTableViewCell.identifier)

// cell for row at indexpath

if let cell = tableView.dequeueReusableCell(withIdentifier:

    TopDealLikedTableViewCell.identifier) as? TopDealLikedTableViewCell{

           return cell

  }

return UITableViewCell()

答案 11 :(得分:0)

// 在单元格上设置

静态变量标识符:字符串{ 返回字符串(描述:自我)
} 静态变量笔尖:UINib { 返回 UINIb(nibName: 标识符, bundle: nil) }