Detect end of reloadData method in UITablewView - iphone

Is there any way of detecting the end of the reloadData method in UITableView ?
I can use the viewDidAppear for the initial call but after that I have no way of detecting the end of a reloadData.

Well, there is nothing in the documentation and the UITableViewDelegate is of no help either. In theory, what you could do, is subclass UITableView and override the reloadData method like so:
- (void)reloadData
{
// reload data starts
[super reloadData];
// and here reload data ended..
}
Unless reloadData spawns some separate background threading, this marks the end of reloadData.
Good luck.

Related

ReloadData doesn't fire tableView:numberOfRowsInSection:

I just encouter a problem, that I call UITableView reloadData method, but nothing happened. No tableView:numberOfRowsInSection is called.
The scenario is:
Table works fine in view A (has the UITableView), then view B shows and hide, after this step, the UITableView reloadData is not working anymore. I am sure reloadData is called in main UI thread and the data source has been changed. Also NO IBOutlet connection issue.
Try putting your call to reloadData in viewWillAppear.
Set BreakPoint on [tableView reloadData]; check that your tableView object is not nil.

Confusion about UIView's setNeedsDisplay

I have an ivar of UITableView* myTableView. I have data being loaded from internet so when the data gets loaded should i call [myTableView setNeedsDisplay], i know i can/should call [myTableView reloadData] but the confusion is that calling setNeedsDisplay should also work but is not working.
I am just looking for an explanation as to what setNeedsDisplay does? when called on UITableView instance.
As per the documentation setNeedsDisplay calls drawRect in "next drawing cycle". so can anyone tell me what is the next drawing cycle.
setNeedsDisplay method has nothing to do with the reloading of the tableView. It just redraws the view of the tableView, not its cells or separators.
setNeedsDisplay and reloadData are entirely for different purposes.
setNeedsDisplay marks the calling UIView as needing to be redrawn is a purely visual sense, which as stated will happen on the next drawing cycle.
This is completely different to reloading the data when used in a UITableView context.
See this article for a little more information on the subject.
SetNeedsDisplay
A good example of this is when a UIImageView is rendered with one image; and while it is still on screen, you change the image to something else. In this case, just changing the image will not always trigger a repaint of the view, for that to occur you need to make a call to setNeedsDisplay.
reloadData
It has to be called when the underlying data source for the tableview is changed and you want that to be refelected in UI.In that case call this reloadData mehod
Generally, you only need to call setNeedsDisplay on custom views for which you have implemented drawRect.
My solution was to update all visible cells and keep track of indexPath of cell in my custom class "ProductTableViewCell" with reloadRowsAtIndexPaths, see below:
NSArray *arrayCells = [self.tableView visibleCells];
NSMutableArray *mArrayIndexPaths = [[NSMutableArray alloc] init];
for(ProductTableViewCell *cell in arrayCells) {
[mArrayIndexPaths addObject:cell.indexPath];
}
[self.tableView beginUpdates];
[self.tableView endUpdates];
[self.tableView reloadRowsAtIndexPaths:[mArrayIndexPaths copy] withRowAnimation:UITableViewRowAnimationAutomatic];
Here is how the class is defined:
#interface ProductTableViewCell : UITableViewCell {
NSString *reuseID;
}
#property (nonatomic, strong) NSIndexPath *indexPath;

iphone - scrollRectToVisible issue

This functions perfectly, but I want to make it an once-function, not fixed-function. When I change tableview with other data, the data displays at the index from previous tableview. So my solution to this is implementing the code below. When I implement this, it works, but when I scroll down, it scrolls up all the time, so it is virtually impossible to scroll down further. Any idea how to make it performs only once when I change tableview?
The code:
[tableView scrollRectToVisible:CGRectMake(0,0,1,1) animated:NO];
Edit 21 august:
Guys, thank you very much! The code was in cellforrowatindexpath. I moved it to inside the function which changes tableview and it works like a charm :D
You could override the reloadData method if that is how you are reloading the Table View with new data and put the code in there. Something like this in your table view controller should suffice:
- (void)reloadData {
[super reloadData];
[tableView scrollRectToVisible:CGRectMake(0,0,1,1) animated:NO];
}
If it's scrolling up every time you scroll down, I assume you put the code in the cellForRowAtIndexPath method which will get called every time you want to present the cell. This is not the correct place to put that code.
It IS a once-function. Most probably, this code of yours is executing again & again. If you have kept this in a function such as cellForRowAtIndexPath:, which is called frequently, that may be the cause of this problem. Where have you put it?
HTH,
Akshay

How to refresh a view when resuming from Multitasking?

