gpt4 book ai didi

ios - 如何在UITableViewController中分配异构数据源?

转载 作者:行者123 更新时间:2023-11-28 12:47:49 25 4
gpt4 key购买 nike

我需要构建一个具有异构数据源的UITableView示例两个模型:person和city。
一种方法是将person数组和city数组组合成AnyObject数组,并检查存储在cell中的对象类型。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let someobject = self.events[indexPath.row]

var test = self.events
if someobject is Person {
print ("I am a person")
}
if someobject is City {
print ("I am a city")
}
}

另一个选项是创建基类并使人和城市从基类继承:
 class Person: Base {}
class City: Base {}

然后用[Base]代替[AnyObject]作为tableView数据源。
我想知道是否有更好的方法来做这件事?

最佳答案

我会这样做的。你有你的模特课程:

class Person {
// ...
}

class City {
// ...
}

我假设您的数据是 PersonCity的混合序列,其中序列中的每个元素可能是a Person或a City
假设每个模型都有一个子类,如下所示:
class PersonCell: UITableViewCell {
var person: Person? {
didSet {
guard let person = person else { return }
// update appearance using properties of person
}
}
}

class CityCell: UITableViewCell {
var city: City? {
didSet {
guard let city = city else { return }
// update appearance using properties of city
}
}
}

我假设您已经在table视图中注册了每个单元格类型,可以在脚本中创建作为原型的单元格,也可以在table视图中调用 UITableViewCellregisterNib:forCellReuseIdentifier:
此时需要的是将 registerClass:forCellReuseIdentifier:对象和 Person对象放在一个数组中,为每个数据对象获取适当类型的单元格,并用数据对象配置单元格。我们来制定一个协议:
protocol TableViewDatum: class {

/// Return a fully-configured cell for displaying myself in the table view.
func cell(inTableView tableView: UITableView, forIndexPath indexPath: NSIndexPath) -> UITableViewCell

}

然后我们扩展 City以符合协议:
extension Person: TableViewDatum {
func cell(inTableView tableView: UITableView, forIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Person", forIndexPath: indexPath) as! PersonCell
cell.person = self
return cell
}
}

我们将 Person扩展到符合协议:
extension City: TableViewDatum {
func cell(inTableView tableView: UITableView, forIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("City", forIndexPath: indexPath) as! CityCell
cell.city = self
return cell
}
}

此时,实现所需的 City方法很简单:
class MyTableViewDataSource: NSObject, UITableViewDataSource {

private var data = [TableViewDatum]()

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return data[indexPath.row].cell(inTableView: tableView, forIndexPath: indexPath)
}

}

注1。
使用泛型可以减少 UITableViewDataSource扩展和 Person扩展之间的代码重复,但这可能不值得。这肯定会更难理解,也不会节省太多代码。
注2。
如果您没有自定义的单元格类,比如说, City,而您只是使用了一种标准的单元格样式,比如 Person,那么您仍然可以使用此模式。您只需在 UITableViewCellStyle.Subtitle扩展名中而不是在自定义单元格类中配置单元格。例子:
extension Person: TableViewDatum {
func cell(inTableView tableView: UITableView, forIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Person", forIndexPath: indexPath)
// Assume cell style is .Subtitle.
cell.textLabel?.text = self.name
cell.detailTextLabel?.text = self.title
return cell
}
}

注3。
对于评论家NRITH关心的是,我正在“混合模型和观点”,通过“[H]让人和城市模型类负责出售他们的表格视图单元格”:我没有混合模型和视图。使 PersonPerson符合 City的扩展,因此它们的单元是与 TableViewDatumPerson类定义完全分离的。
很容易想象 CityPerson类来自某个第三方框架。例如,将 City替换为 Person(来自iOS联系人框架)并将 CNContact替换为 City(来自iOS核心位置框架)。
这种模式在这种情况下也同样有效:框架提供的类实现对我的应用程序的用户界面一无所知。声称类实现正在出售其单元是不合理的。是分机在卖电池。
有关此实现样式的更多信息,请查看 WWDC 2015 Session 408: Protocol-Oriented Programming in Swift
关于“让细胞用传递给他们的人或城市对象来配置自己更有意义”,这正是我所做的!我将 CLLocationperson属性设置为使 PersonCell自行配置,并将 PersonCellcity属性设置为使 CityCell自行配置。
假设您只想消除通过模型对象本身的任何传递。但正如我所说,扩展与模型对象是完全分离的,所以我不认为它们有问题。
不过,让我们看看你的样子。我想你的意思是:
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch data[indexPath.row] {

case let person as Person:
let cell = tableView.dequeueReusableCellWithIdentifier("Person", forIndexPath: indexPath) as! PersonCell
cell.person = person
return cell

case let city as City:
let cell = tableView.dequeueReusableCellWithIdentifier("City", forIndexPath: indexPath) as! CityCell
cell.city = city
return cell

default: fatalError()
}
}

你有一个switch语句。(如果您愿意,可以使用 CityCell语句的级联,但它是相同的基本模式。)如果您实现任何其他特定于行的 ifUITableViewDataSource方法(例如 UITableViewDelegatetableView:canEditRowAtIndexPath:等),则可能需要在每个方法中使用类似的switch语句。是否添加了新的模型类,但忘记更新其中一个委托方法?哦,你要等到运行时才能知道。在我的设计中,向 tableView:editActionsForRowAtIndexPath:协议添加相应的必需方法,数据源或委托方法调用该协议方法。如果忘记在某个模型类中实现该方法,编译器将标记错误。
这也是为什么我的设计没有任何与 TableViewDatum案例对应的东西。编译器强制类型安全在编译时将其排除。

关于ios - 如何在UITableViewController中分配异构数据源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37505846/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com