UICollectionView: Is there a way to reload only the supplementary views? - ios

I have an uicollectionview with supplementaryView for each section.
In each supplementaryView I have some buttons.
In dataSource method collectionView:viewForSupplementaryElementOfKind:atIndexPath: I'm setting the buttons tags with the indexPath.section. I made some delegate methods when a button is pressed and send the section(button.tag) as parameter.
Everything works fine, but here comes the problem:
when I insert or delete a section it must update the buttons tags, but I don't want to reload all the items from each section.
I've tried:
to get the supplementaryViews with the dataSource method collectionView:viewForSupplementaryElementOfKind:atIndexPath: and call layoutIfNeeded method for each supplementaryView, in this way the supplementaryViews are reloading, but this approach multiply my supplementaryViews.
a fast for in collectionView.subviews and get just the supplementaryView and call layoutIfNeeded method, but it doesn't reload, just the layout is reloading.
reloadSections: method, but this reload all items from the section
Ohh.. And I use NSFetchedResultsController(delegate) for inserting and deleting sections.
Can anyone help me with this? Is there a way to reload only the supplementaryView? Is there other approach for this scenario?
Thank You!

To reload supplementary views you can use -invalidateLayoutWithContext:.
See documentation for UICollectionViewLayoutInvalidationContext and method -invalidateSupplementaryElementsOfKind:atIndexPaths: (available since iOS 8).

Instead of reloading these views, getting a reference to each visible supplementary view so that you can change the tag might be sufficient for your needs.
There is a simple method you can use to do this:
let supplementaryViews = collectionView.visibleSupplementaryViews(ofKind: "identifier")
https://developer.apple.com/documentation/uikit/uicollectionview/1618026-visiblesupplementaryviews

Related

Is there a way to directly access UICollectionView elements without reloading?

I have another question open where I'm trying to figure out how to reload the collectionView without auto-scrolling. I was also realizing there are a lot of other situations where I will need to change things in the collection view. Also I have some items that I will want to change the .alpha on and change the text of. Is there a way to do all of this in Swift? For example (to be specific) if I have a collection view with a view in each cell and that view has a textField in it, can I change the alpha and text, (change alpha with animation even) without reloading entire table?
Look at the documentation for UICollectionView. There are several "reload" methods:
reloadData()
reloadSections(_:)
reloadItems(at:)
If you just want to reload a single item, update your data source's data and then call reloadItems(at:) passing in the index path for the item.
Another option, if a cell is currently visible, is to use the cellForItem(at:) method to get a reference to an existing cell. Then you can directly access UI components of the cell as needed. You should also update your data model as needed so if the user scrolls and comes back, the cell will be rendered properly.
Most appropriate where you can update your custom view of a particular UIcollectionViewcell is reloadItemsAtIndexPaths.
You would be handling a particular item than whole collectionview with reloadData.
You can handle it via notifications or some call backs in your code where you can make decision when to update which cell.
Hope it will help you.

UITableView inside UITableViewCell - didSelectRowAtIndexPath

I am making an interface which have UITableView with four custom UITableViewCell's. And every other UITableViewCell have also UITableView. This mean I have TableView inside a TableView.
Let me call first tableView - ParentTableView and nested tableView - ChildTableView. So I implemented method didSelectRowAtIndexPath on both tableView's. But when the app is running, only the method of the ChildTableView is being called. I need to know inside the ParentTableView, which cell is being tapped.
How can I transfer that information further from ChildTableView to ParentTableView.
This may be a silly question, but I can not find any reliable solution so far, so please help me.
Thank You in advance, kind Sir
First, I think nested table views is a bad idea. But I don't know your use case, so it might be an exception.
The table view controller class used inside a cell have its own #protocol definition and set the outer table view as its delegate. In the inner didSelectRowAtIndexPath: it can inform the outer table view about the selected indexPath, its own indexPath and any other information you might want to transmit.
Try using collection views. You can do a layout that works like a regular table view and then in the cells that need to have a table, you can make those separate cells with another collection view inside or a table view inside of it.
As mentioned before, it's not easy doing table views inside of cells, and it can be very tricky to get things to work correctly.
This is an old tutorial I wrote which may help and be of guidance. But since then there's been collection views and auto layout, so keep in mind it's very old.

ios - a single static header that changes as you scroll

I've been searching a ton and can not seem to find an answer...
I have a tableView which scrolls all the days of all the months. And I have a titleForHeaderInSection: and viewForHeaderInSection: which displays a section header at the top of each month-section which replaces appropriately at the top, cool. But how can I create a single header where the titleLabel changes to the proper month as I scroll (in other words, Not have multiple section headers, just one)?
I can't tell whether this should be setup as "one (big) section with a header that changes" or "a headerView that changes", or whatever... Any examples would be greatly appreciated. Thank you in advance.
You can create a static view and place it above your tableView. Then you can use the visibleCells property to determine which cells are visible. When those cells change to the cells of a new section you can update the static view that is above the UITableView.
Once you are the delegate of the UITableView you are also the delegate of the UIScrollView it is built on.
So you can catch the scrollViewDidScroll: delegate call and update your header there.
So to lay it out:
1.) Create a Header View above your UITableView
2.) Become the delegate of the UITableView
3.) Implement the scrollViewDidScroll: method to detect scrolls
4.) Inside the scrollViewDidScroll method use the visibleCells property of the UITableView to determine which cells are being shown and to update your header view appropriately.
I've never done anything like this, but I don't see why it wouldn't work.
EDIT: As Husker Jeff pointed out. It is probably easier to use indexPathsForVisibleRows to determine what is on screen. You can then use that fairly easily to determine which section/sections are being displayed. Thanks Jeff!

Implementing a form within a TableView

I would like to implement a form to insert data within a TableView in my app.
I would like the form appears as a table, and each row of the table represent a TextField.
What is the right approach to do this?
Any help is appreciated!!
Regards, yassa
If I understood your question right then I would go for custom TableViewCells.
Subclass UITableViewCell.
In the init method (initWithStyle, if I am not much mistaken) create the Text Fields and add them to the superview. ([self.view addSubView:myTextField])
In the layoutViewItems method you should arrange the TextField and any other custom view that you may want to create and add in init.
While overwriting both of them, do not forget to call the related superclass method at the very beginning. You may not need [super layoutSubviews] in the event that you do not want to use any of the standard elements of UITableViewCell.
If you are using Storyboard, use the new Static Cell TableView (as opposed to Dynamic Prototypes. This allows for a TableView that you don't have to use the delegate or datasource methods on. You can layout the sections and rows manually in IB. I use it lots for form based views.

UITableView initial row selection

Maybe I'm missing something obvious, but I'm have a hard time programmatically setting the row selection in a tableView. The goal is to simply have a tableView open with a row already selected. The problem appears to be that I have to wait until the tableView is fully loaded before I can modify the selection.
I've read various strategies such as calling reloadData for the tableView in the viewController's viewWillAppear method, then immediately calling selectRowAtIndexPath for the target row. But when I do that, I get a range exception because the tableView has zero rows at that point. The UITableViewDelegate methods (numberOfRowsInSection, etc.) don't appear to be called immediately in response to reloadData (which makes sense if the table rows are drawn "lazily").
The only way I've been able to get this to work is to call selectRowAtIndexPath after a short delay, but then you can see the tableView scroll the selected row into view.
Surely, there's a better way of doing this?
Well, you can use another strategy. You can create a hidden table view, configure how you want and than show to user. Use the tableview.hidden = YES.

Resources