TableView AllowsMultipleSelection - Still allowing multiple selections - ios

I posted earlier - on how to stop multiple cells from being able to be selected in my table view - the answer was to use tableView.AllowsMultipleSelections=false
I have been trying and failing miserably since, essentially it doesn't seem to be obeying that rule.
My desired output should be one cell is selected and has a green tick next to it (this works) if a new cell is selected, the old tick is removed and moved to the new current cell.
I have tried many approaches and the latest is to create my own index path from the last index selected - then set the accessory view to nil and change selected to false. This also does not work. Please could someone help me with what I might be doing wrong.
Thanks
import UIKit
class QuizViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
var countries = ["Germany", "France", "England", "Poland", "Spain"];
var selected = -1;
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.allowsMultipleSelection = false;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.countries.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
println("indexpath \(indexPath.row)");
let cell = self.tableView.dequeueReusableCellWithIdentifier("CountryCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = self.countries[indexPath.row];
cell.textLabel?.textAlignment = NSTextAlignment.Center;
let countryImage = String(self.countries[indexPath.row]) + ".png";
cell.imageView?.image = UIImage(named: countryImage);
let image: UIImageView = UIImageView();
cell.accessoryView = image;
return cell;
}
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
var cell = self.tableView.dequeueReusableCellWithIdentifier("CountryCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = self.countries[indexPath.row];
cell.textLabel?.textAlignment = NSTextAlignment.Center;
let countryImage = String(self.countries[indexPath.row]) + ".png";
cell.imageView?.image = UIImage(named: countryImage);
let imageName = "tick.png";
let image: UIImageView = UIImageView(image: UIImage(named: imageName));
cell.accessoryView = image;
if(selected != -1){
//lets remove the tick from the previously selected cell and set selected to false
var cell = self.tableView.dequeueReusableCellWithIdentifier("CountryCell", forIndexPath: NSIndexPath(forRow: selected, inSection: 0)) as UITableViewCell
cell.accessoryView = nil;
cell.selected = false;
}
selected = indexPath.row;
}
}
Attempt at proposed solution
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("CountryCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = self.countries[indexPath.row];
cell.textLabel?.textAlignment = NSTextAlignment.Center;
let countryImage = String(self.countries[indexPath.row]) + ".png";
cell.imageView?.image = UIImage(named: countryImage);
if(cell.selected){
println("cell was set to selected at \(indexPath.row)");
let imageName = "tick.png";
let image: UIImageView = UIImageView(image: UIImage(named: imageName));
cell.accessoryView = image;
}else{
println("cell was NOT set to selected at \(indexPath.row)");
let image: UIImageView = UIImageView();
cell.accessoryView = image;
}
return cell;
}
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
var cell = self.tableView.dequeueReusableCellWithIdentifier("CountryCell", forIndexPath: indexPath) as UITableViewCell
cell.selected = true;
if(selected != -1){
var previous = self.tableView.dequeueReusableCellWithIdentifier("CountryCell", forIndexPath: NSIndexPath(forRow: selected, inSection: 0)) as UITableViewCell
previous.selected = false;
}
selected = indexPath.row;
tableView.reloadData();
}

Don't modify the cell in didSelectRowAtIndexPath. Set the country as "selected" and the previous one as "not selected" and then reload the table data. Use the selected (or not) state to update the cell visually when cellForRowAtIndexPath is called.

Related

cell.selected doesn't work

