iOS:如何构建具有多种单元格类型的表视图

首先,创建一个新项目,将TableView添加到默认ViewController,将tableView固定到ViewController,然后将ViewController嵌入到Navigation Controller中,并确保该项目能够按预期编译并运行。 这是基本步骤,此处将不介绍。 如果您在这部分上遇到麻烦,那么现在就更深入地了解这一主题可能为时过早。

您的ViewController类将如下所示:

 类ViewController:UIViewController {@IBOutlet弱var tableView:UITableView? 覆盖func viewDidLoad(){super.viewDidLoad()}} 

我创建了一个简单的JSON数据,它模仿了服务器的响应。 您可以下载它。 将此文件保存在项目文件夹中,并确保文件在文件检查器中具有项目名称作为目标:

您还将需要一些图像。 下载档案,将其解压缩,然后将图片添加到资产文件夹。 不要重命名任何图像。

我们需要创建一个模型,该模型将保存我们从JSON读取的所有数据。

  class Profile {var fullName:String?  var pictureUrl:字符串?  var email:字符串?  var about:字串?  var friends = [Friend]()var profileAttributes = [Attribute]()} class Friend {var name:String?  var pictureUrl:字符串?}类属性{var键:字符串?  var值:字符串?} 

我们将使用JSON对象添加一个初始化程序,因此您可以轻松地将JSON映射到模型。 首先,我们需要从.json文件中提取内容并将其表示为Data的方法:

 公共功能dataFromFile(_ filename:String)->数据?  {@objc class TestClass:NSObject {} let bundle = Bundle(for:TestClass.self)if let path = bundle.path(forResource:filename,ofType:“ json”){return(try?Data(contentsOf:URL(fileURLWithPath) :path)))} return nil} 

