Reputation: 13
I am new to IOS programming but, I have an issues I have been stuck on for over a day and I cannot find a solution. I have an app that on the first run after installation needs to download some content. after the download is complete the View which is the RootView controller does not refresh data for the view.I can navigate to other views which are populated correctly but this view isn't. if i close the app and reopen it the data is there. So i need a method to force the view to completely reload or restart the app.
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface RootViewController : UIViewController <NSFetchedResultsControllerDelegate>{
}
@property (nonatomic, retain) IBOutlet UIImageView *bannerImageView;
@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
-(void)populateBannerImages;
-(void)getimage;
here is my .m file
@implementation RootViewController
@end
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title=@"MyTitle";
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
I run the dialog for the download feature in the app delegate with the code sample below. i know the issue is that i call the UIAlert from the appDidFinishLAunching,and the rootViewController is already loaded at this point, but I'm not sure of a better way to do this.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
BOOL hasRunBefore=[[NSUserDefaults standardUserDefaults] boolForKey:@"FirstRun"];
if (hasRunBefore) {
}else if(!hasRunBefore){
UIAlertView *firstRunAlert =[[UIAlertView alloc]initWithTitle:@"Welcome" message:@"" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"DownLoad", nil];
[firstRunAlert show];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"FirstRun"];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
NSString *buttontitle = [alertView buttonTitleAtIndex:buttonIndex];
if ([buttontitle isEqualToString:@"DownLoad"]) {
/download stuff here
}
}
Any constructive ideas or help would be greatly appreciated
Upvotes: 0
Views: 1877
Reputation: 769
Using the NSNotificationCenter
might be overkill. Since you have an NSFetchedResultsController
, I would consider setting your view controller as its delegate and implementing the NSFetchedResultsControllerDelegate#controllerDidChangeContent:
method.
For your case, the simplest implementation of that method will just call [tableView reloadData]
. See the protocol's docs for more info.
Upvotes: 0
Reputation: 676
Assuming your core-data saving and fetching are done properly, the best way to do is through NSNotificationCenter. In your AppDelegate Class, you need to post the notification to to the notification center after data is down downloading. This should only be posted after the data download is completely finished. Maybe something like this:
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataFinishedDownloading"
object:self];
Then in your RootViewController class, first you need to register the RootViewController class to listen to that notification. Maybe in the init method:
-(id)init
{
self = [super init];
if(self)
{
// We add this instance of RootViewController class as an observer of the "DataFinishedDowloading"
// Once this notification is posted to the notification center from appDelegate
// RootViewController will be notified and the method inside selector will be called
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(receivedDataFinishedDownloadingNotification:)
name:@"DataFinishedDownloading"
object:nil];
}
return self;
}
- (void)receivedDataFinishedDownloadingNotification:(NSNotification*)notification
{
// Once the images are done downloading, you just need to refresh the tableView. It will
// then display the newly acquired data in your table cells.
[tableView reloadData];
}
The only other issue that might arise (and it may not) is that if the data downloading happens fast enough. Once in a while, if the data comes down fast enough and viewDidAppear of the viewController hasn't happened yet, notification method will try to reloadData before viewDidAppear has happened. This can cause a crash once in a blue moon. Normally a boolean set in viewDidAppear and checked before reloadData is called is a good idea. Hope this helps.
Upvotes: 1
Reputation: 100581
[self.tableView reloadData]
)[self.window setRootViewController:newController]
this resets the whole view (=> bad user experience)Upvotes: 1