Resize TableCell on select/deselect - ios

I'm new to iOS and MonoTouch, and I have a pretty basic need - I have two vastly different views to display in the same table cell depending on whether it is selected or not. When you load the app I'll present a list of products in a custom UITableView, with all the rows deselected and each row basically just showing the product names in a label. As soon as a user taps one of the rows and selects it, I show a very different view with more of a shopping cart layout. Since the two views are so different they have vastly different sizes. What i need is for the cell itself (or row?) to grow and shrink according to the natural height of whichever view is currently being displayed.
I'm using descendants of UITableViewController, UITableViewSource, and UITableViewCell for the solution. What I do is add both versions to the cell's ContentView, then set the Hidden property as needed when the cell/row is selected/deselected to show the right layout. That works well. I'm in demo mode right now, so I'm not overly worried about efficiency or responsiveness, that will have to come later.
I know that GetHeightForRow is responsible for sizing the rows but it only gets called once, when the cell is first shown. It seems to me that I need to alert the TableView to re-poll the source for a new size as the views are changing, but I can't figure out how to do it.
I tried (rather hopefully) to cause GetHeightForRow to be invoked again manually using Cell.SetNeedsLayout and Cell.SetNeedsDisplay, hoping that would cause the table to re-query the source for new dimensions, but no joy.
I tinkered with the direct approach, trying to size the contentview itself but it didn't seem as if it was leading anywhere. I feel as if the table needs to be told to query for a new row size, but I'm open to any suggestions.
Surely I'm not the first to attempt this? What am I missing?

Try forcing GetHeightForRow to be called again by calling ReloadRows instead.
You may or may not have to specify begin/end updates (this might just be for animation, though?)
tableView.BeginUpdates();
tableView.EndUpdates();

Related

UICollectionView reload every second

My sport app keeps track of who is on and off the field, and for how long. I normally have 20-30 people to swap around, during training time. I have a timer to reload the visible cells of the collection view every second. The whole collection view reload can cost between 120-150ms.
The scrolling performance is good, however, sometimes the tapping to swap players does not respond. I think that is when the collection view is trying to reload the cells.
I can see there might a couple of ways:
Use UITableView, with each row to have 4 different elements.
Use UIScrollView, and preload all elements there. We used to use KKGridView library here, but it is way outdated. That is why we move to UICollectionView after 6-7 years
Have anyone had the same issue, and which way should provide the acceptable level of efficiency but not too complex to implement (to reduce the number of bugs)
Keep the record of the cell's index that need to update, then get the Cell from collection view, call method ask it to update itself, push the view update to the cell class, it wont mess with your collection view tap/drag...
Reload whole collectionView is only needed when whole dataSource change, yours is simply cell-by-cell update as I notice

iOS infinite scroll items disapearing (sometimes)

This is a very rare occurring bug from hell,
I have an infinite scroll controller that displays products, 2 in each row. Rarely, something affects the controller and causes items to vanish, when I tap the empty area where the item should be, it works as expected and directs the user to the item details controller. When I back out back to the list, sometimes the cell shows its content, and others get hidden.
Sometimes it just a couple of items missing, sometimes there are so many missing items that makes the list appear empty, like only 1 or 2 cells are visible per screen height.
An even stranger situation is, when I scroll really fast to the end and stretch the screen really fast out of the visible area, and there are no more items to load, the visible items can jump from left to right.
Please see these two videos.
https://www.dropbox.com/s/jibflcouz1ena8n/missingProductImages.mov?dl=0
https://www.dropbox.com/s/uz13fzorypnp38t/again.mov?dl=0
I could send code but I didn't want to clutter this place with full length code, let me know if you want to see a specific section of the code please. Maybe someone could have an idea of what might be going on by looking at the vids.
What's probably going on here is a state problem with your collection view cells. The code assigning model values to the cell's views would be of use here. But absent any actual information, the first thing to review would be the cell's prepareForReuse implementation:
Does it call super?
Does it clear out all current values?
Does it cancel any pending asynchronous operations?
Are fetches and cancellations correctly matched?
Next, check if there's any essential configuration in the cell's init/initWithCoder methods -- those are only called on first creation, not on reuse.
Those are the normal pitfalls of UICollectionView cell handling. If they don't suggest the problem, please post the cell code.
It looks like your cells are not being reused correctly.
Can you check that you have set the same reuseIdentifier for your cell in Interface Builder that you are assigning in your code?
Update: Attached image to show where to set the identifier in the storyboard/xib
Update: added layout solution
Another problem could be due to the layout bounds of your collectionViewCell. When you load your cells they bounds are not calculated until they have been added to your collectionView and rendered. This can cause the elements in your cell to layout with the wrong values. This happens commonly with async image frameworks as they cache a resized version of the image for performance. When you cell loads, the cached image is loaded at the wrong the wrong size.
Add the following code to your collectionViewCell:
- (void)setBounds:(CGRect)bounds {
[super setBounds:bounds];
self.contentView.frame = bounds;
[self setHighlighted:NO];
}

