I have two UITableViewCells and displaying them based on condition in
cellForRowatIndexPath. Both cells related to a creation of a post and than displaying them in UITableView.
In cellForRowAtIndexPath method i don't have any issues to use condition to display cell.
For example:
if postType[indexPath.row] == "Regular" {show this sell }
else {show another}`
This is working perfect. postType array is created during the post creation.
The issue that i have is to show a proper cell outside of cellForRowAtIndexPath method.
I have a button and when user click on it they would be going to the proper cell, just like they would click on the cell it self. However I don't know how to condition an array at proper indexPath or maybe there other way. I'm not that good because just starting out to learn swift.
I can do for a one cell but i want a condition first and than display a proper cell.
This statement works for a one cell.
#IBAction func usernameBtn_click(_ sender: AnyObject) {
let i = sender.layer.value(forKey: "index") as! IndexPath
let cell = tableView.cellForRow(at: i) as! postCell
}
In my case I have two cells. How to have a condition based on post type value in array and have a proper index inserted to check the value and than display a cell.
I have these two cells:
let cell = tableView.cellForRow(at: i) as! postCell
let cell = tableView.cellForRow(at: i) as! moreinfoCell
Any suggestion would be helpful.
You mention that the button does the same as if the user selects the cell so if you have that working just deselect "User Interaction Enable" of your button.
In interface builder:
Programmatically:
button.isUserInteractionEnabled = false
Doing that the touch will be done on the UITableViewCell and the didSelectRowAt indexPath: method will be fired.
Related
I tried to access custom tableView cell textfield from outside tableView like this :
for i in 0..<NameCounter {
let indexPath = IndexPath(row: i, section: 0)
guard let cell = sampleTableView.cellForRow(at: indexPath) as? sampleCellView else{
return
}
if let text = cell.txtName.text, !text.isEmpty {
let value = text
print("Getting NameText : \(value)")
}
if let text = cell.txtNote.text, !text.isEmpty {
let value = text
print("Getting noteText : \(value)")
}}
But the problem is above method you can only get visible cell of tableView except cell is nil. and because I guard it to avoid nil cell, I did not get all textfield value.
If I remove the guard like this :
let cell = sampleTableView.cellForRow(at: indexPath) as! sampleCellView
It will crash and got some cell is nil.
How to access all textfield value from outside tableView and got all cell (cell maynot nil)?
I have multiple tableView, and inside each tableView cell, I put txtName and txtNote. I want to detect which txtName and txtNote is being edited, so I can put in the right model.
note: txtName is textfield and txtNote is textView
You shouldn't rely on the values being taken from the cell labels, text fields etc.
Once a cell goes off-screen - it gets thrown to a pool for later reuse, and it may even get deallocated.
You should keep the view state inside some array, and then you can SAFELY get any value at any index.
If you have 1000 cells, perhaps only 10-20 will be visible at any time, and maybe 40-50 or so in the reusable cells pool. If you are at index path row 100 - obviously the cells after index path row 150 will be nil.
This return
let cell = sampleTableView.cellForRow(at: indexPath) as! sampleCellView
nil and crash for any cell that's not visible as of the fact that the table cells are reusable , you need to save the user typing for each cell to model ( tableView dataSource array ), then get the values from it
var model = [String]()
// inside cellForRowAt
cell.textView.delegate = self
cell.textView.tag = indexPath.row
}
#objc func textViewDidChange(_ tex: UITextView) {
model[tex.tag] = tex.text!
}
class VC:UIViewController,UITextViewDelegate {
As a good standard practise, there should be no need to get values from the UITableViewCells. You should instead get the values from the Model that is presented in the UITableView, based on some logic as per the need.
Further, when it is needed to access any text that was typed on UITableViewCell, then it should be updated in the associated model first and should be accessed from there.
Behind the scene UITableViewCell are re-used and only the cells currently visible will show you actual data if you access it from UITableView. Hence persisting cell's entered values to some array / dictionary for later use is the option.
I have an application wherein when tableview cell is clicked, another tableview is loaded and an api call is made. Based on the response from api, table view list is loaded and when a particular item in the second tableview is selected, there is a selected checkbox displayed just besides the tableview text label and at the same time database is updated with selected value,
so when I come back to the first tableview I display a label with selected item.
When the first tableview cell I clicked, api is called and results of api should be compared with the active list from database and that particular cell should remain selected.
When there is some item selected in first tableview and when i click on that particular cell, api results reload the tableview and selection for respective cell is not displayed.
Following is the code:
for selectedDict in (appDelegate?.selectedCategoryFilterArray)! {
let selectedUuid = selectedDict.categoryUuid
print("selectedUuid\(selectedUuid)")
for allDict in self.requestedFiltersArray!{
let allUuid = allDict.objectForKey("uuid") as? String
if selectedUuid == allUuid {
cell.imgSelected.image = UIImage(named: "radio_selected")
continue
}else{
cell.imgSelected.image = UIImage(named: "radio")
}
print("allUuid\(allUuid)")
}
}
This is not working as expected, no cell is displaying as selected even if their is a cell selected.
Where have you placed this code?
From what I think you might be trying to achieve, here is an approach that I would suggest.
For your second tableView which is loaded based on the API call results, I would add a String property called uuid to your custom UITableViewCell class.
Then when you call cellForRowAtIndexPath to populate your second tableView, instantiate each cell as your custom UITableViewCell and set its uuid property to the appropriate value based on the results array, using the indexPath.row.
After setting that, next you can run the for loop with your condition to match the cell's uuid property value against the selectedUuid value from your AppDelegate and thereafter set the image as per the logic.
A rough implementation:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") as! YourCustomTableViewCell
let allDict = self.requestedFiltersArray[indexPath.row]
let allUuid = allDict.objectForKey("uuid") as? String
cell.uuid = allUuid
for selectedDict in (appDelegate?.selectedCategoryFilterArray)! {
let selectedUuid = selectedDict.categoryUuid
if selectedUuid = cell.uuid {
cell.imageSelected.image = UIImage(named: "radio_selected")
} else {
cell.imageSelected.image = UIImage(named: "radio")
}
}
}
I have created a tableview prototype cell in storyboard and I have added a button to cell and set its tag to indexpath.row. When I scroll my cells the scrolled cell on the top of tableview always set tag to zero instead of correct tag.
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("autoLoadReuseIndentifier", forIndexPath: indexPath)
print("indexpath :\(indexPath.row)")
cell.contentView.viewWithTag(100)?.layer.cornerRadius = 5
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
let tempDict : NSDictionary = savedCardsArray.objectAtIndex(indexPath.row) as! NSDictionary
let bankName = cell.contentView.viewWithTag(102) as! UILabel
deleteButton = cell.contentView.viewWithTag(106) as? UIButton
deleteButton?.tag = indexPath.row
deleteButton?.addTarget(self, action: "deleteCard1:", forControlEvents: UIControlEvents.TouchUpInside)
print("delete button:\(deleteButton)")
// print("indexpath delete tag :\(deleteButton.tag)")
if(self.isSetUpAutoloadSelected){
deleteButton?.hidden = true
}else{
deleteButton?.hidden = false
}
return cell;
}
Whenever I scroll the cells, delete button tag is always set to zero.
If you should go with other way so use follow code and get indexPath.
func deleteCard1(_ sender:deleteCard) {
let buttonPosition:CGPoint = sender.convert(CGPointZero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
}
I think you don't need to follow this approach because firstly you set button tag statically in storyboard and again you are change it's tag in cellforrowatindexpath so when you scroll, cell will never find button with tag 106.If you want to follow this approach then you need to create customButton and add Variable of type NSInteger or whatever you want and store indexpath.row into that variable of customButton.
Another Approach is Create CustomTableViewCell Class and create button outlet in this custom Cell class and set indexpath.row into button tag like this
CustomCellClassObject.buttonName.tag = indexPath.row
As Sumit said, it’s better to use a custom cell and create outlet for the buttons and labels, as fetching sub views using tags will be tough to maintain the code in the future.
Additionally, you don’t have to create the variable deleteButton, as I don’t see a valid purpose.
Assign tag to the button and add target in cellForRowAtIndexPath, it should work fine.
I’m trying to get data associated with the UITableViewCell where a UIImageView is clicked within the cell. The code I currently have to capture the click event is working fine. However, once I get into the click function that is called, I’m unable to retrieve the associated data from the same UITableViewCell where the UIImageView was clicked. Here is the code I'm using to set up the click event. This code is contained in cellForRowAtIndexPath:
var tap = UITapGestureRecognizer(target: self, action: Selector("staticMap_click:"))
cell.imgStaticMap.addGestureRecognizer(tap)
cell.imgStaticMap.userInteractionEnabled = true
Here is the function staticMap_click that gets called when the UIImageView is clicked:
func staticMap_click(sender:UITapGestureRecognizer)
{
let rowData: NSDictionary = self.arrayPosts[sender.valueForKey("row") as Int] as NSDictionary
mdblStaticLat = rowData["dblLat"] as String
mdblStaticLong = rowData["dblLong"] as String
self.performSegueWithIdentifier("sgShowMapFromStaticClick", sender: self)
}
As you can see, I'm unsure of how to reference the data for the row that was clicked. I attempted setting a tag on the UIImageView, but that didn’t work. I also attempted to set a tag on the UITapGestureRecognizer, but I haven’t been able to get that to work either.
Does anyone know how I can reference the data from the selected row where the UIImageView is tapped?
You might be interested in
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
This function will be called whenever a cell is pressed.
You can access the row which is pressed by using indexPath.row
Furthermore you can use
func staticMap_click(sender:UITapGestureRecognizer){
let tappedView = sender.view as? UIImageView
let indexPath = (tappedView.superview as UITableView).indexPathForCell(self)
}
To get the cell which was tapped if you want only the Image to be tapable
This code will also return an indexPath, you will be able to use indexPath.row again to get the row.
Getting the row will enable you to get data out of an array if deemed necessary
can anyone please help me with how to access a specific cell with its tag or text label, i have a table view with a list of buttons above, those buttons filed with the thumbnail of the cell when ever the cell was clicked then also the background of the cell goes red.
when i click on the cell once again - when its red - the background goes white - default - also the thumbnail removed from the button above.
also when i click on the button the photo in it should disappear as well as the background of the cell itself, it should go white. and thats what i couldnt do .. can anyone help me with that, how to access the the cell to change its background when the cell.tag or cell. texlabel.text is given.
thanx in advance
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = myTable.dequeueReusableCellWithIdentifier("intrest") as UITableViewCell
cell.tag = indexPath.row + 1
cell.textLabel?.text = InterstArr[indexPath.row]
var img = UIImageView(frame: CGRect(x: 10, y: 3, width: 40 , height: 40))
img.image = UIImage(named:"\(InterstArr[indexPath.row]).png")
cell.selectionStyle = UITableViewCellSelectionStyle.None
cell.indentationLevel = 1
cell.indentationWidth = 45
cell.addSubview(img)
return cell
}
I did it with the help of #natuslaedo ... i just stored the value of the index path when i clicked on the row .. then in my if statements to check on the 5 buttons above and deselect them, i took the indexpath stored and accessed the cell to change its color ... i initialise the index paths variables like this var firstIP:NSIndexPath!
First of all, add the following line to your didSelectRowAtIndexPath: function:
yourTableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: UITableViewScrollPosition.None)
And target selector for your button is like as follows:
func buttonPressed(sender: UIButton!) {
// Code to remove photo from your button
// ......
// To remove background effect of cell
let indexPaths:Array<NSIndexPath> = yourTableView.indexPathsForSelectedRows() as Array<NSIndexPath>
// If you have implemented your own class which inherits from UITableViewCell, use its name while type casting and explicit typing
for indexPath in indexPaths {
let cell:UITableViewCell = yourTableView.cellForRowAtIndexPath(indexPath) as UITableViewCell!
// REMOVE BACKGROUND EFFECT HERE (using cell)
}
}
You shouldn't be trying to match on tag or text content, everything should be based on row or index path so that it correlates back to your data model.
Consider creating a custom class for your button data storage so you have an array with one entry per button and the class holds the index path of the associated cell, the image, etc. Then, when a button is clicked it's easy to update your main data model and the cell (if it's visible).
You can get the indexPath of cell in click event this way,
func buttonClick(sender:UIButton)
{
let position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
if let indexPath = self.tableView.indexPathForRowAtPoint(position)
{
println(indexPath.row)
println(indexPath.section)
}
}
Another way to match buttons in a cell with your data model is to store the indexPath of the cell with the cell. When the button is tapped, your target method which is a method on the cell, will get called and you can use the indexPath and pass it up to your data model using a delegate call.
I'd give you more details but I am not sure if that is what you are asking.