multiple rows gets selected while selecting a single row on tableView - ios

am having this strange issue while am selecting any of the row from TableView another row is also get selected , say i have a tableView with multiple rows in my case its 11 and multiple selection with the accessory of tick mark is enabled (when i select a row a tick is marked on the selected row ) so when am selecting my first row , then row number 8 is also got selected (i can see the tick mark in the row number 8 but i selected only the row number 1 ) when i select another row number 2 my row number 9 is also get selected dont know why this is happening if anybody knows anything about this behaviour then please let me know it'll be so helpful for me , below is the code of didSelectRowAtIndexPath :
var selectedTextLabels = [NSIndexPath: String]()
var selectedTextLabelsName = [NSIndexPath: String]()
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let cell = tableView.cellForRowAtIndexPath(indexPath) as! UsersTableViewCell
if (cell.accessoryType == UITableViewCellAccessoryType.Checkmark){
cell.accessoryType = UITableViewCellAccessoryType.None;
selectedTextLabels[indexPath] = nil
selectedTextLabelsName[indexPath] = nil
}else{
cell.accessoryType = UITableViewCellAccessoryType.Checkmark;
if (cell.accessoryType == UITableViewCellAccessoryType.Checkmark){
if let Id = cell.channelIDLbl?.text {
selectedTextLabels[indexPath] = Id
}
if let channelName = cell.lblChannelname?.text{
selectedTextLabelsName[indexPath] = channelName
}
}
}
cellForRowAtIndexpath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UsersTableViewCell
if isFavoritesTabActive == true {
let object : RChannels = self.favoritesArray.objectAtIndex(indexPath.row) as! RChannels
cell.lblChannelname.text = object.channelName
let favorite = object.isFavorite
if favorite == "true" {
cell.favIcon.image = UIImage(named: "Favourite")
return cell }
else {
let object : RChannels = self.noteObjects.objectAtIndex(indexPath.row) as! RChannels
cell.lblChannelname.text = object.channelName
let favorite = object.isFavorite
if favorite == "true" {
cell.favIcon.image = UIImage(named: "Favorite")
}else {
cell.favIcon.image = UIImage(named: "unFavorite") }
return cell
}

checking inside the channelIDLbl array for existence of the cell's id at cellforRowAtIndexPath did the job
if ((selectedTextLabels[indexPath]?.containsString("\(cell.channelIDLbl)")) != nil){
cell.accessoryType = .Checkmark
}else {
cell.accessoryType = .None
}
for more detail please check this same question

Related

Multiple selection UITableView without dequeueReusableCellWithIdentifier

When selecting multiple cells in my tabeview the cells out of view are being selected too. I understand that this is because i am reusing the cell and its maintaining its selection as i scroll down. I have found a few people with similar issues but cant translate their solutions across to resolve my issue. I have tried not dequeing a cell and just use:
let cell = NewBillSplitterItemCell()
but get:
unexpectedly found nil while unwrapping an Optional value
on the line:
cell.currentSplitters.text = splitterList
in the following code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
fetchBillItems()
let cell: NewBillSplitterItemCell = tableView.dequeueReusableCellWithIdentifier("NewBillSplitterItemCell") as! NewBillSplitterItemCell
let item = allItems[indexPath.row]
let numberOfSplitters = item.billSplitters?.count
if numberOfSplitters == 0 {
cell.currentSplitters.text = "No one is paying for this item yet."
} else {
var splitterList = "Split this item with "
let itemSplitters = item.billSplitters?.allObjects as! [BillSplitter]
for i in 0...Int((numberOfSplitters)!-1) {
if numberOfSplitters == 1 {
splitterList += "\(itemSplitters[i].name!)"
} else {
splitterList += ", \(itemSplitters[i].name!)"
}
}
cell.currentSplitters.text = splitterList
}
cell.name.text = item.name
cell.price.text = "£\(item.price!)"
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
if cell.accessoryType == .Checkmark
{
cell.accessoryType = .None
selectedItems.removeAtIndex(selectedItems.indexOf(allItems[indexPath.row])!)
} else {
cell.accessoryType = .Checkmark
selectedItems.append(allItems[indexPath.row])
}
}
}
I dont quite understand what to do and any help would be great. Thanks
In addition to what #Mike said, inside of cellForRowAtIndexPath you need an additional check because cells get reused.
Something along the line
let isSelected = selectedItems[indexPath.row].selected
if isSelected{
cell.accessoryType = .Checkmark
} else {
cell.accessoryType = .None
}
Same thing inside of didSelectRowAtIndexPath you should update the data source instead of relying on the UI of your cell for that condition.
Assuming your cell is nil, you should use
let cell = tableView.dequeueReusableCellWithIdentifier("..." forIndexPath:indexPath) as! NewBillSplitterItemCell
instead of
let cell= tableView.dequeueReusableCellWithIdentifier("...") as! NewBillSplitterItemCell
This ensures that cell will never be nil.
Also, I would check if the correct identifier is being used in all of your .xib .storyboard files.

