将 UITableView 排序为多个部分
Posted
技术标签:
【中文标题】将 UITableView 排序为多个部分【英文标题】:sorting UITableView into sections 【发布时间】:2016-04-24 19:10:33 【问题描述】:我是 swift 和 Xcode 的新手(通过教程和 *** 自学)。我已经编写了一些代码,将地点添加到 TableView 中的列表中,现在我正在尝试将该地点列表分类为部分。
具体来说,我有一个 ViewController,我在其中输入姓名、邻居和朋友(所有字符串),这会在我的 TableView 底部添加一个 Place。
我想按社区对这个地点列表进行分组,并将同一社区中的所有地点一起显示在一个部分中,使用社区字符串作为部分标题。
我很接近,但我没有正确索引我的部分。 indexPath.section 我相信是我所缺少的..
到目前为止,我的 TableViewController 中有这段代码:
// MARK: Properties
var places = [Place]()
override func viewDidLoad()
super.viewDidLoad()
// Use the edit button item provided by the table view controller.
navigationItem.leftBarButtonItem = editButtonItem()
// Load any saved places, otherwise load sample data.
if let savedPlaces = loadPlaces()
places += savedPlaces
else
// Load the sample data.
loadSamplePlaces()
// Sort by neighborhood
places.sortInPlace (place1, place2) -> Bool in
return place1.neighborhood < place2.neighborhood
// MARK: Getting Count, Number and Name of Neighborhoods
func getCountForNeighborhood(neighborhood:String) -> Int
return places.filter (place) -> Bool in
return place.neighborhood == neighborhood
.count
func getNumberOfNeighborhoods() -> Int
var neighborhoodCount = 0
var neighborhoodPrev = "Not a real neighborhood"
for place in places
if place.neighborhood != neighborhoodPrev
neighborhoodCount += 1
neighborhoodPrev = place.neighborhood
return neighborhoodCount
func getNeighborhoodForSection(section:Int) -> String
var previousNeighborhood:String = "Not a real neighborhood"
var currentIndex = -1
for place in places
if(place.neighborhood != previousNeighborhood)
currentIndex += 1
if(currentIndex == section)
return place.neighborhood
previousNeighborhood = place.neighborhood
return "Unknown"
func loadSamplePlaces()
let place1 = Place(name: "Motorino", neighborhood: "East Village", friend: "Maggles")!
let place2 = Place(name: "Bar Primi", neighborhood: "Lower East Side", friend: "Em")!
let place3 = Place(name: "El Carino", neighborhood: "Williamsburg", friend: "Ruby")!
places += [place1, place2, place3]
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
//alter this for To Try, Been To sections =2
return getNumberOfNeighborhoods()
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// #warning Incomplete implementation, return the number of rows
let neighborhood = getNeighborhoodForSection(section)
return getCountForNeighborhood(neighborhood)
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "PlaceTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! PlaceTableViewCell
// Fetches the appropriate place for the data source layout.
let place = places[indexPath.row]
cell.placeLabel.text = place.name
cell.neighborhoodLabel.text = place.neighborhood
cell.friendLabel.text = place.friend
return cell
//Add section headers
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?
return getNeighborhoodForSection(section)
我很确定这是我的 cellForRowAtIndexPath 方法的问题。我想我缺少一些代码来正确地将数据索引到各个部分......
当前版本显示
【问题讨论】:
【参考方案1】:你把部分弄得一团糟。
在方法tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
中,您根据indexPath 的行从places 数组中获取数据。
但是您根本不会“谈论”部分。这就是为什么您告诉数据源委托获取这 2 个位置对象的数据,而不管它询问您的部分。
您已经以这样的关系样式创建了一个数据结构:
neighbourhood1 - place1
neighbourhood1 - place2
neighbourhood2 - place3
neighbourhood2 - place4
neighbourhood3 - place5
neighbourhood3 - place6
相信我,将这个数据结构与UITableView
数据源概念结合起来真的很困难,因为很难从单个数据中确定节索引。
尝试将您的数据排列成这样的树:
neighbourhood1:
- place1
- place2
neighbourhood2:
- place3
- place4
neighbourhood3:
- place5
- place6
在一个数组数组中,然后它会很简单,因为 indexPath 对(节,行)将匹配您的 places[section][row]
的索引:
neighbourhood1: (section 0)
- place1 (path 0.0)
- place2 (path 0.1)
neighbourhood2: (section 1)
- place3 (path 1.0)
- place4 (path 1.1)
neighbourhood3: (section 2)
- place5 (path 2.0)
- place6 (path 2.1)
【讨论】:
【参考方案2】:我同意另一个答案:如果您首先将数据存储在按邻域组织的二维数组中,然后放置第二个,然后按以下方式访问数据,这将更容易:
let place = places[indexPath.section, indexPath.row];
但是,对于您的具体问题和当前代码,我在这里看到了两件事。首先,您的样本数据每个社区有一个项目,但您的表格显示每个社区有两行。这表明您的 numberOfRowsInSection
函数在我们期望它为 1 时返回 2。确保您的 getNeighborhoodForSection
返回正确的部分。然后看看为什么getCountForNeighborhood
没有为每个部分返回 1。 (顺便说一句,您可能已经知道这一点,但getNeighborhoodForSection
假设您的数据始终按邻域排序。如果您无序插入新的邻域,则会遇到问题)。
其次,cellForRowAtIndexPath
你总是按indexPath.row
号码提取数据。当您为每个社区输入此函数时,indexPath.row
号码将始终在每个部分(社区)的 0 处重新开始。因此,您将从places
(Motorino) 中拉出第一项,作为每个部分的第一行。这就是为什么您会在每个部分中看到相同的地点列表。
一旦每个社区的行数正确,在cellForRowAtIndexPath
中,您需要:
-
使用您的
getNeighborhoodForSection(index.section);
获取 index.section 的邻域
搜索places
,直到找到那个邻域并保存起点的索引,我将其称为neighborHoodStartIndex
let place = places[neighborHoodStartIndex + indexPath.row]
出于调试目的,我建议在每个社区中创建不同数量的示例位置。当您期望每个部分中的行数不同时,发现问题模式会更容易一些。
【讨论】:
以上是关于将 UITableView 排序为多个部分的主要内容,如果未能解决你的问题,请参考以下文章