When I selected a row, text color turns white. however, when I scroll to refresh the row, the text color turns back to black. so I have added a logic if(cell.selected). However it didn't work. when I scroll. the code can't get into if case.Here is the code :-
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
for subview in selectedCell.subviews {
if let view = subview as? UILabel {
view.textColor = UIColor.whiteColor()
}
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var renderWidth:CGFloat = 8
var renderYPosition:CGFloat = 15
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "idcell")
let date = UILabel(frame: CGRectMake(renderWidth, renderYPosition, 110, 20))
let dateText = "asdasdsad"
date.text = dateText
if (cell.selected) {
date.textColor = UIColor.whiteColor()
}
cell.addSubview(date)
}
You are creating a new UITableViewCell everytime. It is recommended to reuse it.
Instead of creating a new cell with this:
let cell:UITableViewCell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "idcell")
Use this to reuse the cell:
let cell = tableView.dequeueReusableCellWithIdentifier("cellIdInStoryboard", forIndexPath: indexPath) as! UITableViewCell
The identifier should be the same as the one you set in storyboard.
The problem is with your if clause in cellForRowAtIndexPath function and also you create cell instance everytime you load the tableview.You need to reuse tableview cells.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var renderWidth:CGFloat = 8
var renderYPosition:CGFloat = 15
let cell = tableView.dequeueReusableCellWithIdentifier("idcell", forIndexPath: indexPath) as! YourTableViewCell
let date = UILabel(frame: CGRectMake(renderWidth, renderYPosition, 110, 20))
let dateText = "asdasdsad"
date.text = dateText
if (cell.selected) {
date.textColor = UIColor.whiteColor()
} else {
date.textColor = UIColor.blackColor() // You didn't add else
}
cell.addSubview(date)
}

How to implement 2 UITableViews in 1 ViewController? The tableViews each have their own custom cell