使用数据,我们可以初始化配置文件。 有两种不同的方法可以使用本机或第三方串行器快速解析JSON,因此您可以使用自己喜欢的一种。 我将坚持使用标准的Swift JSONSerialization来保持项目简单,并且不使用任何外部库重载该项目:

  class Profile {var fullName:String?  var pictureUrl:字符串?  var email:字符串?  var about:字串?  var friends = [Friend]()var profileAttributes = [Attribute]()init?(data:Data){做{如果让json =尝试JSONSerialization.jsonObject(with:data)as?  [String:任何],让body = json [“ data”]为?  [String:任何] {self.fullName = body [“ fullName”]为? 字符串self.pictureUrl = body [“ pictureUrl”]为? 字符串self.about = body [“ about”]为? 字符串self.email = body [“ email”]为?  Stringif让friends = body [“ friends”]表示为?  [[String:Any]] {self.friends = friends.map {Friend(json:$ 0)}}是否让profileAttributes = body [“ profileAttributes”]设为?  [[[String:Any]] {self.profileAttributes = profileAttributes.map {Attribute(json:$ 0)}}}} catch {print(“反序列化JSON:\(error)”错误)return nil}}} class Friend {var名称:字符串?  var pictureUrl:String?init(json:[String:Any]){self.name = json [“ name”] as? 字符串self.pictureUrl = json [“ pictureUrl”]为?  String}} class Attribute {var key:String?  var值:字符串?  init(json:[String:Any]){self.key = json [“ key”]如吗? 字符串self.value = json [“ value”]如? 字符串}} 

第2部分:视图模型

我们的模型已经准备就绪,因此我们需要创建ViewModel。 它将负责向我们的TableView提供数据。

我们将创建5个不同的表节:

·全名和个人资料图片

· 关于

·电子邮件

·属性

·朋友

前三个部分每个都有一个单元格,后两个部分可以有多个单元格,具体取决于我们JSON文件的内容。

因为我们的数据是动态的,所以单元格的数量不是恒定的,并且我们为每种类型的数据使用不同的tableViewCells,所以我们需要提出正确的ViewModel结构。

首先,我们必须区分数据类型,因此我们可以使用适当的单元格。 当您需要在多个项目之间快速切换时,最好的方法是枚举。 因此,让我们开始使用ViewModelItemType构建ViewModel:

 枚举ProfileViewModelItemType {case nameAndPicture case有关电子邮件案例case朋友case属性} 

每个枚举情况代表需要不同TableViewCell的数据类型 但是因为我们要在同一tableView中使用我们的数据,所以需要具有单个DataModelItem,这将确定所有属性。 我们可以通过使用协议来实现这一点,该协议将为我们的商品提供计算属性:

 协议ProfileViewModelItem {} 

我们需要了解的关于物品的第一件事是物品的类型。 因此,我们为协议创建一个type属性。 创建协议属性时,需要提供其名称类型并指定该属性是gettable还是settableand gettable。 您可以在此处获取有关协议属性的更多信息和示例。 在我们的例子中,类型将为ProfileViewModelItemType,并且我们只需要此属性的getter:

 协议ProfileViewModelItem {var类型:ProfileViewModelItemType {get}} 

我们需要的下一个属性是rowCount。 它将告诉我们每个部分有多少行。 提供此属性的类型和获取器:

 协议ProfileViewModelItem {var类型:ProfileViewModelItemType {get} var rowCount:Int {get}} 

该协议中最后一件好事是章节标题。 基本上,节标题也是tableView的数据。 如您所记得,使用MVVM结构,我们不想在其他任何地方创建数据或任何类型的数据,而是在viewModel中创建

 协议ProfileViewModelItem {var类型:ProfileViewModelItemType {get} var rowCount:Int {get} var sectionTitle:字符串{get}} 

现在,我们准备为每种数据类型创建ViewModelItem 。 每个项目都将符合协议。 但是在执行此操作之前,让我们进一步进行干净整洁的项目:为我们的协议提供一些默认值。 在Swift中,我们可以使用协议扩展为协议提供默认值:

 扩展ProfileViewModelItem {var rowCount:Int {return 1}} 

现在,如果行数为1,我们就不必为我们的项目提供行数,因此它将为您节省几行多余的冗余代码。

协议扩展还可以使您无需使用@objc协议即可制定可选的协议方法。 只需创建一个协议扩展并将默认方法实现放在该扩展中即可。

为名称和图片单元格创建第一个ViewModeItem

 类ProfileViewModelNameItem:ProfileViewModelItem {变量类型:ProfileViewModelItemType {return .nameAndPicture} var sectionTitle:字符串{返回“主要信息”}} 

就像我之前说的,我们不需要提供行数,因为在这种情况下,我们需要默认值1。

现在,我们添加其他属性,对于该项目将是唯一的:pictureUrl和userName。 两者都是没有初始值的存储属性,因此我们还需要提供此类的init:

 类ProfileViewModelNameAndPictureItem:ProfileViewModelItem {变量类型:ProfileViewModelItemType {return .nameAndPicture} var sectionTitle:字符串{返回“主要信息”} var pictureUrl:字符串var userName:Stringinit(pictureUrl:字符串,userName:字符串){self.pictureUrl = pictureUrl self。 userName = userName}} 

现在我们可以创建剩余的4个模型项:

 类ProfileViewModelAboutItem:ProfileViewModelItem {变量类型:ProfileViewModelItemType {返回} var sectionTitle:字符串{返回“关于”} var about:字符串init(about:String){self.about = about}}类ProfileViewModelEmailItem:ProfileViewModelItem {变量类型: ProfileViewModelItemType {return .email} var sectionTitle:字符串{return“电子邮件”} var email:Stringinit(email:String){self.email = email}}类ProfileViewModelAttributeItem:ProfileViewModelItem {var type:ProfileViewModelItemType {return .attribute} var sectionTitle:字符串{返回“属性”} var rowCount:Int {返回attribute.count} var属性:[Attribute] init(attributes:[Attribute]){self.attributes =属性}}类ProfileViewModeFriendsItem:ProfileViewModelItem {var类型:ProfileViewModelItemType {return .friend} var sectionTitle:字符串{返回“ Friends”} var rowCount:Int {return friends.count} var朋友:[Friend] init(friends:[Friend]){self.friends = fr 意向}} 

对于ProfileViewModeAttributeItemProfileViewModeFriendsItem,我们可以有多个单元格,因此RowCount将分别是Attributes数和Friends数。

这就是我们需要的数据项。 最后一步将是ViewModel类。 该类可由任何ViewController使用 ,这是MVVM结构背后的关键思想之一:您的ViewModelView一无所知,但它提供了View可能需要的所有数据。

ViewModel唯一的属性是项目数组,它将代表UITableView的部分数组

  class ProfileViewModel:NSObject {变量项= [ProfileViewModelItem]()} 

为了初始化ViewModel,我们将使用Profile模型。 首先,我们尝试将.json文件解析为Data:

 类ProfileViewModel:NSObject {变量项= [ProfileViewModelItem]()覆盖init(profile:Profile){super.init()保护let data = dataFromFile(“ ServerData”),let profile = Profile(data:data)else {return} //初始化代码将在此处}} 

这是最有趣的部分:基于Model ,我们将配置要显示的ViewModel项。

 类ProfileViewModel:NSObject {变量项= [ProfileViewModelItem]()覆盖init(){super.init()保护let data = dataFromFile(“ ServerData”),let profile = Profile(data:data)else {return} if let name = profile.fullName,let pictureUrl = profile.pictureUrl {let nameAndPictureItem = ProfileViewModelNamePictureItem(name:name,pictureUrl:pictureUrl)items.append(nameAndPictureItem)} if let about = profile.about {let aboutItem = ProfileViewModelAboutItem(about:about)项目.append(aboutItem)} if let email = profile.email {let dobItem = ProfileViewModelEmailItem(email:email)items.append(dobItem)} let attribute = profile.profileAttributes //如果属性不为空,则仅需要属性item! .isEmpty {让attributesItem = ProfileViewModeAttributeItem(attributes:属性)items.append(attributesItem)}让朋友= profile.friends // //如果朋友不为空,我们只需要朋友项目,如果!profile.friends.isEmpty {让friendsItem = ProfileViewModeFriendsItem(fri 结束:朋友)items.append(friendsItem)}}} 

现在,如果要重新排序,添加或删除项目,则只需修改此ViewModel项目数组。

接下来,我们将UITableViewDataSource添加到我们的ModelView中:

 扩展ViewModel:UITableViewDataSource {func numberOfSections(in tableView:UITableView)-> Int {返回items.count} func tableView(_ tableView:UITableView,numberOfRowsInSection部分:Int)-> Int {返回item [section] .rowCount} func tableView( _ tableView:UITableView,cellForRowAt indexPath:IndexPath)-> UITableViewCell {//我们将在此处配置单元格}} 

在下一篇文章中,我们将使用多种单元格类型升级Table视图的延续。

在http://www.greenstechnologys.com/apple-ios-training-in-chennai.html中查看我的其他作品

GreensTechnology提供的最佳iOS培训。 使用Swift语言创建iOS应用。 果岭提供100%的位置。 绿党的分支机构包括:Adyar,Tambaram,OMR,Velachery,Annanagar。 Greens Technologys通过实践和理论课程为您提供最佳的移动应用培训。

    Interesting Posts