I have an app which is targeted to iOS 4 and above.I have a custom view, which is having
1.Scroll view
2.Custom drawing inside scroll view.
Now when my app is resuming from background,I want to refresh/reload this scroll view.
setNeedsDisplay is not working here as it usually meant for loading custom drawings and here I want to reload my scroll view contents.
Thanks in advance.
If I understand your question correctly, setNeedsDisplay does not work for you in this case because you need to "reload" the data that the UIScrollView handles before doing the redraw.
If this is right, I would define a method in your controller that does the reloading part; then, I would call this method from applicationDidEnterForeground or applicationWillEnterForeground; the reload method will need to call setNeedsDisplay after reloading the data.
I am sorry if this answer seems very generic to you. If you explain more or post some code, I can try and be more specific.
Have you tried redraw inside viewDidAppear?
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[yourScrollView setNeedsDisplay];
}
setNeedDisplay calls the drawRect which is repainting operation. If you want to refresh the content only simply create one method in viewController and notify this method using performSelectorOnMainThread if you created new thread whenever thread complete (or you receive Data).

Redraw UITableView after updating data async

I have a UITableview that I load with data async so the tableview might appear without data.
I have tired the ReloadData method but the tableview remains empty until I scroll the tableview, suddenly the data appears.
The same thing happens when I load a tableview as a detailedview and switching between items, the previoud items data appears first and as soon as I scroll in the table view it shows the correct data.
My guess is that the ReloadData method works just fine, but I need to redraw the tableview somehow, any suggestions on how to solve this?
/Jimmy
You said you're populating content asynchronously but did you invoke the reloadData in the context of the main thread ? (and not via the thread that populates the content)
Objective-C
[yourUITableView performSelectorOnMainThread:#selector(reloadData)
withObject:nil
waitUntilDone:NO];
Swift
dispatch_async(dispatch_get_main_queue(), { self.tableView.reloadData() })
Monotouch
InvokeOnMainThread(() => this.TableView.ReloadData());
Yonels answer is perfect when your view is currently visible to the user (e.g: User presses a reload button which populates your UITableView.)
However, if your data is loaded asynchronously and your UITableView is not visible during the update (e.g: You add Data to your UITableView in another View and the UITableView is displayed later by userinput), simply override the UITableViewController's viewWillAppear method.
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.tableView reloadData];
}
The positive effect is that your UITableView only reloads it's data once when the user actually want's to see it, not when new items are added.
I had the similar issue today(Storyboard in iOS 7.0).
I was using table View inside a UIViewController.When the view was loaded everything was working fine; all the delegates were getting called.However ; When the underlying dataSource(in my case,Array) was modified; the visible table rows were not getting updated.They were updated; only when I was scrolling the table view.
Tried everything; calling reloadData on Main thread;calling reload in ViewWillAppear; nothing worked.
The issue that I found ; was that I had not made the connection in storyboard; for the table view with the reference Outlet.The dataSource and delegate were set though.
I did not think that it could be the issue; as everything was working fine at the first go.
Hope it helps someone.I had some terrible time to find this out.
I guess it wasn't reloaded.
When you scroll the cells to out of screen, then…
tableView: cellForRowAtIndexPath:
…will be called. So it will be reloaded.
I guess UITableView variable is not validated.
If you use UITableView as a main view, you can try this.
[self.view reloadData];
or
[self.tableView reloadData];
Swift 4:
DispatchQueue.main.async { self.tableView.reloadData() }
After somewhat naively copying in yonel's solution and calling it good I realized that calling performSelectorOnMainThread:withObject:waitUntilDone: fixed the symptom, but not the problem. The bigger problem is that you are making UI updates while still in the context of the asynchronous or background thread.
This is what my code looked like:
dispatch_queue_t queue = dispatch_queue_create("com.kyleclegg.myqueue", NULL);
dispatch_async(queue, ^{
// Make API call
// Retrieve data, parse JSON, update local properties
// Make a call to reload table data
});
When it should look like this:
dispatch_queue_t queue = dispatch_queue_create("com.kyleclegg.myqueue", NULL);
dispatch_async(queue, ^{
// Make API call
// Retrieve data, parse JSON, update local properties
dispatch_async(dispatch_get_main_queue(), ^{
// Now make the call to reload data and make any other UI updates
[self.tableView reloadData]
});
});
If the only thing you need to do is call [self.tableView reloadData] it's probably fine to use performSelectorOnMainThread:withObject:waitUntilDone: since it accomplishes the same goal, but you should also recognize what's happening in the big picture. Also if you are doing more UI work than just reloading the table then all of that code should go on the main queue as well.
Reference: A concise example of using GCD and managing the background vs. main thread.