Ios Swift中nib的自定义UITableViewCell

Ios Swift中nib的自定义UITableViewCell,ios,uitableview,swift,ios8,Ios,Uitableview,Swift,Ios8,我正在尝试从nib创建自定义表视图单元格。我指的是这篇文章。我面临两个问题 我创建了一个.xib文件,其中拖拽了一个UITableViewCell对象。我创建了一个子类UITableViewCell,并将其设置为单元格的类,将其设置为可重用标识符 import UIKit class CustomOneCell: UITableViewCell { @IBOutlet weak var middleLabel: UILabel! @IBOutlet weak var left

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

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

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
    }
}
这段代码没有错误,但是当我在模拟器中运行它时,它看起来是这样的

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

我遇到的另一个错误是,当我试图在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子类。但我得到了以下错误

使用选择器“tableView:willDisplayCell:ForRowatineXpath:'具有不兼容的类型”(UITableView!、CustomOneCell!、NSIndexPath!)->()”

有人知道如何解决这些错误吗?这些似乎在Objective-C中工作得很好

多谢各位


编辑:我刚刚注意到,如果我将模拟器的方向更改为横向,并将其恢复为纵向,细胞就会出现!我还是不知道发生了什么。如果您有时间快速查看,我上传了一个Xcode项目来演示问题。

对于Swift 5和iOS 12.2,您应该尝试以下代码来解决问题:

斯威夫特

TableViewController.swift


下图显示了一组约束,这些约束与提供的代码一起工作,而没有来自Xcode的任何约束模糊消息:

对于修复“重写方法…具有不兼容类型…”错误,我已将函数声明更改为

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

(was
->UITableViewCell!
--末尾带有感叹号)

以下是我使用Swift 2和Xcode 7.3的方法。本例将使用单个ViewController加载两个.xib文件——一个用于UITableView,另一个用于UITableCellView

在本例中,您可以将UITableView直接放入空的TableNib.xib文件中。在内部,将文件的所有者设置为ViewController类,并使用出口引用tableView

现在,在视图控制器中,您可以像往常一样委托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文件中。这一次,在cell.xib文件中,您不必指定“所有者”,但需要指定自定义类和标识符,如“TableCellId”

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

class TableCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!

}
最后。。。回到视图控制器中,您可以像这样加载和显示整个内容

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以供单元使用


希望这有帮助

另一种可能适合您的方法(我就是这样做的)是注册一个类

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

class UICustomTableViewCell: UITableViewCell {...}
然后,您可以使用“registerClass”将此单元格注册到要在其中显示它的任何UITableViewController中:

您可以在cell for row方法中调用它:

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

使用classUITableViewCell简单获取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
}

100%工作无任何问题(已测试)Swift 4

寄存器笔尖

override func viewDidLoad() {
    super.viewDidLoad()
    tblMissions.register(UINib(nibName: "MissionCell", bundle: nil), forCellReuseIdentifier: "MissionCell")
}
在TableView数据源中

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          guard let cell = tableView.dequeueReusableCell(withIdentifier: "MissionCell", for: indexPath) as? MissionCell else { return UITableViewCell() }
          return cell
    }

您没有按以下方式注册nib:

tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
swift 4.1.2

xib

创建ImageCell2.swift

第一步

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

}
第二步。根据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
    } 

}

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

  • 创建一个空的用户界面文件,并将其命名为
    MyCustomCell.xib
  • 添加一个
    UITableViewCell
    作为xib文件和任何其他所需可视组件的根
  • 创建一个cocoa touch类文件,将类名
    MyCustomCell
    作为
    UITableViewCell
    的子类
  • 设置自定义表视图单元格的自定义类和重用标识符
  • 打开助手编辑器并按住ctrl键并拖动,为视觉组件创建插座
  • 配置
    UIViewController
    以使用自定义单元格

  • 我必须确保在创建出口时指定我是挂接到单元格,而不是对象的所有者。当菜单出现命名时,您必须在“对象”下拉菜单中选择它。当然,您也必须将单元格声明为类,而不仅仅是“TableViewCellClass”。否则,我将继续获取不符合密钥的类。

    此行加载项
    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()
    
    //启动电池

    静态变量标识符:字符串{ 返回字符串(描述:self)
    } 静态变量nib:UINib{ 返回UINib(nibName:identifier,bundle:nil)
    }

    谢谢您的回复。但这也不起作用。是否需要更改表视图控制器中的任何内容?因为它仍然设置为原型单元格。继续使用原型单元格。但是,请确保您已经设置了良好的自动布局约束(如果您使用自动布局)。我上传了一个测试项目,演示了我遇到的问题。如果你有时间,你能看一下吗?你的测试项目证实了这一点:我在你的.xib文件中为你的自定义单元格设置了一些自动布局约束后,我能够使你的应用程序正常工作。看看你是否需要
    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)
        }
    
    }
    
      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
        } 
    
    }
    
    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
            }
            ...
        }
    }
    
    
    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()