I have UICollectionView with a series of cells, and for each cell, some hidden annotations. The annotations are only meant to be shown when the the associated item is selected. So I added the following chunk of code to my controller's collectionView:didSelectItemAtIndexPath: method:
WESpan *span = self.selectedSpan;
for (UIView *view in self.collectionView.subviews) {
if ([view isKindOfClass: [AnchorCell class]]) {
view.hidden = ((AnchorCell*)view).anchor.span != span;
}
}
This works... but it seems ugly to me that I have to do the loop over all subviews, doing an isKindOfClass: check. Is there not a better way to do this? Something more idiomatic?
I wish there was an analog to the cellForItemAtIndexPath: method, so I could fetch just the ones correlated with the appropriate index and hide/unhide them.
collectionView:viewForSupplementaryElementOfKind:atIndexPath: ?
If you want to update a value in the supplementaryView you could always update your model and then reload the section of the collectionView.
[collectionView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]];
Related
I have a Custom UITableView Cell as xib.
I have taken an Scroll View inside it.
I Know how to set the delegate but I have confusion.Their is two of doing this.
I don't knw which is best and How to decide which way I have to choose.
1 Way : To set Delegate To Files Owner
2 Way : setting Delegate to UITableViewCell
In a tableviewcell the delegate of scrollview will always be set to UITableViewCell
That means your second step will work .
Let me know if you find any difficulty.
The choice depends on what the delegate function for the inner scroll view must do. It is simpler to point the delegate to the custom cell and handle the inner scrolling events there.
But if handling that inner scrolling requires a lot of data and logic from the view controller, then point the delegate to the vc. To make that work, we'll need to know that the scroll event was from an inner scroll view, not the table, and we probably need the row where the scrolling happened, so:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// if the table view's delegate points here (likely), then to distinguish...
if (scrollView != self.tableView) {
// one of the scroll views in the table, but which one?
NSIndexPath = [self indexPathContainingView:scrollView];
// here we know that horizontal scrolling happened on indexPath.row
}
}
// return the indexPath of the tableView cell containing a view
- (NSIndexPath *)indexPathContainingView:(UIView *)view {
while(view && ![view isKindOfClass:[UITableViewCell self]])
view = view.superview;
return [self.tableView indexPathForCell:(UITableViewCell *)view];
}
I have a a custom UITableViewCell class and in it I have a UIImageView. This UIImageView is only displayed when the text of the UITableViewCell is equal to a certain string, eg "Home". When the method mapView:regionWillChangeAnimated: is called, I want to apply an animation on this UIImageView.
My question is how can I, when mapView:regionWillChangeAnimated: is called, go through my UITableView and custom UITableViewCells and perform an animation on the UIImageView within the cells which have the UIImageView set as visible?
I've been able to call methods on cells before using the UITableView delegate methods but I'm struggling to find a solution in this scenario because the the UITableView is not being directly called by the map panning method, it's not a didSelectRowAtIndex path issue?
Thank you.
If you have reference to table view in your map delegate method, you can get all visible cells using visibleCells method in UITableView and apply animation for them if needed. General structure may look like:
// Controller
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
...
[self applyCellsAnimation];
}
- (void)applyCellsAnimation {
for (CustomCell* cell in [self.tableView visibleCells]) {
[cell performImageAnimationIfNeeded];
}
}
// CustomCell
- (void)performImageAnimationIfNeeded {
if (!self.myImageView.hidden) {
// perform animation
}
}
You can get an array of all the visible rows in your table view using
[myTableView visibleCells]
You then just need to integrate through each cell and animate the image.
i.e.
for (MyCustomCell* cell in [myTableView visibleCells])
{
[cell animateImage];
}
The implementation of animateImage can then do whatever you want - just check the imageView.hidden property and animate it if the imageView is visible.
I have a UITable view with a random number of UIImageView in every Single row. In the costruction of the single row, I've used [self addSubView: xxx] and a for cycle to add every UIImageView i need to add (my model has an array of URL). But now I've noticed that when the UITableView reuse the rows and it doesn't clean the UIImageViews added.
I've tied to manually remove them in method onPrepareForReuse as in the code:
if(_messageContentsFrames != nil){
for(NVChatMessageContent *singleContent in _messageContentsFrames){
[singleContent removeFromSuperview];
}
}
But it gives me error. How can i completely reset the view when it is going to be reused?
You can remove these imageViews in -tableView:cellForRowAtIndexPath: method. That always worked for me.
By the way, do you really need to reuse cells if you make such work with it. Wouldn't it be easier to create new cell?
Or it would be better not to remove imageViews, but reconfigure them on reusing and remove those views, that cell doesn't need.
Option 1. Set tag to your UIImageView (use: imageView.tag = 123456) and then in tableView:cellForRowAtIndexPath: you should get the specific view using:
id imageView = [self.view viewWithTag:yourInteger];
[imageView removeFromSuperview];
Option 2. Use:
for( UIView *view in cell.subviews) {
if ([view isKindOfClass:[UIImageView class]]) {
[view removeFromSuperView];
}
}
In my app, i have table view in which i am reloading data based on Business logic so it was overlapping earlier then i write this piece of code to remove content before drawing:
for(UIView *view in cell.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
And now its removing everything including cell separators. Any idea how to prevent it??
Thanks,
Remove subviews from [cell contentView]
If you don't know what are you doing, you should never add views or remove views from the cell directly. Use only contentView, backgroundView and selectedBackgroundView.
However, there is rarely a use case when you should remove all the views from a cell. Why don't you just create a new cell (or reuse one)? Or just set the hidden property to YES for the subviews?
every time I scroll up or down, and cell which has been drawn already gets redrawn because "cellForRowAtIndexPath" is called again when that cell comes in view.
Is there a way to not call "cellForRowAtIndexPath" for a cell that has already been called for.
That is once cellForRowAtIndexPath is called for a indexpath it should not call it again when the user scrolls.
I can set flags in a flag array and do it manually but is there a more direct way?
I have most definitely a design that is causing performance issues. I can't explain the design nor change it therefore I am asking.
If you do not let the "cellForRowAtIndexPath" method calling again, it may create performance issue,
But you can do that by assigning different cell identifier for each row as follows.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:#"Cell%d%d", indexPath.row, indexPath.section]];
//TRY TO REMOVE ALL CONTENT BEFORE CREATING NEW.
//USE IN "cellForRowAtIndexPath" method
for(UIView *view in cell.contentView.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}