Reputation: 5039
I'm trying to have a tableview with some players listed in two sections. section 1 is players currently playing and section 2 is for substitutes. I have one data set with all the players on.
How I went about this is I created two sections let sections = ["playing", "subs"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 11
} else {
return players.count - 11
}
}
I had hoped that this would put the 1st 11 players in my array in the playing section, which it does seem to, but, as I scroll through the table it crashes as I come to the next section I believe. I'm assuming that each section of data must therefore start with an indexPath of 0? and I only have one set of data.
As my app works I want to be able to reorder people across the two sections as they are playing or are subbed. What's the iOS appropriate way to achieve this?
This is my cell for row at indexpath method:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = playerTableView.dequeueReusableCellWithIdentifier("MatchPlayerCell")! as! MatchPlayerCell
cell.configureForMatchPlayer(orderedPlayers[indexPath.row])
return cell
}
and it crashes here with EXC_BAD_INSTRUCTION. Happy to update my question with any more info, I'm relatively new to iOS and not attempted moving rows before
Upvotes: 0
Views: 81
Reputation: 13903
If your player
has a property to determine whether he's playing or a sub, then you can certainly use a single array, although whether it's wise to do so is up to you.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return orderedPlayers.filter { $0.playing }.count
} else {
return orderedPlayers.filter { !$0.playing }.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let player = orderedPlayers.filter { indexPath.section == 0 ? $0.playing : !$0.playing }[indexPath.row]
let cell = playerTableView.dequeueReusableCellWithIdentifier("MatchPlayerCell")! as! MatchPlayerCell
cell.configureForMatchPlayer(player)
return cell
}
You can make this even more concise by making it look like there are two arrays, when, in fact, there's only one:
var players: [Player] {
return orderedPlayers.filter { $0.playing }
}
var subs: [Player] {
return orderedPlayers.filter { !$0.playing }
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? players.count : subs.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let player = (indexPath.section == 0 ? players : subs)[indexPath.row]
let cell = playerTableView.dequeueReusableCellWithIdentifier("MatchPlayerCell")! as! MatchPlayerCell
cell.configureForMatchPlayer(player)
return cell
}
Upvotes: 0
Reputation: 7588
I think it is better to create 3 separate NSMutableArrays. 1st for totalPlayers. 2nd for "playing". and 3rd for "subs".
Then you add/remove players accordingly from totalPlayers. Then you can properly return [array count] in the numberOfRowsInsection.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return players.count
} else {
return subs.count
}
}
Doing the math in this delegate is bad practice really. Because you need to handle all values and in your case, the app will crash if the player-11 becomes less than 0.
Upvotes: 1
Reputation: 2160
If you don't have more than 11 player it will crash anyways.. please make sure that.
Upvotes: 1
Reputation: 535566
You have not given enough information to explain the crash, but as a general matter of policy, using a single array (players
) to represent the data for a table with two sections is just silly. Two sections? Two arrays.
To do otherwise is just asking for trouble, especially because it means that your cellForRowAt:
has to know how the model works. That's inappropriate. The model should be such that cellForRowAt:
is just dumb. Section? Pick the corresponding array. Row? Pick the corresponding index. Done. Don't try to be a smarty-pants in your cellForRowAt:
; you'll just end up, uh, crashing.
Upvotes: 1