Swift 中的自定义 UITableViewCell 注册类
Posted
技术标签:
【中文标题】Swift 中的自定义 UITableViewCell 注册类【英文标题】:Custom UITableViewCell register class in Swift 【发布时间】:2014-07-15 06:42:44 【问题描述】:在我的应用程序中,我根据数组填充表格。该表使用自定义 UITableViewCell。一切正常,桌子满了。然后我将搜索显示控制器添加到我的 UITableViewController 中,无需编写代码来处理搜索,只需添加控制器即可。当您运行应用程序时,表格仍然被填满。但是如果我尝试单击搜索栏,则会收到错误消息:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier CitiesListCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
我尝试在 UITableViewController 行中添加我的 viewDidLoad 函数:
self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
启动应用程序并立即得到错误:
fatal error: unexpectedly found nil while unwrapping an Optional value
在线cell.cellMyCity.text = cellText
我做错了什么?
这是我的自定义 UITableViewCell 类:
import UIKit
class MyCell: UITableViewCell
@IBOutlet var cellMyImage: UIImageView
@IBOutlet var cellMyCity: UILabel
@IBOutlet var cellMyCountry: UILabel
@IBOutlet var cellMyTemp: UILabel
init(style: UITableViewCellStyle, reuseIdentifier: String!)
super.init(style: style, reuseIdentifier: reuseIdentifier)
override func awakeFromNib()
super.awakeFromNib()
override func setSelected(selected: Bool, animated: Bool)
super.setSelected(selected, animated: animated)
这是单元格的代码:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath) as MyCell!
if cell == nil
cell = MyCell(style: UITableViewCellStyle.Default, reuseIdentifier: kCellIdentifier)
let cellText: String? = dataWeatherSelectedCity[indexPath.row].name as String
println("Строка: \(cellText)")
cell.cellMyCity.text = cellText
let cellSubtitle: String? = dataWeatherSelectedCity[indexPath.row].country as String
cell.cellMyCountry.text = cellSubtitle
cell.cellMyImage.image = UIImage(named: "Blank52")
var currentCityWeatherURL = "http://api.wunderground.com/api/\(self.myAPI.kWundergroundApiKey)/conditions/lang:RU/q/zmw:\(self.dataWeatherSelectedCity[indexPath.row].zmv).json"
var fullObservation:NSDictionary = self.myAPI.jsonParsingWeather(currentCityWeatherURL)
var currentObservation:NSDictionary = fullObservation.valueForKey("current_observation") as NSDictionary
var currentWeather = self.myAPI.parsingOneCityCurrentCondition(currentObservation)
cell.cellMyImage.image = currentWeather.image
cell.cellMyTemp.text = currentWeather.temp
return cell
TableViewCell 中的属性:
没有self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
或self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: kCellIdentifier)
的表:
【问题讨论】:
我没有在您的帖子中看到您在 IB 中为您的单元格设置了 reuse identifier... 更新的图片在哪里?我没有看到任何... 现在你看到我编辑过的帖子中的图片了吗? 你试过object_getClass(MyCell)
而不是MyCell.classForCoder()
和MyCell.self
吗?这在 Swift... 中对我来说在逻辑上看起来更正确
刚试过-Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'must pass a class of kind UITableViewCell'
【参考方案1】:
我所做的工作是这样的:
class MainViewController: UIViewController
// ...
@IBOutlet var tableView: UITableView
override func viewDidLoad()
super.viewDidLoad()
self.tableView.registerNib(UINib(nibName: "UICustomTableViewCell", bundle: nil), forCellReuseIdentifier: "UICustomTableViewCell")
// ...
// ...
注意:如果我使用 –registerClass(_: forCellReuseIdentifier:)
方法,将不会加载 xib 文件,因此除非您以编程方式将内容添加到单元格,否则不会出现实际的自定义界面.如果你想从一个 nib 文件加载界面,你需要用它的 nib 注册单元格。
遵守基本协议:
extension MainViewController: UITableViewDataSource
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
return 3
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
let cell: UICustomTableViewCell = tableView.dequeueReusableCellWithIdentifier(UICustomTableViewCell.reuseIdentifier) as UICustomTableViewCell
println(cell)
return cell;
//
extension MainViewController: UITableViewDelegate
func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat
return 44.0
并且自定义单元类是一个非常通用的类,其名称为UICustomTableViewCell
:
class UICustomTableViewCell: UITableViewCell
class var reuseIdentifier: String
get
return "UICustomTableViewCell"
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
具有相当随机的界面:
以及自定义类和重用标识符的这些设置:
我屏幕上的最终结果与我预期的一样,只有 3 行:
注意:要进一步自定义自定义单元格,您可能需要扩展上面的代码。
更新
使用UISearchBar
,最终结果会是这样的:
【讨论】:
我的意思是,我肯定需要为单元格制作 xib?没有它就不行吗? 不,您不需要为自定义单元格制作 xib,如果您更喜欢这种方式,您可以通过编程方式创建整个自定义内容。 您能建议我如何在我的项目中实现它吗? 恐怕我不明白您的问题...您可以将自定义视图/图层添加到您的自定义单元格中,例如–init(style:reuseIdentifier:)
或者通常您可以使用–willMoveToSuperview(newSuperview:)
甚至–didMoveToSuperview()
方法来自定义视图。
好的。尝试使用带有搜索显示控制器的标准表格【参考方案2】:
在tableView
之前添加self
可以解决问题:
var cell = self.tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath) as MyCell!
【讨论】:
简单有效。为我工作。 这是对我有用的解决方案(XCode 7.2 & Swift v2) wtf... 谁能解释一下为什么会这样?self
对我来说似乎很随意。【参考方案3】:
由于错误提示您正在获取您的 cell
或 UITestField
nil
和 Swift
不支持对 nil 对象进行方法调用,这就是您崩溃的原因。您可以通过检查对象是否为 nil 来防止崩溃,如下所示
if var label = cell.cellMyCity
label.text = cellText
编辑
我想我知道这里有什么问题......
您在storyboard
中有拖放UISearchBar
,因此默认情况下,所有数据源和委托 都设置为您的控制器,例如ViewController
(您覆盖UITableView 的类DataSource 方法)并在 ViewController
中将 MyCell 类注册为您的自定义类。
因此,您的 tableView 显示完美,但是当您向 UISearchBar 键入内容时,同样的 DataSource 方法 (ViewController
) 也会被调用,并且您会为 searchResultsTableView
注册 MyCell(UISearchDisplayController
tableView 即显示搜索结果),但事实并非如此了解 MyCell ,这就是为什么 cell.cellMyCity
在搜索时为零的原因,这意味着 searchResultsTableView
期望默认的 UITableViewCell
并且您没有为默认单元格设置任何内容 -
cell.textLabel.text = countryList[indexPath.row]
您可以通过如下更改 DataSource 方法来观察整个场景
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as MyCell!
if cell == nil
//tableView.registerNib(UINib(nibName: "UICustomTableViewCell", bundle: nil), forCellReuseIdentifier: "UICustomTableViewCell")
tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
cell = MyCell(style: UITableViewCellStyle.Default, reuseIdentifier: kCellIdentifier)
if var label = cell.cellMyCity
label.text = countryList[indexPath.row]
else
cell.textLabel.text = countryList[indexPath.row]
return cell
就解决方案而言,可能有两种可能的解决方案..
A)。不要使用searchResultsTableView
(由UISearchDisplayController
提供)并在ViewController
中的tableView
中显示您的搜索结果。为此,您可以做的是 - 当用户在 UISearchBar
中键入某些内容时,收听 UISearchBar
代表通过谓词获取您的结果数据源(可能在不同的数组中)并在相同的 UITableView
中显示结果。
B)。自定义 UISearchDisplayController 并在 searchResultsTableView
中使用您的自定义单元格(即 MyCell)
【讨论】:
你每次都得到单元格对象 nil 吗?? 如果我使用self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: kCellIdentifier)
- 那么每次。如果我不使用它,那么一切都很好 - 表已填满。但粉碎搜索显示控制器
感谢有用的回答!
我还是不明白这个问题!但这解决了它【参考方案4】:
如果您使用故事板,请确保删除注册类,因为它会覆盖故事板以及与之关联的所有外链
请检查 https://***.com/a/26350795/4453583
它对我有用 =)
【讨论】:
【参考方案5】:您必须记住为任何使用它的 tableView 注册单元格 - 包括 searchDisplayController.tableView。
【讨论】:
以上是关于Swift 中的自定义 UITableViewCell 注册类的主要内容,如果未能解决你的问题,请参考以下文章