I have 2 tableviews each with their own custom cell. How can I implement these tableviews in 1 viewcontroller? Here is my code.
Xcode can't cast the custom cell to the standard UITableViewCell
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// let accountSize = Int(accounts.count())
// return accountSize;
var count:Int?
if tableView == self.tableView {
count = Int(accounts.count())
}
if tableView == self.tableViewLoan {
count = Int(loans.count())
}
return count!
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// return UITableViewCell()
var cell:UITableViewCell?
if tableView == self.tableView {
//cell = tableView.dequeueReusableCellWithIdentifier("AccountsTableViewCell", forIndexPath: indexPath) as! AccountsTableViewCell
var cell1 = tableView.dequeueReusableCellWithIdentifier("AccountsTableViewCell", forIndexPath: indexPath) as! AccountsTableViewCell
var account:SUVTISDDA = SUVTISDDA()
account = accounts.objectAtIndex(UInt(indexPath.row))
var accountType = ""
var accountNum = ""
let accountNumber = account.Description.Value
var accountSplit = accountNumber.componentsSeparatedByString(": ")
if(accountSplit.count > 1){
accountNum = accountSplit[1]
accountType = accountSplit[0]
print("Account number: \(accountSplit[1])")
} else {
accountType = account.Description.Value
accountNum = " No Account Number"
print("Account number unavailable")
}
let formatter = NSNumberFormatter()
formatter.numberStyle = .DecimalStyle
cell1.AccountTypeLabel!.text = accountType
cell1.AccountNumberLabel!.text = accountNum
cell1.AccountCurrencyLabel!.text = account.Currency.Value
cell1.AccountAmountLabel!.text = formatter.stringFromNumber(account.AvailableBalance.Value)
cell1.AccountTypeLabel!.textColor = UIColor(red:0, green:0.451, blue:0.682, alpha:1)
return cell1
}
if tableView == self.tableViewLoan {
var cell2 = tableView.dequeueReusableCellWithIdentifier("loanCell", forIndexPath: indexPath) as! LoanCell
var loan: SUVTILN = SUVTILN();
loan = loans.objectAtIndex(UInt(indexPath.row));
cell2.descriptionLabel.text = loan.Description.Value;
cell2.currencyLabel.text = loan.Currency.Value;
cell2.[![valueLabel][1]][1].text = loan.LoanAmount.Value.stringValue;
cell = cell2;
}
return cell;
}
http://i.stack.imgur.com/An6G2.png
Here is how you would configure two tableViews in one viewController (this can work with 2 or more tableViews).
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == yourFirstTableView {
return yourFirstArray.count
} else {
return yourSecondArray.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == yourFirstTableView {
let cell1 = tableView.dequeueReusableCellWithIdentifier("yourFirstCellReuseIdentifier", forIndexPath: indexPath) as! YourFirstCustomTableViewCell
// Configure the cell for your first tableView
return cell1
} else {
let cell2 = tableView.dequeueReusableCellWithIdentifier("yourSecondCellReuseIdentifier", forIndexPath: indexPath) as! YourSecondCustomTableViewCell
// Configure the cell for your second tableView
return cell2
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if tableView == studentsTableView {
// Perfrom action for your first tableView
} else {
// Perfrom action for your second tableView
}
}
I am not exactly sure what you are trying to do. Maybe try using a ContainerViewController and embedding two TableViewControllers into that. This should give the effect of having two TableViews in one ViewController but you will have separate files for each TableViewController.

Highlight TableView Cell's TextLabel text colour

I am using a popover tableview in my project. I want to change the tableview cell's text colour from grey to red on selection. And i also want the highlighted color to remain red when the popover tableview is loaded next time like left menu selection. Need help to do this. I have provided the code for the popover tableview.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView === tableViewPopOver {
let cell = UITableViewCell(style: .Default, reuseIdentifier: nil)
cell.textLabel?.text = FeedFilter.allValues[indexPath.row].rawValue
if indexSelected == indexPath.row {
cell.textLabel?.textColor = UIColor.redColor()
} else {
cell.textLabel?.textColor = UIColor.lightGrayColor()
}
//cell.selectionStyle = .None
return cell
}
let cell = tableView.dequeueReusableCellWithIdentifier(kDreamFeedTableViewCell, forIndexPath: indexPath) as! DreamFeedTableViewCell
cell.selectionStyle = .None
let dream = self.arrayDreams[indexPath.row]
cell.dream = dream
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if tableView === tableViewPopOver {
//tableViewPopOver?.cellForRowAtIndexPath(indexPath)?.textLabel?.highlightedTextColor = UIColor.redColor()
//selectedIndexPath = indexPath.row
let cell = tableView.cellForRowAtIndexPath(NSIndexPath.init(forRow: indexSelected, inSection: 0))
cell?.textLabel?.textColor = UIColor.lightGrayColor()
let cell2 = tableView.cellForRowAtIndexPath(indexPath)
cell2?.textLabel?.textColor = UIColor.redColor()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
indexSelected = indexPath.row
self.popover.dismiss()
NRLoader.showLoader()
self.searchDreams(true)
}
else { // dream feed tableview
tableView .deselectRowAtIndexPath(indexPath, animated: false)
let dream = self.arrayDreams[indexPath.row]
if !isValidUser(dream.user) {
return
}
if isCurrentUser(dream.user)
{
self.pushToUserDreamViewControllerForDream(dream)
}
else
{
tableView .deselectRowAtIndexPath(indexPath, animated: false)
self.pushToFeedDetailViewControllerForDream(dream)
}
}
}
I see a problem with your code relate to tableViewPopOver. If you set selection style is .None. You can't select cell.
With your problem I can suggest for you two way to resolve:
If you want use cell.textLabel?.highlightedTextColor you will have face a problem: background of cell will be grey or blue depend on style selection you select. If you can accept it. You can implement like this:
You create a variable to hold a cell selected. Maybe it is int value like var indexSelected = 3. And when you implement cellForRowAtIndexPath you should implement like this:
cell.textLabel?.text = FeedFilter.allValues[indexPath.row].rawValue
cell.textLabel?.highlightedTextColor = UIColor.redColor()
if indexPath.row == indexSelected {
tableView.selectRowAtIndexPath(indexPath, animated:true, scrollPosition: .None)
}
return cell
And in didSelectRowAtIndexPath you update indexSelected:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
indexSelected = indexPath.row //update selected row
}
If you don't want cell background change color. You can choose this way. You should create variable like the way above. But in cellForRowAtIndexPath you should implement:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")//init cell it depend on your way create cell
cell?.textLabel?.text = "Your text"
if indexSelected == indexPath.row {
cell?.textLabel?.textColor = UIColor.redColor()
} else {
cell?.textLabel?.textColor = UIColor.lightGrayColor()
}
return cell!
}
and in didSelectCellAtIndexPath you should implement:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(NSIndexPath.init(forRow: indexSelected, inSection: 0))
cell?.textLabel?.textColor = UIColor.lightGrayColor()
let cell2 = tableView.cellForRowAtIndexPath(indexPath)
cell2?.textLabel?.textColor = UIColor.redColor()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
indexSelected = indexPath.row //update selected row
}
Here Demo: Demo
Hope this help!
To change cell's text colour to red on selection you need to implement didSelectRowAtIndexPath and change the cell text Color to red, but it will not stay red when you open it the next time. to handle that you need to have a member variable selectedIndexPath. So it will be something like this
var selectedIndexPath:NSIndexPath!
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.textLabel?.highlightedTextColor = UIColor.redColor()
selectedIndexPath = indexPath
}
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.textLabel?.highlightedTextColor = UIColor.grayColor()
selectedIndexPath = nil
}
}
And to load the table next time with the selected cell red text colour you need to add this line in your cellForRowAtIndexPath
Cell
cell.textLabel?.highlightedTextColor = indexPath == selectedIndexPath ? UIColor.redColor() : UIColor.grayColor()
}