Cell not being displayed - "no index path for table cell being reused"

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("Wall Delegate: caso 2")
let cell = tableView.dequeueReusableCellWithIdentifier("you1on1Cell", forIndexPath: indexPath) as! OneToOneCell
let cell1 = tableView.dequeueReusableCellWithIdentifier("other1on1Cell", forIndexPath: indexPath) as! OneToOneCell
let newMessage = messages[indexPath.row]
if(newMessage.you == true){
if let picture = imageYou { cell.profilePictureyou.image = picture }
if let textmsg = newMessage.text {
cell.messageTextYou.text = textmsg
}
return cell
} else {
if let picture = imageOther { cell1.profilePicture.image = picture }
if let textmsg = newMessage.text { cell1.messageText.text = textmsg }
return cell1
}
I don't know what is the problem, this error is being showed up, however app is still running, but text is only displayed when I click on tableview with mouse on simulator - it is the first app I am developing and it is the first time I am using a table view with two different cell structure (however it is the same cell file). This is meant to be a chat.

How to get the textvalue of each dynamically created row in UITableView in swift

As shown in below image,i created a prototype cell with label and textfield in tableviewController.
Each row is created at runtime as shown below. When user clicks SAVE button all the details like Course detail,Registration id, Username and passowrd should be saved in respective varaibles. But it does not work. It stores value of last textfield in all variables.
How do i get text value in each row of the table.
// Row creation code
cell variable is global
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch(indexPath.row)
{
case 0 :
cell = tableView.dequeueReusableCellWithIdentifier("RegCell", forIndexPath: indexPath) as! RegCell
cell.configure("Course detail", txtValue: "Enter course.")
break;
case 1 :
cell = tableView.dequeueReusableCellWithIdentifier("RegCell", forIndexPath: indexPath) as! RegCell
cell.configure("Registration ID", txtValue: "Enter registration id.")
cell.txtIpValue.tag = 1
break;
case 2 :
cell = tableView.dequeueReusableCellWithIdentifier("RegCell", forIndexPath: indexPath) as! RegCell
cell.configure("Username ", txtValue: "Username")
cell.txtIpValue.tag = 2
break;
case 3 :
cell = tableView.dequeueReusableCellWithIdentifier("RegCell", forIndexPath: indexPath) as! RegCell
cell.configure("Password ", txtValue: "Password")
cell.txtIpValue.tag = 2
break;
default :
break;
}
return cell
}
// Save button code
func saveButtonClicked() {
if(cell.txtIpValue.tag == 1)
{
strCourse = cell.txtIpValue.text
}
if(cell.txtIpValue.tag == 2)
{
strID = cell.txtIpValue.text
}
if(cell.txtIpValue.tag == 3)
{
strUsername = cell.txtIpValue.text
}
if(cell.txtIpValue.tag == 1)
{
strPassword = cell.txtIpValue.text
}
}
// Regcell
class RegCell: UITableViewCell {
#IBOutlet var txtIpValue: UITextField
#IBOutlet var lblstr: UILabel
func configure(lblValue : String,txtValue :String)) {
lblstr.text = lblValue
txtIpValue.text = txtValue
}
}
All code is in swift. Please if possible give an example.
Iterate over all cells in your tableView.
Assuming you have only one section, try this:
Update : Using label texts as keys for the values - you might want to think about finding constant values for that
func save() {
var fields = NSMutableDictionary();
for rowIndex in 0...self.tableView.numberOfRowsInSection(0) {
let indexPath : NSIndexPath = NSIndexPath(forItem: rowIndex, inSection: 0);
let cell : RegCell = self.tableView.cellForRowAtIndexPath(indexPath);
fields.setObject(cell.txtIpValue.text, forKey: cell.lblstr.text)
}
// ... here fields will contain all values, using the lblstr.text as key
let username = fields["Username "];
}

Why is my SearchController not displaying the correct cell prototype for the first cell?

