0

So I am using NSURLConnection delegate to download a JSON feed in my AppDelegate.m file. Now I have a problem. My application:didFinishLaunchingWithOptions is shown below:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// Display the progress indicator
HUD = [[MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES] retain];

// Start the HTTP request
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:
                         [NSURL URLWithString:@"*****some url here*********"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];

// Display the navigation controller
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];

return YES;

}

So all I do is display an activity indicator, start the HTTP request (which is when the NSURLConnection delegate starts working) and then I display my Navigation Controller's root view controller. Now the problem is that it will load that view, which has a table view, without any data in it (since NSURLConnection) hasn't finished downloading the data. It looks quite ugly because I have static UILabels that I made on interface builder so it displays them and then after loading it will show the data. I have an activity indicator in the middle of the screen so all along the user knows that new data is loading.

Now after my NSURLConnection finishes downloading the data, the view loads one more time for some weird reason. I know that because if I put NSLog(@"Test"); in my viewDidLoad method, it prints out twice. At the end of the application:didFinishLaunchingWithOptions and at the end of the connectionDidFinishLoading. Why is that? How do I make it look neat, where the view loads once after my data has been loaded? Any suggestions?

Thank you all,

EDIT: More code in the AppDelegate before application:didFinishLaunchingWithOptions

- (void)hudWasHidden {
    // Remove HUD from screen when the HUD was hidded
    [HUD removeFromSuperview];
    [HUD release];
}

#pragma mark -
#pragma mark NSURLConnectionDelegete

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"Starting Response");

    [responseData setLength:0];
    expectedLength = [response expectedContentLength];
    currentLength = 0;

    // Change the progress indicator to the loading wheel
    HUD.mode = MBProgressHUDModeDeterminate;

    NSLog(@"Done Response");
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    NSLog(@"Starting Data");

    [responseData appendData:data];
    currentLength += [data length];

    // Calculate progress indicator progress
    HUD.progress = currentLength / (float)expectedLength;

    NSLog(@"Done Data");
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {

    NSLog(@"Start Error");

    [HUD hide:YES];

    UIAlertView *alert = [[UIAlertView alloc] 
                          initWithTitle:@"Error" 
                          message:@"Please check your network connection and relaunch the application" 
                          delegate:self 
                          cancelButtonTitle:@"Dismiss" 
                           otherButtonTitles:nil, nil];
    [alert show];
    [alert release];

    [connection release];

    NSLog(@"Done Error");
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    NSLog(@"Start Finish Loading");

    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

    if ([responseString isEqualToString:@"Unable to find specified resource."]) {
        NSLog(@"Unable to find specified resource.n");
    } 

    else {

        ListingsViewController *listingsViewController = [[ListingsViewController alloc] initWithNibName:@"ListingsViewController" bundle:nil];
        listingsViewController.jsonData = responseString;
        [self.navigationController pushViewController:listingsViewController animated:NO];
        [self.navigationController setViewControllers:[NSArray arrayWithObject:listingsViewController] animated:NO];
        [listingsViewController release];
    }

    // Save the pList to the Documents directory in iOS

    ListingsViewController *listingsViewController = (ListingsViewController *)[self.navigationController topViewController];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectoryPath = [paths objectAtIndex:0];
    NSString *plistFilePathInDocumentsDirectory = [documentsDirectoryPath stringByAppendingPathComponent:@"Channels.plist"];

    // Instantiate a modifiable array and initialize it with the content of the plist file
    NSMutableDictionary *channelsData = [[NSMutableDictionary alloc] initWithContentsOfFile:plistFilePathInDocumentsDirectory];

    if (!channelsData) {
        NSString *plistFilePathInMainBundle = [[NSBundle mainBundle] pathForResource:@"Channels" ofType:@"plist"];

        // Instantiate a modifiable array and initialize it with the content of the plist file in main bundle
        channelsData = [[NSMutableDictionary alloc] initWithContentsOfFile:plistFilePathInMainBundle];
    }

    // Set the ListingsViewController's's savedChannels array
    listingsViewController.channelsDict = channelsData;

    [channelsData release];

    // Display progress indicator checkmark and hide
    HUD.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]] autorelease];
    HUD.mode = MBProgressHUDModeCustomView;
    [HUD hide:YES afterDelay:1];

    [connection release];
    [responseData release];

    NSLog(@"Done finish loading");
    [window removeFromSuperview];
}
darksky
  • 20,411
  • 61
  • 165
  • 254
  • this answer may me useful to you.....http://stackoverflow.com/questions/1081131/viewdidload-getting-called-twice-on-rootviewcontroller-at-launch – Aravindhan Jun 17 '11 at 17:55
  • Are you getting any memory warnings in your console window? If the system is running low on memory, the OS will try to unload views as needed, which could cause your viewDidLoad method to fire twice. – BP. Jun 17 '11 at 17:55
  • Nope. Actually, I am getting a very weird error during connection:didReceiveData The error is: : CGPathAddArc: invalid value for start or end angle. I tried searching what Error CGPathAddArc is and I found nothing online Note: I am not using "CGPathAddArc". I am just using json-framework. – darksky Jun 17 '11 at 17:59
  • I think it would be useful to see some more code... – tc. Jun 18 '11 at 00:06
  • I guess the CGPathAddArc error comes from the HUD Control you're using, because it has an invalid progress value... does your HUD control display progress with a circle? – codeclash Jun 18 '11 at 10:29
  • @tc I added more code on top. @cardinal yes it does circle. – darksky Jun 20 '11 at 06:30

1 Answers1

0

It's all in your code:

    ListingsViewController *listingsViewController = [[ListingsViewController alloc] initWithNibName:@"ListingsViewController" bundle:nil];
    listingsViewController.jsonData = responseString;
    [self.navigationController pushViewController:listingsViewController animated:NO];
    [self.navigationController setViewControllers:[NSArray arrayWithObject:listingsViewController] animated:NO];
    [listingsViewController release];

You're creating a new ListingsViewController and replacing the old one with it. The new ListingsViewController doesn't have its view loaded yet. (You don't need to call both -pushViewController:animated: and -setViewControllers:; the second one overrides the first in this case).

Other things:

  • In -hudWasHidden, you probably want to do [HUD release]; HUD = nil;.
  • It's not clear what [window removeFromSuperview] is trying to achieve (it probably does nothing, since windows don't have superviews).
tc.
  • 33,468
  • 5
  • 78
  • 96
  • Is there anything wrong with creating a new ListingsViewController and replacing it? What are my alternatives to achieve what I want? – darksky Jun 22 '11 at 07:43
  • There's nothing fundamentally wrong with it, but it's what's causing your view to be loaded twice. If all you want is a "Loading" screen, it might be worthwhile creating a new controller for it. – tc. Jun 23 '11 at 23:32