This is the flow of my app:
First, the TableView is set to hidden. There is a UITextField in the center of the screen. When the user types something and hits Go, this code is run:
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5, animations: {
self.textFieldConstraint.constant = -230
self.tableView.hidden = false
self.goButton.hidden = true
self.view.layoutIfNeeded()
}, completion: nil)
At this point, the tableview is populated. When a row is selected, I need to manipulate the data that is populating it.
However, absolutely nothing happens when I tap a cell.
What am I doing wrong?
My TableView code is here:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: SearchResultsTableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! SearchResultsTableViewCell
cell.label.text = searchResultsNames[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchResultsUrls.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("HELLO")
}
And, I have set the dataSource and delegate properly.
I also want to clarify that the tableView populates and scrolls properly; it just won't do anything when I tap a cell.
Update:
I've discovered that for some reason, I can select the cells when I press and hold them. It is not what I want, so does anybody know how to fix this?
I have just used your code to create a simple table, selection is working fine and logging out HELLO as expected. Can you check the values of Selection in the attributes inspector? Here is mine, which has Selection set to Single Selection.
And here is the code I used for my simple table
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var searchResults = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
searchResults.append("Testing 1")
searchResults.append("Testing 2")
searchResults.append("Testing 3")
searchResults.append("Testing 4")
searchResults.append("Testing 5")
tableView.dataSource = self
tableView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("tableCell", forIndexPath: indexPath)
cell.textLabel?.text = searchResults[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchResults.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("HELLO")
}
}
I also tried hiding and showing the tableView which made no difference on selection.
EDIT & SOLUTION:
In the comments below, we discovered that the issue is related to a tapGestureRecogniser on the view, This was identified by the op only being able to make a selection by holding a tap on the cell. The gesture has to fail before the selection can be made, the op managed to solve the problem by referring to this other SO Answer
if you use "tap" gesture, you can't select table cell. (but, if you click and drag to right a cell, you can select it.)
Check gesture first.
And if your code has self.tableView.allowsSelection = false, replace false to true or delete this line.
My problem has been caused by the tap gesture recognizer on the view controller itself (I had BaseTableViewController I was extending from). Probably it was interfering with the gesture recognizers of UITableView.
In your viewDidLoad, or wherever you set up your view, make certain that your table view even allows selections. That can be controlled with the allowSelection property.
Something like:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.allowsSelection = true
}
If you have a gesture recognizer, just type gestureRecognizer.cancelsTouchesInView = false
For me I was implementing another did select row method, so I erased it and typed "didSelect..." and selected the first one in the suggested methods, which is this for swift 3:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Row #: \(indexPath)")
}
Try disabling and then enabling the user interaction Enabled property in the attribute inspector of your tableView
Looks something like this
I met the same problem as you and solved it by removing the below code
self.view.layoutIfNeeded()
you can try it.
Related
I am new to swift and I have this app in mind that basically needs to update all the cells based on the data received from one of the cells.
I am using dynamic cells and each one has a textfield inside.
TableViewController.swift:
import UIKit
class MyCells: UITableViewCell{
#IBOutlet weak var value_textfield: UITextField!
}
class TableViewController: UITableViewController {
var units_length: [String] = ["Centimeter", "Meter", "Foot"]
override func viewDidLoad() {
super.viewDidLoad()
units_length = units_length.sorted()
self.tableView.keyboardDismissMode = .onDrag
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return units_length.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = units_length[indexPath.row]
cell.textLabel?.textColor = UIColor.white
cell.textLabel?.font = UIFont(name:"DINAlternate-Bold", size:30)
return cell
}
override func viewWillAppear(_ animated: Bool){
tableView.rowHeight = 100
}
}
Which function should I use to access all the cells with different identifiers and simultaneously update all the textfield inside each cell?
I do have access to the textfield by having another class called MyCells, how should I implement it?
(I will not include the base ViewController class here as there's nothing inside)
Thanks!
Normally you use the function you already showed: cellForRowAt. You update your model data, tell the table to reloadData, cellForRowAt is called for all visible cells, and their values become the new values.
However if you are updating after every character, I would set up a notification broadcast situation and update all visible text fields and the model together without a reload. Just make sure the model and the table stay in sync in case the user scrolls and cellForRow is called.
I have an iPad TabBar navigation app and in OrderViewController I have a tableview on left side and outlets on the right side of the view as in a sort of split view controller. When you click a tableView's cell it shows details on the other half screen. As I'm introducing two different color schemes for A/B testing, I use a switch to perform the change in color. The color switching dough doesn't succeed with tableView's cells. Adding a reloadData() in viewWillAppeardidn't solve the problem.
Everything gets updated except for the cells, they maintain the colors of when they got created the first time.
I added prints throughout the phases and I detected that cell's awakeFromNimbgets called only the first time. How do I get it to be called on tableView.reloadData()? As always many thanks.
awakeFromNib():
override func awakeFromNib() {
super.awakeFromNib()
configureUi()
}
viewWillAppear():
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.configureFetchedResultsController()
orderTableView.delegate = self
orderTableView.dataSource = self
configureUI()
orderTableView.reloadData()
}
Use the tableView delegate willDisplayCell
https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614883-tableview
class MyCustomVC: UITableViewDelegate {
override func tableView(_ tableView: UITableView,
willDisplay cell: UITableViewCell,
forRowAt indexPath: IndexPath) {
guard var cell = tableView.dequeueReusableCell(withIdentifier: "yourReuseIdentifier", for: indexPath) as? YourCustomCell else {
return UITableViewCell()
}
cell.configureUi()
}
}
I have UITableView in a test project that is created this way:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.delegate = self
tableView.dataSource = self
}
// height?
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//return cellHeightWithoutSeparator + cellSeparatorHeight
//print("YES!")
return 80 // arbitrary
}
// table wants a UITableViewCell for each row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
// customize cell here
return cell
}
// how many rows?
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 50 // arbitrary
}
}
The structure of the table view is:
So, as you can see the cell contains a button.
I want the button (or any clickable view that is a subview of the cell) to respond immediately to the touch-down event and so I unchecked "Delay Touch Down" in the ScrollView property inspector in the storyboard.
It is my understanding that unchecking that box is equivalent to the code:
tableView.delaysContentTouches = false
According to the docs, this method is supposed to work on IOS 2.0+
But setting this property true or false only works as expected on IOS 11 and 12, but on IOS 10 (and presumably earlier), it is as if the box was never unchecked and touches on the button are still delayed.
I understand that it is still possible to make views "clickable" in the cell, and respond immediately to "touch up inside," (because the touch-up event will cancel the delay on the touch-down), but I still want the touch down event to call immediately (on all iOS versions, not just 11+) because:
1) I want the re-order control to respond immediately.
2) I want to have visual feedback for touch-down be normal/immediate on views in the cell.
I have also consulted this similar, but not the same, question which was written 4 years ago, and I tried applying the answers, but none of those answers seem to apply to whatever the modern day reason for this problem is.
Does anyone know the cause and (preferably Swift) solution to this?
I have a RootViewController that embeds a container that contains a table:
I'd like the garbage can icon on the top left of the RootViewController to enable editing mode for the embedded table view. I would like them to show up as checkboxes so that I can select multiple rows at once and then press "Delete" to delete all of the selected ones.
How would I do this?
Hopefully your class already conforms to UITableViewDelegate like so:
class MyViewController: UIViewController, UITableViewDelegate
In viewDidLoad(), you would need to have:
myTable.delegate = self
Then you can hook up the trash can icon to an IBAction that sets the table to editing mode:
#IBAction func myTableSetEditing(sender: AnyObject) {
myTable.setEditing(true, animated: true)
}
Then, as we see in an answer here: Select multiple rows in tableview and tick the selected ones, in viewDidLoad() put:
self.tableView.allowsMultipleSelection = true
and to get your checkmark, implement:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.Checkmark
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.None
}
I am trying to learn swift which is also my first programming language. I am trying learn by creating an app with table view in it. I have added a table view and table cell(myCell as identifier). Table cell in turn has labels and text field. Also the background color of the table cell is yellow.
The view controller which encapsulates all this is hooked to class showDetailViewController as show below.
class showDetailViewController:UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: TaskCell = tableView.dequeueReusableCellWithIdentifier("myCell") as TaskCell
return cell
}
//UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
When I run my application I expect to see my cell replicated 5 times (as number of cells in section returns 5) in table view but upon debug I realized that the no tableview delegate class get invoked and hence the issue.
Can anyone please help me with this issue?
Thanks,
Dev
Add the tableView as an IBOutlet.Then you should set tableView's datasource to viewController. self.tableView.dataSource = self. You can also set tableView's dataSource in Interface bulider.