Multiple TableView Row Select - Swift

I am using Swift. I have a tableView, and i want the user to select multiple selects. When the user taps on a row i want it to be highlighted and then allow them to select more rows.
My code is as follows:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
var allCreditCard : AllCreditCard
allCreditCard = self.creditCard[indexPath.row]
cell.textLabel?.text = allCreditCard.bankName
// if(cell.selected){
// println("cell selected at \(indexPath.row)");
// let imageName = "tick.png";
// let image: UIImageView = UIImageView(image: UIImage(named: imageName));
// cell.accessoryView = image;
// }else{
// println("cell was NOT selected. Index path----- \(indexPath.row)");
// let image: UIImageView = UIImageView();
// cell.accessoryView = image;
// }
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
How can i solve this. I am not sure how to add the rowIndexes and then populate the table with the updated rows. Can someone help me here.
Take one array and add all selected indexPath.row in it on didSelectRowAtIndexPath
and in cellForRowAtIndexPath check for all the objects in that array and set AccessoryType of cell as UITableViewCellAccessoryCheckmark,
if (selectedIndex==indexPath.row) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
you can do it in swift, logic is the same

Unabled to change UITableViewCell properties

I'm trying to change the accessory view / accessory type of my table view cells, but it doesn't work.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell?
switch indexPath.row {
case 0:
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "enabledCell")
cell!.textLabel?.text = "Alarm enabled"
var enabledSwitch = UISwitch(frame: CGRectZero)
cell!.accessoryView = enabledSwitch
case 1:
cell = self.tableView.dequeueReusableCellWithIdentifier("calendarCell", forIndexPath: indexPath) as? UITableViewCell
cell!.textLabel?.text = "Calendar"
cell!.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
default:
cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as? UITableViewCell
cell!.textLabel?.text = "Oops"
}
return cell!
}
I am not sure why this isnt working for you. I created a new project. Made a ViewController with a tableView in it and copied/pasted your code. Works. I get 1 cell with a switch, another with a disclosure, and one with no accessor. Is your table working at all? If your app just crashes maybe your reuseIdentifiers are misspelled or something. Maybe you didnt link your tableView to your ViewController as the delegate/datasource. Good Luck!
import Foundation
import UIKit
class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var cell: UITableViewCell?
switch indexPath.row {
case 0:
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "enabledCell")
cell!.textLabel?.text = "Alarm enabled"
var enabledSwitch = UISwitch(frame: CGRectZero)
cell!.accessoryView = enabledSwitch
case 1:
cell = self.tableView.dequeueReusableCellWithIdentifier("calendarCell", forIndexPath: indexPath) as? UITableViewCell
cell!.textLabel?.text = "Calendar"
cell!.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
default:
cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as? UITableViewCell
cell!.textLabel?.text = "Oops"
}
return cell!
}
}

Resources