How to determine whether the user has scrolled past the first cell?

On iOS, when you append something to the beginning of UITableView's data source, the cell will "animate in" and push the rest of the cells down only if the user is already scrolled to the top. When the user is scrolled down farther down the list and a new item gets appended to the top, iOS does not automatically move the cells down.
When a new cell comes in from the top, how do I determine between the two?
My use case is that when the user has scrolled down past the iOS point, I can display a "new item above" button for the user to click . (similar to Twitter)
I'm using dynamic height for cells, so hard coding the scrollView by pixel isn't the most ideal way. I'd like to utilize iOS's way to determine it.
There is an array available of all visible cells' index paths called indexPathsForVisibleRows. You can access that property and check to see whether or not your first row is one of them, and go from there. You can also access visibleCells property to get the actual UITableViewCells themselves.
How to determine whether the user has scrolled past the first cell: a UITableView is a subclass of UIScrollView, so you can just look at the contentOffset property.
I'm not exactly sure that that's enough to accomplish what you want though. You could also maybe take advantage of the fact that tableView's cellForRowAtIndexPath: method only returns a cell if it's visible, and request the first cell. I've never tried implementing something like this before though so there might be a better approach.

XCode autocomplete

I'm new to IOS development, I have a few questions.
1) What's the purpose of property rowheight on table view cell, I mean it does nothing even if I change its value, it always takes the value from its parent view i.e a tableview property rowheight? It visually changes in the IB but nothing happens when I run the app.
2) What's the purpose of Content View why is it even there? Let's say If I have to make some image equal to the height of the cell it restricts me. Or is there any way a content view can be changed to be equal to the cell height & width? I have to put constraints on the image in relation with the cell which is not the immediate parent of the image and I don't know if this is the correct way to do it.
3)How does Xcode Autocomplete works? like if I want to write a function tableview(_:tableview didselectrowwithindex:IndexPath) and I type tableview it shows a list, what to do next? I mean I can't type the whole fucntion with params or find the func in the huge list.
The height of the cell set at the IB is primarily used for simulation, the views described at IB are normally resized when actually used. E.g. you can set rows height to be 100 for the table view, 30 for some of the cells and keep the whole controller simulating a nice screen of iPhone 6. The same view will be used for all devices and will be scaled accordingly as well as the cells with the help of your delegate.
The content view is there for the reasons directly related to your additional requests. It holds all the content while there other views that accompany your content and are part of the cell like separators, accessory views, slide action views. Without a content view the responsibility of managing all the additional parts would most likely fall on you as a developer and while you might think that that is fine at the simple layouts, a simple enhancement to it would make a huge impact.
Fuzzy autocompletion at Xcode seems to be something Apple is working on now. If you can't wait and find it too difficult to navigate through the list, there are Xcode plugins available that provide fuzzy autocompletion.
Answering the question in the topic:
example: tableview(_:tableview didselectrowwithindex:IndexPath)
if you write tableview it will show all the symbols that start with tableview. For functions, it will show all the functions sorted by the second parameter name (didSelectRowWithIndex).
[EDIT]
it will autocomplete as far as the answer is unique and then show you a list full of options. I don't know any tricks to skip looking through the massive list. But after a while you'll know what you're looking for and it gets faster.
[\EDIT]
when you press tab, it
by the way: the delegate functions names start with the name of the object they're related to.
So UITableViewDelegate functions start with tableview.
as for your first two questions there are tons of answers for those questions on SO. This one seems closely related to yours.

