I have a table view, onclick of 7th row, I push another view. Then when I come back using pop, tableview is reloaded automatically in ios8. It does not happen is ios 7.
Problem is cellForRow and HeightForRow for 0,1,2,3 cell is not called. Hence table scrolls the 7th row up, and not visible. 9,10,11 cells are visible.
I want table to stay as it was when I come back to that view.
I saved selectedIndex and scrolled table to particular index in viewWillAppear.
[self.table_exhibitorProfile scrollToRowAtIndexPath:self.selectedIndexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
It shows 7th cell, but its position is not same as it was. It goes to top.
It shouldn't be reloading unless you tell it to. It's not automatically reloading in iOS 8 for me.
The only possibilities that I can come up with are that
you're using CoreData, an NSFetchedResutsController, and the same managedObjectContext in both view controllers. If something changes in the managedObjectContext in the second view controller, when you pop back, the fetchedResultsController will reload the table, or
you're calling tableView.reloadData() in viewWillAppear() or viewDidAppear().
I had the same problem and this is how I fixed it:
According to the Apple docs:
UITableView overrides the layoutSubviews method of UIView
so that it calls reloadData only when you create a new
instance of UITableView or when you assign a new data source.
In my case I was setting the table view's dataSource to nil in viewWillDisappear: and setting it back to self in viewWillAppear: thus causing the data to be reloaded.
The 'automatic' reload went away when I moved the dataSource assignment to viewDidLoad
Hope this helps!
Related
I am using UICollectionView inside a UIPageViewController.
Each page is an instance of the same subclass of UICollectionViewController.
Whenever I do a page swipe to see a page I haven't seen before, the animation gets a small delay (few milliseconds) to start because of the time UICollectionView takes to go through all the delegate/datasource methods.
So I was trying to implement a pre-caching system to load the viewcontroller before the user actually starts swiping.
I am able to create it easily, but, for some reason, whenever I call reloadData on the non-visible ViewController, none of the UICollectionViewDelegateFlowLayout delegate methods get called.
So far I have tried to use: setNeedsDisplay, setNeedsLayout, setLayoutIfNeeded and invalidateLayout to force them to get called, but nothing is working.
The viewcontroller is not nil. The view is not nil.
Does anyone know what could be the reason? Is it because the viewcontroller is not in the viewport?
Loading the view controller first is probably not the best idea.
You should rather cache the data source.
About reloadData not working properly with a non displayed controller, you are right, it's because the controller is not present.
The delegates won't fire unless the view is visible.To counter the delay you are facing you would have to ditch the collectionview and use collectionview controller and add those collectionview controllers as child to page controller
Note: Set the frame appropriately for each collection controller
CollectionController *collectionController = [self.storyboard instantiateViewControllerWithIdentifier:#"Calculate"];
[self addChildViewController:collectionController];
collectionController.view.frame = self.calculationView.bounds;
[self.pageControllerView addSubview:collectionController.view];
[collectionController didMoveToParentViewController:self];
In my app, there are tabs. I have one tableviewcontroller that contains messages and I have implemented pull to refresh so that works fine. However, if the user goes from the message tab to another tab and then back to the message tab, the uitableview doesn't reload and the user has to pull to refresh. I have thought of putting [self.tableview reloadData] or [self loadObjects] (i am using Parse) in viewDidLoad/viewWilAppear, but that doesn't seem to work...it's because they are only called when the view controller is initially visited right? So I'm wondering as to where I should put that code so that the table view can be reloaded every time the view controller is revisited?
viewWillAppear and viewDidAppear are both called every time the view controller appears. If you call reloadData in one of those methods then it will refresh the table view.
I think your problem is you aren't updating your data source. You will need to make another call to Parse otherwise your table view will just reload with the same data.
I don't think that this behavior is desirable. I suggest you tu wait for a reasonable timeout before updating data, or your user will experience lags and high network usage.
However to do that, you should set a delegate that fires when the corresponding view is loaded (take a look here how to get the event that switch tab menu on iphone ) and then call
[yourTableView reloadData]
inside didSelectViewController
I have two view controllers A and B. ViewControllerA has a UICollectionView on it.
If I push ViewControllerB onto ViewControllerA, then in the background ViewControllerA's UICollectionView updates I want to force the collection view to redraw and dequeue it's cells so that when I return from ViewControllerB ViewControllerA's data is up to date and correct. Calling reloadData doesnt make the collection view redraw it's self if its in the background, it will wait until after viewWillAppear to trigger
[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes], which is the method that calls into the datasource to dequeue new cells.
Anyway to force or trick the collectionview so that it calls [UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes] on new cells prior to viewWillAppear being called?
I am trying to get a custom view controller transition to work and it looks weird if the data has changed in ViewControllerA while looking at ViewControllerB. I want to force the collectionView to update so when I call CollectionView.visibileIndexPaths the correct items are returned and my animation will look correct.
Calling layoutIfNeeded on ViewControllerA's view prior to animating to it again forces the collectionView to update prior to ViewControllerA coming back onscreen.
When is the best time to call [reloadData] on a UITableView? viewDidAppear or viewWillAppear? If a view is unloaded, will the underlying tableview be unloaded as well?
The reason I am asking is due to some behavior I am seeing. Let's say a view is asked to reload its datasource, but is deallocated before it can finish. A scenario would be with a UITabBarController and navigating to a different view than the ViewController being selected. So what happens is that viewWillAppear gets called, but viewDidAppear does not (since I navigated away).
As a result, the ViewController gets deallocated (along with its model data), but if I am calling reloadData in viewWillAppear, the "cellForRow", and "numberOfRows" methods are invoked which causes a "deallocated instance" error. Does that make sense? Do you normally put in code that checks for nil if the model can be changed anytime the view is requested to appear?
I would load the table once the view has loaded, it allows for all of the UIObjects to be created before messing with them. Not sure, but I believe the table is automatically unloaded with the superview.
Take a look at this question>>>
Objective C - Correct way to empty and reload UITableViewController with NSMutableArray
before you get the datasource from server or anywhere, you can display the tableview with a blankcell(a cell that you can draw sth like 404 web page) , when you get the data, then reload the tableview.
remember to set number of cell to 1 for the blankcell
I'm encountering a problem where tableView:numberOfRowsInSection: is getting called, then a other methods are getting called that affect the underlying array, then tableView:cellForRowAtIndexPath: gets called and crashes because the contents of the underlying array is different than when numberOfRowsInSection was called. If the framework would call numberOfRowsInSection right before calling cellForRowAtIndexPath, there wouldn't be a problem.
Since I can't expect a fix in the framework in the short term, the easiest solution I'm looking at is returning a dummy cell if the underlying array doesn't contain the requested entry.
More details on how this problem occurs:
App uses a tab bar controller.
The root controller for each tab is a UINavigationController.
The view controller in question is invoked by pushing it on the nav stack of the second tab bar item's nav controller.
The viewWillAppear method of the view controller in question resets the underlying array and then calls [_tableView reloadData].
The app delegate which implements UITabBarControllerDelegate implements the tabBarController:didSelectViewController: method and calls popToRootViewControllerAnimated: on the view controller being selected.
The root view controller's viewWillAppear method calls a method on the view controller in question which affects the contents of the underlying array.
Steps to repro the problem:
Start app.
Tap second tab item.
Tap to bring up view controller in question. Perform work on that view to fill the table.
Tap first tab item.
Tap second item.
At step five, here is the order of the calls:
viewControllerInQuestion: viewWillAppear - reloads underlying array, calls [_tableView reloadData]
viewControllerInQuestion: numberOfRowsInSection - returns 1
App delegate: didSelectViewController - calls popToRootViewControllerAnimated
secondTabBarRootViewController: viewWillAppear - calls method on viewControllerInQuestion that clears contents of underlying array
viewControllerInQuestion: cellForRowAtIndexPath - crashes trying to access object at index 0 in underlying array.
Thanks for any help you can give me.
This turned out to be a problem with improper calls to reloadData on the table view. I inherited this code, but I'm new enough to iOS that I didn't understand the proper usage.
The code was calling [_tableView reloadData] in both loadView and in viewWillAppear. Removing both calls solved this particular problem.
I had a similar problem.
If you have an observer in your controller that calls reloadData, use the viewWillAppear method to add the observer and viewWillDisappear to remove it.