I am using the self sizing cell feature and it works well until I want to hide a cell completely. I moved away from heightForRowAtIndexPath for this and I setup the following:
override func viewDidLoad() {
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 0
}
However when I have no text for a tableviewcell to render I get the following message:
Warning once only: Detected a case where constraints ambiguously
suggest a height of zero for a tableview cell's content view. We're
considering the collapse unintentional and using standard height
instead.
I really just need a way to hide / show content dynamically. I am using a static tableview for this, so maybe I am approaching this wrong?
I found the solution.
First, for a static table to use self sizing correctly, you can only have one label per table cell. I was trying to put in a lot of content into a cell and only the first label would size the cell. I could be wrong about the rule of one label per cell, and the problem might be constraints / auto layout related. I've watched the WWDC video on this, and the way I had it setup, should have worked with my existing constraints, as they where set to the contentView of the cell.
Secondly, the UI updates needed to be coupled with begin and end rules, and a reload.
tableView.beginUpdates()
//-- You Table UI changes
tableView.reloadData()
tableView.endUpdates()
You can also replace reloadData with reloadRowsAtIndexPaths to be specific to the rows to update, but my instance required all rows to be updated.
I had a similar problem some time ago. I would use dynamic cells, and remove the hidden cells in
numberOfRowsInSection
and in
cellForRowAtIndexPath
You should try to add a property, like "hidden" in your cell content array, and check when you load/reload your data. That works (of course) still fine with Autolayout.
Related
Since macOS 10.13 we can use NSTableView with automatic row heights, thanks to the new property usesAutomaticRowHeights and of course auto layout. This works quite nicely.
But when the user resizes a column, the calculated heights are no longer correct, and gaps appear in the tableview cells.
Is there a proven way to update the row heights after column resize in this scenario?
I already tried methods like updateConstraintsForSubtreeIfNeeded(), updateConstraints(), setNeedsDisplay(), reloadData() and so on, but nothing works.
If you use NSTextField's in your design, make sure the Desired Width setting of each NSTextField with dynamic height, is set to Automatic. This setting is located in the Size Inspector.
Changing this resulted in automatic recalculation of the tableview row heights.
Something that worked for me was to include the tableViewColumnDidResize notification method in the NSTableviewDelegate. There you can call the noteHeightOfRows method of the table view. Here is an implementation:
//Recalculate when the screen moves
func tableViewColumnDidResize(_ notification: Notification) {
let allIndex = IndexSet(integersIn:0..<self.YOURTABLE.numberOfRows)
YOURTABLE.noteHeightOfRows(withIndexesChanged: allIndex)
}
Here are the links to the documentation: tableViewColumnDidResize and noteHeightOfRows
In iOS you could use:
self.tableView.rowHeight = UITableViewAutomaticDimension
to achieve automatic height adjustment of cells.
Is there any way to achieve this behaviour in macOS with NSCollectionView or NSTableView?
Talking about NSTableView... As of El Capitan there was no easy way to do this. Not sure about new Sierra SDK.
From my experience, the most reliable way to regulate table row's height is to use NSTableViewDelegate method:
func tableView(tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
//Here you do some magic measuring actual content of the cell and returning heigh
}
The only positive thing is that some controls have: fittingSize property and can simplify process.
Also, dynamic content change will require you to call noteHeightOfRowsWithIndexesChanged method of table view, to cause that delegate method be called again where your code will recalculate new height.
With macOS 11 and newer, the situation is as follows:
NSTableView can now actually use auto layout to achieve automatic height adjustment of cells. You must properly configure your cell template(s) to use auto layout, and you must instruct the table to use auto layout (can also be done in the storyboard) for row height calculations:
tableView.usesAutomaticRowHeights = true
NSCollectionView is currently (2021) still behind in features compared to the iOS counterpart, and still doesn't support any tableview feature like automatic row heights.
I am having trouble understanding how to embed my view into a scroll view with a dynamic height. I have managed to create scroll views before, but only with a static height. How would an iPhone application, such as Facebook or Instagram, for example, manage to create a scroll view for an entire feed of dynamic-height data. To this point I have used storyboards to create the scroll views, but I am assuming that this done in code would be much better.
class connectDetailsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//set up variables with data
fillData()
}
override func viewWillAppear(animated: Bool) {
let nameTitleString = String(businesses[businessNum]["name"]!)
nameTitle.text = nameTitleString
processTimes() // Adds information for the hours of operation, if applicable
processDetails() //Adds information for the details if possible (a few sentences to a few paragraphs)
}
}
processDetails() and ProcessTimes() will edit the content in a stack view, how can I create a scroll view to encompass both of these stack views at the correct height?
Generally, for providing a feed of content such as a Facebook timeline you would likely use a UITableView as it manages the reuse of cells and the overall contentSize internally using it's delegate methods on the dataset to determine number of rows, estimated row heights and so on. The tableView actually uses a scrollView to acheive this but it handles it internally.
In my opinion this would be your best approach, to do this without using a tableView you would need to replicate alot of the logic that it performs on your behalf.
The main thing to remember with a scrollView is that it can load content that is larger than the scrollView, and then manages scrolling/panning/zooming to allow you to view the larger content.
If you just wanted to know how to do this yourself, you would likely need a parent container in the scrollview and then you would keep adding new views into it, adjusting the scrollViews contentSize height each time you add new content
I am Creating a tableview using custom cell with textfield. When i enter text in tableviewcell textfield and when i scroll the tableview the data is changing . Means re painting cells . How can i stop reloading cell on drag or scroll in IOS 8 swift
Thanks
If your want your cell not re-used, try to make it a subclass of UITableViewCell with a unique identifier, and do not use the identifier with other cells. I haven't test it yet, just hope it will solve your problem.
Ps. If the textfield's text is still overwritten, make a check at the cell's class file (like making an if-else statement checking if the textfield's text is empty).
Detailed workflow:
In cellForRowAtIndexPath(), after you dequeue the cell, normally you will set some property of your custom cell to refresh the data it holds. To implement this, you need to add a didSet observer on the property at the cell's class file. To achieve the goal you want, you can also add the checking code in the didSet observer.
In Your case. You need to customize your keyboard.
Add [Prev][Next] buttons on top of the keyboard and avoid scrolling.
Basically this idea is useful in form based app. May be your doing that kind.
And yes, Stop relaoding of cells is not good to app. If you will implement this. Apple will not approve your app. So avoid this kind of stuffs.
This is how cells work in a UITableView. The standard implementation of the cellForRowAtIndexPath: method dequeues cells and reuses them.
And ideally your app should save the text from the text fields and change the correct text in the cells depending on their indexPath in the same method's implementation.
If you do not want to do that, a dirty workaround would be to create a new cell every time in the cellForRowAtIndexPath: method instead of dequeuing rows.*
*Do not do this unless absolutely necessary. This is very bad coding practice
I need to create a view based tableview in Popover as specified below:
Tableview should be placed in Popover(Popover height should be same as tableview).
Each row should contain a view.
Each row view will contain 3 labels.
Labels should be auto re sizable based on its text height.
Based on 3 labels height, Cell row height should resize.
Based on all cell rows, tableview height should resize.
Based on tableview height, Popover should resize.
I have done this in a static format, but i need to do it in more dynamic format(in future i should be able to add more rows using same classes and methods).
Main problem i am facing is, i am unable calculate the size of cell view in tableView:heigthOfRow: since i don't know the text of labels in this point of time.
So i just created tableview cells in loadView itself and saved in array, and fetching from array in tableview delegate methods. But i think this is wrong way of doing so.
Note: All data to tableview will be given while loading the view itself. Labels are not editable.
Cocoa system resizes the subviews based on superview ,I think scenario that you are looking for is to resize super view based on subview size.
Following 2 solutions i can suggest right awyay,
1.You can choose to post notification upon size change in each subview and make immediate superview observe that.
2.Use globals for size of each subview in your case 3 labels, and have an API to calculate finalRect in your view of view based table view.
Hope this helps:) have a nice day.