When to use UICollectionView instead of UITableView?

I found that UICollectionView is like an upgraded version of UITableView introduced in iOS6, but when should I choose UICollectionView instead of UITableView?
There are still Apps using UITableView, if UICollectionView can do anything UITableView can do , why people still use UITableView? Is there a difference as far as performance is concerned?
Thanks!
That depends on the requirements. How the application flows determines which type of UI to integrate into the application.
People mainly use the UICollectionview for creating types of UIs with multiple images shown in a grid. This would have complex logic using UITableView, but with UICollectionview, it would be easy.
When using UICollectionview, you don't need to set buttons with tags or other things by getting selected items values. You can simply get -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath and in UITableViewDelegate:
`-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath`
You get the selected row instead of the item, so for creating grid or modified items, using UICollectionview is best.
For the listing details of each item, people use UITableView because it shows more info on each item.
Apple Docs:
UICollectionView Class Reference
The UICollectionView class manages an ordered collection of data items and presents them using customizable layouts. Collection views provide the same general function as table views except that a collection view is able to support more than just single-column layouts. Collection views support customizable layouts that can be used to implement multi-column grids, tiled layouts, circular layouts, and many more. You can even change the layout of a collection view dynamically if you want.
UITableView Class Reference
A table view displays a list of items in a single column. UITableView is a subclass of UIScrollView, which allows users to scroll through the table, although UITableView allows vertical scrolling only. The cells comprising the individual items of the table are UITableViewCell objects; UITableView uses these objects to draw the visible rows of the table. Cells have content—titles and images—and can have, near the right edge, accessory views. Standard accessory views are disclosure indicators or detail disclosure buttons; the former leads to the next level in a data hierarchy and the latter leads to a detailed view of a selected item. Accessory views can also be framework controls, such as switches and sliders, or can be custom views. Table views can enter an editing mode where users can insert, delete, and reorder rows of the table.
Here's my criteria:
If a UITableView can do it, use it
If a UITableView needs lots of code to do it or can't do it at all, use UICollectionView.
You have to consider the restrictions on UITableView before making a decision: It's a single column. And you can only customize the cells, but not section backgrounds and such. So if you have a straight-up list of things with no extra frills - that looks like a bog standard iOS view, basically - then use UITableview. If you have custom insets, or a border around each section, use UICollectionView.
I'm actually considering UICollectionView for all things simply because it's very expensive when you start developing your view as a table view, then later find out it can't do that one thing that you need it to do. 1st hand experience ;)
Edit after even more experience with the two: Disregard that last paragraph. UICollectionView requires a lot of boilerplate code to make it work like a UITableView. Use UICollectionView only when really needed. ;)
For simple lists and forwards/backwards navigtaion, use UITableView.
If you need a high degree of customisability, use UICollectionView.
Generally speaking, in software development, it's best to choose the approach which represents "The Simplest Possible Thing".
EDIT: As of iOS 14, UICollectionView can now do lists as well and is now the recommended approach. See this session from WWDC20 for more information and implementation details: https://developer.apple.com/videos/play/wwdc2020/10026/
According to my point of view main difference between collectionView and tableView is that
TABLEVIEW --> show list of items in only one column.
COLLECTION-VIEW -->show list of items in multiple column.
Hope it will help you.
If you choose UITableView for iPhone, make sure you have considered your iPad strategy first. If you want an iPad-specific layout, you may want that single-column layout to become a grid.
Although it's not required, I always use a collectionview. That way I can easily adapt how my collections are presented for differing resolutions. A plus is that it's ready to quickly add new types of cells when refactoring in the future.
I see no point of tableviews. It's very simple to use a collection view to represent a table. IMO.
From my personal experience the two elements should only be compared loosly.
TableView
A TableView is a UI element designed for showing data in a list format. There is certain functionality that comes as standard with a UITableView, such as:
Accessory View
Cell Selection Style
Editting Style (Delete and edit buttons).
The above elements enhance the usability of data when displaying and interacting in a list format. Such as viewing emails.
CollectionView
A CollectionView is a UI element designed for showing content using a custom layout (usually anything that isn't a list). CollectionViews improve functionality of displaying data in completely bespoke layout styles and also dynamically changing layouts on the fly. Some examples are:
Horizonal Lists
Photo Galleries
Thumbnail views
Carousels
Dials
Laying out elements on a map
etc.
CollectionViews also allow for multiple selections.
Conclusion
As you can see from the above, both have completely different use cases and are designed for enhancing the development and usability of their own specific data sets.
If you are looking at displaying anything in a list style with the followin interactions:
- Adding
- Deleting
- Re-ordering
Then a UITableView will simplify this process by providing the support straight out of the box.
Anything else, you should leverage the benefits of CollectionView as you have more flexibility.
Its totally dependent on how your data to be shown.
As mentioned by many above, if you require only single set of data and that too not complex, go for UITableView else use UICollectionView.
UICollectionView is customization friendly.
If you are dealing with multiple cell heights or so, then go for UICollectionView.
Both are depends on the requirements. Table Views also have support for a variety of editing scenarios. This support has not been implemented in the Collection View classes.
If you are converting from a Table View that relies on these methods, expect to do a little extra heavy lifting in the Collection View.
Collection View section headers can be placed anywhere within the view.
and UITableView don't need to set buttons with tags or other things by getting selected items values.
In practice, everyone uses UICollectionView that I've come across, when they only need a UITableView. "It's one-dimensional. It goes up and down. Why are you adding unnecessary delegate methods for layout AND data?". I once spent an extra 2 hours helping a startup find out why their UICollectionViewCell got squished because the owner, who didn't read the Animations manual, nor HIG, nor the UICollectionView guide, decided to use it and add variable heights and anims. Needless to say, he gave himself a headache and much lost time on a non-business-critical issue he could have avoided by simply using a table cell, since there's no extra layout delegate + Nib.
Let me get this straight, I am all for UICollectionView's when your data and display need it. They're very powerful. But in practice, most people I've seen have been using them on lists.
This brings up another flaw. They're also used on short, constant lists that won't change, ever. In this case, just make a Xib. Or write a custom view that stacks them. Why? Because you don't need the memory management for 5 sets of labels with a button or switch. If they might change, then yes, use a list. If you want physics, then UICollectionView works well with a some cool effects. But do you really need to add 5 delegate methods and a layout system for 5 labels that will never move?
Also, I'm not forgetting that iOS has a native stacking view now too. I can never get it to deform how I want, even though I'm quite adept at the 2D and animation systems, so I never use the built-in one.
All I'm saying is, define your requirements. Maybe you don't need either of these, if your UI isn't adding/removing items and refreshing itself. Or maybe you want to write a Card Game and throw them out virtually on a table, then use UICollectionView with a physics system for its layout guide.
Personally I think the UICollectionView can do most of the work which UITableview can do. well, at the same time, it's more complex to use.
I suggest you use UICollectionView as TableView just in case your manager change requirements in the future.
Based on our need we are choosing TableView or CollectionView.
Example:
For phone contacts tableView is best option.
For photo gallery, collection view will be best option.
I had this issue in my current project. Which to use. In my case it was simple really. I needed both. I needed my view to look like UITableView and also to change its change / layout. So, UICollectionView was used. I also use UITableView everywhere I don't need any extra customisation. Since UiTableView comes with a default layout that includes images and text - I use it for simplicity.
Based on our requirement we choose UITableView or UICollection view.
If we want to display images or items in grid type or if we need more customisability we use UICollectionview.
For listing each item with details and subdetails we use UITableView.
UICollectionView:
The UICollectionView class manages an ordered collection of data items and presents them using customizable layouts. Collection views provide the same general function as table views except that a collection view is able to support more than just single-column layouts.
UITableView: A table view displays a list of items in a single column. UITableView is a subclass of UIScrollView, which allows users to scroll through the table, although UITableView allows vertical scrolling only.
As per my view for Grid View display use UI Collection View.All other list view use UITable View

Resources