As the title suggests, I am having trouble with my UISearchController displaying the wrong cell prototype for the first cell in the search results.
Background Information: I have two cell prototypes, one without an image (identifier: basicCell) and another with a UIImageView (identifier: imageCell). Cells work perfectly when not searching.
Detailed Description of the Problem: When I click on the search bar everything is fine until I start searching for something. When I do, the first cell always has the imageCell identifier (a gray empty image view is shown denoting the lack of an image), no matter what. NB: Before searching anything, the first cell in the tableview has a custom image... Maybe that's of note?
Anyway I have no idea what I am doing wrong. Would anyone mind helping?
Code:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (self.resultSearchController.active) {
if hasImageAtIndexPath(indexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier(imageCellIdentifier, forIndexPath: indexPath) as! TimelineTableViewCellImage
let event = filteredTableData[indexPath.row]
cell.content.text = profile.content
cell.name.text = profile.name
//This is the image
cell.attachment.image = profile.image
cell.attachment.layer.cornerRadius = 1
cell.attachment.clipsToBounds = true
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(basicCellIdentifier, forIndexPath: indexPath) as! TimelineTableViewCell
let event = filteredTableData[indexPath.row]
cell.content.text = profile.content
cell.name.text = profile.name
return cell
}
} else {
if hasImageAtIndexPath(indexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier(imageCellIdentifier, forIndexPath: indexPath) as! TimelineTableViewCellImage
let event = events[indexPath.row]
cell.content.text = profile.content
cell.name.text = profile.name
cell.attachement.image = profile.image
cell.attachment.layer.cornerRadius = 1
cell.attachment.clipsToBounds = true
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(basicCellIdentifier, forIndexPath: indexPath) as! TimelineTableViewCell
let event = events[indexPath.row]
cell.content.text = profile.content
cell.name.text = profile.name
return cell
}
}
}
And this is my code that checks for an image:
func hasImageAtIndexPath(indexPath:NSIndexPath) -> Bool {
let event = events[indexPath.row]
let imageArray = [event.image]
for eventImage in imageArray {
if eventImage != nil {
return true
}
}
return false
}
You need to have an if-else clause in your hasImageAtIndexPath: function just like you have in your cellForRowAtIndexPath:. If the table view is the search table, then event needs to be defined the same way as you have in cellForRowAtIndexPath:,
func hasImageAtIndexPath(indexPath:NSIndexPath sender:UITableView) -> Bool
if (self.resultSearchController.active){
let event = filteredTableData[indexPath.row]
}else{
let event = events[indexPath.row]
}
let imageArray = [event.image]
for eventImage in imageArray {
if eventImage != nil {
return true
}
}
return false
}

Array: Swift and IOS

All,
Can you give me a source code of my below problem?
I have 100 user array and load that array value(username) in tableview.
Scenario:
When I click any tableviewcell, i store that value in new array( userArray) and also i have displayed right side discloser (checkmark).
But my problem is when i click again to deselect that user from tablecell my app has been crashed due to index out of bound.
I know problem is out of index, but how can i resolve that issue so if i click again on that tablecell it will remove user from userArray and i get new fresh userArray?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let tagValue = 100 + indexPath.row
let cell: UITableViewCell = tableView.viewWithTag(tagValue) as UITableViewCell
if cell.accessoryType == UITableViewCellAccessoryType.None
{
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
userToSendPost.append(self.users2[indexPath.row])
} else {
cell.accessoryType = UITableViewCellAccessoryType.None
let tempString = userToSendPost[indexPath.row] //tagvalue
let objcArray = userToSendPost as NSArray
let indexOfObject = objcArray.indexOfObject(tempString)
userToSendPost.removeAtIndex(indexPath.row)
}
}
sorry for my bad english.
You are approaching this incorrectly.
On the tableview set the property tableView.allowsMultipleSelection = true.
Then when you want to get the selected users...
let selectedIndexPaths = tableView.indexPathsForSelectedRows()
Then you can use the row property from those index paths to find the users.
var selectedUsers: [User] = []
for indexPath in selectedIndexPaths {
let user = theUsers[indexPath.row]
selectedUsers.append(user)
}
The multiple selection and the check mark is handled automatically by the tableview.
To follow your approach, I think this could help you ;)
But the approach of #Fogmeister is better !
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let tagValue = 100 + indexPath.row
let cell: UITableViewCell = tableView.viewWithTag(tagValue) as UITableViewCell
if cell.accessoryType == UITableViewCellAccessoryType.None
{
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
userToSendPost.append(self.users2[indexPath.row])
} else {
let tempUserString = self.users2[indexPath.row] // get your user string
if contains(userToSendPost, tempString) { // check if exist on your array
userToSendPost.removeObject(tempString) // remove it
}
cell.accessoryType = UITableViewCellAccessoryType.None
}
}
// If you want to use Array, add this method
extension Array {
mutating func removeObject<U: Equatable>(object: U) {
var index: Int?
for (idx, objectToCompare) in enumerate(self) {
if let to = objectToCompare as? U {
if object == to {
index = idx
}
}
}
if(index != nil) {
self.removeAtIndex(index!)
}
}
}

Resources