Call function only after reloadData has finished - iphone

I have a tableView and need to perform a function once the tableView has been reloaded. How do I know if reloadData has finished? Lets say I have methodA that populates the tableView, and once [tableView1 reloadData] has been completed, I want to call methodB. Can anyone help me with this? I've been searching for hours... Thank you!
- (void) methodA
{
NSString *URLa = [NSString stringWithFormat:#"http://www.website.com/page.php?
v1=%#&v2=%#&v3=%#",v1, v2, v3];
NSURL *url = [NSURL URLa];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
(void) [[NSURLConnection alloc] initWithRequest:request delegate:self];
[tableView1 reloadData];
}

You can add a method/category on UITableView or even subclass UITableView:
-(void)reloadDataAndWait:(void(^)(void))waitBlock {
[self reloadData];//if subclassed then super. else use [self.tableView
if(waitBlock){
waitBlock();
}
}
And you need to use it as
[self.tableView reloadDataAndWait:^{
//call the required method here
}];

The problem is that you call reloadData immediately after starting the URL request. That does not make sense because the request has not been completed at that point.
The correct way would be to call reloadData and methodB in connectionDidFinishLoading, after you have updated your data source with the response from the URL request. At that point you know if the number of rows is zero or not, and there is no need to wait for the table view update to complete.

Once I get updated data from server for my table.
I use following code snip to Hide progress bar when table reload gets complete.
[UIView animateWithDuration:0 animations:^{
[your_table_view reloadData];
} completion:^(BOOL finished)
{
//Table reload completed TODO here
//Hide progress bar etc.
}];

Related

MBProgressHud not hiding after calling hide from another class

I have a ViewController called GetInfoViewController. Basically it takes the users input and then sends the input to a NSObject class, ServerConnection. ServerConnection makes a nsurlconnection request and when it is done I want the MBProgressHUD to hide.
GetInfoViewController
- (IBAction)go:(id)sender{
ServerConnection *serverConnection = [[ServerConnection alloc]init];
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
HUD.labelText = #"Searching...";
// here the progressHUD shows normally, and the yelpConnectionMethod is successful in retrieving the result.
[serverConnection yelpConnectionMethod];
}
-(void)endProgressHUD{
NSLog(#"end called");
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
ServerConnection.h
I am not going to put all the nsurlconnection code because I don't think it really applies.. but if you want it I can post it
The only line that matters is:
(this is called after all the connections are done.)
GetInfoViewController *getinfoVC = [[GetInfoViewController alloc]init];
[getinfoVC endProgressHUD];
I call the endProgressHUD method of the getInfoViewController successfully, as it logs "end called". however, the progress hud stays spinning and does not hide.
Any input would be helpful.
Try this method when showing the HUD.
- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated;
It is a method of MBProgressHUD - selector should be the yelpConnectionMethod and target the serverConnection, object = nil and animated depends on you :)

refresh the table in view controller by using refresh bar button

I want to add a refresh bar button in my view controller
I put in the viewdidload() this code:
UIBarButtonItem *refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(refreshTable)];
self.navigationItem.leftBarButtonItem = refreshButton;
and the refreshtable function is :
- (void) refreshTable
{
[self.tableView reloadData];
NSLog(#"table is refreshing ....");
}
this is a screenshot of the refresh button:
but it doesn't work, shall i add something else in the refreshtable function?, the table view doesn't refreshed!, the message "table is refreshing ...." appears everytime i click on the refresh button, but the table doesn't load new data!
when refreshing, can I have this icon somewhere?
If I had two table view in my view controller, and I want when I click on the refresh button, just the first table to be reloaded,
I put the same you code that you suggested, but it doesn't work here! should I do something else?
The issue is you added the data fetching logic in your viewDidLoad (according to your comments).
The viewDidLoad method will be called when the view is loading. It' won't be called unless you dismiss the view and present it again(it won't be calles if you call the reloadData it's just for reloading the UITableView).
When you call the reloadData the data source is still with old data, it is not updated.
So implement your refreshTable method like:
- (void) refreshTable
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://....../fastnews.php"]];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
-(void)fetchedData:(NSData *)responseData
{
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
fastResults = [json objectForKey:#"nodes"];
[self.tableView reloadData];
}
try this .
[self.tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows]
withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
You need to update your dataSourceAaaay in refreshTable method before reload table.

Drop Down Refresh not working?

I've successfully implemented a drop down refresh into my rss feed so that when I pull down the UITableView, it should refresh. All is well in that sense as the date on the pull down refreshes etc. but my UITableView doesn't refresh.
I've followed this code: DropDownRefresh.
Am I missing something to actually refresh the tableview?
Thanks.
Refresh Code
- (void)reloadTableViewDataSource {
//should be calling your tableviews data source model to reload.
//put here just for demo.
[self performSelector:#selector(refresh)];
_reloading = YES;
}
- (void)refresh {
for (NSString *feed in _feeds) {
NSURL *url = [NSURL URLWithString:feed];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[_queue addOperation:request];
}
}
Are you implementing the delegate methods:
#pragma mark EGORefreshTableHeaderDelegate Methods
- (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view{
[self reloadTableViewDataSource];
[self performSelector:#selector(doneLoadingTableViewData) withObject:nil afterDelay:3.0];
}
Have a look at the Demo example (View folder) for more details.
My guess is you've got the following code so far:
- (void)reloadTableViewDataSource
{
// should be calling your tableviews data source model to reload
// put here just for demo
_reloading = YES;
}
So you might do something like:
[self.tableView reloadData];
to trigger a reload of the table's cells.

iPhone - UIWebView not loading first request

I have a TableViewController with some items, each item when pressed pushes a ViewController with an UIWebView, the ViewController is the same in all cases, but each item asks the webView to load a diferent URL. Now the problem is that the first time I select an item, the webView doesn't load the URL, but if I go back in my navigation controller and then press again any of the items (even the same that the first time), it loads correctly. Why could this be?
This is my code. In my TableViewController I have this inside the didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *urlAddress;
NSInteger row = [indexPath row];
// SELECT THE URL BASED ON THE SELECTED ROW. SECTION OMMITED FOR CLARITY PURPOSES.
urlAddress = #"http://www.google.com";
[browserViewController refreshUrl:urlAddress];
[urlAddress release];
browserViewController.title = [NSString stringWithFormat:#"%#", [itemsArray objectAtIndex:row]];
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.mainNavController pushViewController:browserViewController animated:YES]; }
The browserViewController is initialized in the viewDidLoad method of the TableViewController. In the BrowserViewController implementation I have this method:
- (void) refreshUrl: (NSString *)theUrlAddress{
NSURL *url = [NSURL URLWithString: theUrlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];}
But this is the method that seems to be working only from the second time is invoked. If I set a breakpoint on it, I can see it is actually being invoked the first time I press the item on the table, but the loadRequest does nothing.
BrowserViewController is also an UIWebViewDelegate. The webViewDidStartLoad and webViewDidFinishLoad methods aren't being invoked the first time either.
Any ideas of why and how to fix it? Thanks!
you are using refreshUrl on the viewController before it has created its UIWebView.
Use a breakpoint and check the value of your webview. I think it is nil for the first time.
Simply move [browserViewController refreshUrl:urlAddress]; to the line after the push.

What's with [UITableView reloadData]?

I have an application that has a UITableView. This UITableView is populated by an NSMutableArray being held (as a property) in the appDelegate. You can think of this as an email window. It lists messages in a subclassed UITableViewCell. When a new message appears, I have all the code done which downloads the message, adds the data to the appDelegate's NSMutableArray which holds all of the messages. This code is working fine.
Now, once the new message is downloaded and added to the array, I am trying to update my UITableView using the following code, however - the UITableView's delegate functions do not get called.
The odd thing is when I scroll my UITableView up and down, the delegate methods finally get called and my section headers DO change (they show the message count for that section). Shoudn't they update in real-time and not wait for my scrolling to trigger the refresh? Also, the new cell is never added in the section!!
Please Help!!
APPDELEGATE CODE:
[self refreshMessagesDisplay]; //This is a call placed in the msg download method
-(void)refreshMessagesDisplay{
[self performSelectorOnMainThread:#selector(performMessageDisplay) withObject:nil waitUntilDone:NO];
}
-(void)performMessageDisplay{
[myMessagesView refresh];
}
UITableViewController Code:
-(void) refresh{
iPhone_PNPAppDelegate *mainDelegate = (iPhone_PNPAppDelegate *)[[UIApplication sharedApplication] delegate];
//self.messages is copied from appDelegate to get (old and) new messages.
self.messages=mainDelegate.messages;
//Some array manipulation takes place here.
[theTable reloadData];
[theTable setNeedsLayout]; //added out of desperation
[theTable setNeedsDisplay]; //added out of desperation
}
As a sanity check, have you verified that theTable is not nil at that point?
You could try putting a delay on the reloadData call - I had a similar problem when I was trying to get my tableview to update when reordering cells, except that the app crashed if I called reloadData during it.
So something like this might be worth a try:
Refresh method:
- (void)refreshDisplay:(UITableView *)tableView {
[tableView reloadData];
}
and then call it with (say) a 0.5 second delay:
[self performSelector:(#selector(refreshDisplay:)) withObject:(tableView) afterDelay:0.5];
Hope it works...
If you call reloadData from within a dispatched method, make sure to execute it on the main queue.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0), ^(void) {
// hard work/updating here
// when finished ...
dispatch_async(dispatch_get_main_queue(), ^(void) {
[self.myTableView reloadData];
});
});
..same in method form:
-(void)updateDataInBackground {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0), ^(void) {
// hard work/updating here
// when finished ...
[self reloadTable];
});
}
-(void)reloadTable {
dispatch_async(dispatch_get_main_queue(), ^(void) {
[myTableView reloadData];
});
}
Have you tried setting a breakpoint in your refresh method just to be sure your messages array has the correct content before calling reloadData?