为不同的 UITableViewCell 创建单个 .xib 类
Creating single .xib for different UITableViewCell classes
我遇到了问题
我有一个 NNVerticalStackTableViewCell.xib
文件及其对应的 NNVerticalStackTableViewCell.swift
文件。
NNVerticalStackTableViewCell.swift
文件的代码
class NNVerticalStackTableViewCell: UITableViewCell
{
//MARK: Outlets
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var verticalStack: NNVerticalStackView!
//MARK: Internal Properties
var titleString : String?
{
set{
self.titleLabel.text = newValue
}
get{
return self.titleLabel.text
}
}
//MARK: View Lifecycle Methods
override func awakeFromNib()
{
super.awakeFromNib()
self.titleLabel.text = nil
}
//MARK: Internal Methods
func addViewsInVerticalStack(viewsArray : [UIView])
{
for view in viewsArray
{
self.verticalStack.insertStackItem(view)
}
}
}
NNVerticalStackTableViewCell.xib
文件的接口
with class name
as : NNVerticalStackTableViewCell
and cell identifier
as : NNVerticalStackTableViewCell
现在我创建了 NNVerticalStackTableViewCell
的子class 作为:
class NNPropertiesUnderProjectTableViewCell: NNVerticalStackTableViewCell
{
//MARK: Internal Properties
var completionHandler : ((NNSearchPreference) -> Void)?
//MARK: Internal Methods
func configureCell(_ propertiesUnderProjectArray : [[String : Any]])
{
var viewsArray = [UIView]()
for dict in propertiesUnderProjectArray
{
let elementView = NNPropertiesUnderProjectElementView.loadFromNib()
elementView?.configureViewWith(buttonTitleString: dict["displayString"] as! String, searchPreference: dict["searchPreference"] as! NNSearchPreference, completionHandler: {[weak self] (searchPreference) in
if let handler = self?.completionHandler
{
handler(searchPreference)
}
})
viewsArray.addObject(elementView)
}
self.addViewsInVerticalStack(viewsArray: viewsArray)
}
}
现在我要做的是使用 NNPropertiesUnderProjectTableViewCell
class 和 NNVerticalStackTableViewCell.xib
接口。
类似于NNPropertiesUnderProjectTableViewCell
class 我有许多其他class使用与NNVerticalStackTableViewCell.xib
相同的界面并相应地自定义它。
在我的 ViewController
中,我注册了 NNVerticalStackTableViewCell.xib
然后将单元格创建为:
self.tableView.register(UINib(nibName: "NNVerticalStackTableViewCell"), forCellReuseIdentifier: "NNVerticalStackTableViewCell")
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let propertiesUnderProjectCell = tableView.dequeueReusableCell(withIdentifier: "NNVerticalStackTableViewCell", for: indexPath as IndexPath) as! NNPropertiesUnderProjectTableViewCell
}
但是,我遇到了异常:
Could not cast value of type 'NNVerticalStackTableViewCell' (0x100945878) to 'NNPropertiesUnderProjectTableViewCell' (0x100949330).
任何人都可以建议如何解决这个问题。我想使用单个 .xib
并且不想重复代码。
可以,但是不要使用 UITableViewCell
,而是使用类似的 UIView
为单元格内容视图创建一个 xib,给它一个 class(比如 CellView
)。
在每个单元格class中,获取CellView
和loadNibNamed
并将其设置为单元格内容视图,然后可以自由更改CellView
的属性和将其用作其他单元格 class 的内容视图
也许有更好的解决方案,但对于类似的外观 UIViewController
,我就是这样做的,您也可以尝试在情节提要中未设置 class 的单元格 xib 并尝试加载它,看看是否错误是否仍然存在
基本上,你不能完全按照你想做的去做,因为 class 名称在 XIB 中,所以你总是得到基 class 的实例,而不是任何你的子classes.
@Tj3n 的建议很好,将公共部分提取到可重用视图中,然后在您的 superclass 初始化中创建该视图的实例并添加它。现在,当您实例化一个 subclass 并调用 super 时,公共元素将被初始化并由 subclass.
使用
换句话说,使用组合来实现你的目标,而不是继承。
NNPropertiesUnderProjectTableViewCell 没有注册 Cellidentifier。
如果你想在多个时间使用tableViewCell.xib,你可以这样做。
首先转到文件并创建新文件(Cocoa 触摸 Class)。
使用 .xib 创建 TableViewCell 文件
现在简单地创建您的自定义单元格设计
现在将此代码添加到您的文件中 TableViewCell.swift
现在只需像这样在您的 tableView 单元格中添加标识符(您要在其中添加此自定义 TableviewCell)
现在就把它当成你的Cell吧..
还有宾果你猜对了..
现在只需将单元格添加为!任何 TableViewController 文件中的 TableViewCell(您使用相同的设计得到相同的结果。)
点击这里(首先加载TableViewController)
第二次点击(加载第二个 TableViewController)
你不能那样做,因为 registerNib:
期望确切注册视图的相同实例。
从这里你可以做的是复制 NNVerticalStackTableViewCell.xib
并保留 NNVerticalStackTableViewCell.swift
作为你的基础 class。
然后创建类似 NNPropertiesUnderProjectTableViewCell.xib
的内容,其中包含与之前添加的控件完全相同的视图 NNVerticalStackTableViewCell.xib
。然后使用唯一标识符将其子class 到NNPropertiesUnderProjectTableViewCell.swift
:NNPropertiesUnderProjectTableViewCell
.
其中 NNPropertiesUnderProjectTableViewCell
是 NNVerticalStackTableViewCell
的子类。
从这里,只需添加 NNPropertiesUnderProjectTableViewCell
class.
独有的额外控件
我遇到了问题
我有一个 NNVerticalStackTableViewCell.xib
文件及其对应的 NNVerticalStackTableViewCell.swift
文件。
NNVerticalStackTableViewCell.swift
文件的代码
class NNVerticalStackTableViewCell: UITableViewCell
{
//MARK: Outlets
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var verticalStack: NNVerticalStackView!
//MARK: Internal Properties
var titleString : String?
{
set{
self.titleLabel.text = newValue
}
get{
return self.titleLabel.text
}
}
//MARK: View Lifecycle Methods
override func awakeFromNib()
{
super.awakeFromNib()
self.titleLabel.text = nil
}
//MARK: Internal Methods
func addViewsInVerticalStack(viewsArray : [UIView])
{
for view in viewsArray
{
self.verticalStack.insertStackItem(view)
}
}
}
NNVerticalStackTableViewCell.xib
文件的接口
with class name
as : NNVerticalStackTableViewCell
and cell identifier
as : NNVerticalStackTableViewCell
现在我创建了 NNVerticalStackTableViewCell
的子class 作为:
class NNPropertiesUnderProjectTableViewCell: NNVerticalStackTableViewCell
{
//MARK: Internal Properties
var completionHandler : ((NNSearchPreference) -> Void)?
//MARK: Internal Methods
func configureCell(_ propertiesUnderProjectArray : [[String : Any]])
{
var viewsArray = [UIView]()
for dict in propertiesUnderProjectArray
{
let elementView = NNPropertiesUnderProjectElementView.loadFromNib()
elementView?.configureViewWith(buttonTitleString: dict["displayString"] as! String, searchPreference: dict["searchPreference"] as! NNSearchPreference, completionHandler: {[weak self] (searchPreference) in
if let handler = self?.completionHandler
{
handler(searchPreference)
}
})
viewsArray.addObject(elementView)
}
self.addViewsInVerticalStack(viewsArray: viewsArray)
}
}
现在我要做的是使用 NNPropertiesUnderProjectTableViewCell
class 和 NNVerticalStackTableViewCell.xib
接口。
类似于NNPropertiesUnderProjectTableViewCell
class 我有许多其他class使用与NNVerticalStackTableViewCell.xib
相同的界面并相应地自定义它。
在我的 ViewController
中,我注册了 NNVerticalStackTableViewCell.xib
然后将单元格创建为:
self.tableView.register(UINib(nibName: "NNVerticalStackTableViewCell"), forCellReuseIdentifier: "NNVerticalStackTableViewCell")
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let propertiesUnderProjectCell = tableView.dequeueReusableCell(withIdentifier: "NNVerticalStackTableViewCell", for: indexPath as IndexPath) as! NNPropertiesUnderProjectTableViewCell
}
但是,我遇到了异常:
Could not cast value of type 'NNVerticalStackTableViewCell' (0x100945878) to 'NNPropertiesUnderProjectTableViewCell' (0x100949330).
任何人都可以建议如何解决这个问题。我想使用单个 .xib
并且不想重复代码。
可以,但是不要使用 UITableViewCell
,而是使用类似的 UIView
为单元格内容视图创建一个 xib,给它一个 class(比如 CellView
)。
在每个单元格class中,获取CellView
和loadNibNamed
并将其设置为单元格内容视图,然后可以自由更改CellView
的属性和将其用作其他单元格 class 的内容视图
也许有更好的解决方案,但对于类似的外观 UIViewController
,我就是这样做的,您也可以尝试在情节提要中未设置 class 的单元格 xib 并尝试加载它,看看是否错误是否仍然存在
基本上,你不能完全按照你想做的去做,因为 class 名称在 XIB 中,所以你总是得到基 class 的实例,而不是任何你的子classes.
@Tj3n 的建议很好,将公共部分提取到可重用视图中,然后在您的 superclass 初始化中创建该视图的实例并添加它。现在,当您实例化一个 subclass 并调用 super 时,公共元素将被初始化并由 subclass.
使用换句话说,使用组合来实现你的目标,而不是继承。
NNPropertiesUnderProjectTableViewCell 没有注册 Cellidentifier。
如果你想在多个时间使用tableViewCell.xib,你可以这样做。 首先转到文件并创建新文件(Cocoa 触摸 Class)。
使用 .xib 创建 TableViewCell 文件
现在简单地创建您的自定义单元格设计
现在将此代码添加到您的文件中 TableViewCell.swift
现在只需像这样在您的 tableView 单元格中添加标识符(您要在其中添加此自定义 TableviewCell)
现在就把它当成你的Cell吧..
还有宾果你猜对了..
现在只需将单元格添加为!任何 TableViewController 文件中的 TableViewCell(您使用相同的设计得到相同的结果。)
点击这里(首先加载TableViewController)
第二次点击(加载第二个 TableViewController)
你不能那样做,因为 registerNib:
期望确切注册视图的相同实例。
从这里你可以做的是复制 NNVerticalStackTableViewCell.xib
并保留 NNVerticalStackTableViewCell.swift
作为你的基础 class。
然后创建类似 NNPropertiesUnderProjectTableViewCell.xib
的内容,其中包含与之前添加的控件完全相同的视图 NNVerticalStackTableViewCell.xib
。然后使用唯一标识符将其子class 到NNPropertiesUnderProjectTableViewCell.swift
:NNPropertiesUnderProjectTableViewCell
.
其中 NNPropertiesUnderProjectTableViewCell
是 NNVerticalStackTableViewCell
的子类。
从这里,只需添加 NNPropertiesUnderProjectTableViewCell
class.