Pregunta

I started working with iOS. And using Storyboard to navigate between the view controllers. First screen is an uiviewcontroller(login screen) and second one is an uiviewcontroller with a table view. I'm sending some web requests in the first viewcontroller and then performing segue to the next viewcontroller. There is about 9 seconds delay to load the second view controller after getting the response. I tried checking the cause using Timer profiler and didnt find anything in my obj-c code.

If anyone can help me here is the link to my trace file.

My Log:

2014-05-08 10:12:12.601 Consumer[6713:4207] One 2014-05-08 10:12:12.602 Consumer[6713:4207] Three 2014-05-08 10:12:12.605 Consumer[6713:4207] Four 2014-05-08 10:12:12.606 Consumer[6713:4207] Two 2014-05-08 10:12:21.394 Consumer[6713:60b] numberOfSectionsInTableView 2014-05-08 10:12:21.395 Consumer[6713:60b] titleForHeaderInSection 2014-05-08 10:12:21.395 Consumer[6713:60b] numberOfRowsInSection 2014-05-08 10:12:21.395 Consumer[6713:60b] titleForHeaderInSection 2014-05-08 10:12:21.395 Consumer[6713:60b] numberOfRowsInSection 2014-05-08 10:12:21.396 Consumer[6713:60b] titleForHeaderInSection 2014-05-08 10:12:21.396 Consumer[6713:60b] numberOfRowsInSection 2014-05-08 10:12:21.396 Consumer[6713:60b] cellForRowAtIndexPath 2014-05-08 10:12:21.399 Consumer[6713:60b] returning cell 2014-05-08 10:12:21.399 Consumer[6713:60b] cellForRowAtIndexPath 2014-05-08 10:12:21.400 Consumer[6713:60b] returning cell 2014-05-08 10:12:21.401 Consumer[6713:60b] cellForRowAtIndexPath 2014-05-08 10:12:21.402 Consumer[6713:60b] returning cell 2014-05-08 10:12:21.402 Consumer[6713:60b] titleForHeaderInSection

My LoginViewController:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"login_success_new"]){
    TableViewController *controller = (TableViewController *)segue.destinationViewController;
    controller.municipalitiesArray = municipalitiesArray;
    controller.muni_metergroup_dict = muni_metergroup_dict;
    NSLog(@"Three");
}
}

-(void) sendPostRequest:(NSURL *)requestURL requestParams:(NSDictionary *)params requestType:(NSInteger)type{
NSError *error;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL];
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
//[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPMethod:@"POST"];

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];

NSData *postData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error];
[request setHTTPBody:postData];


NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    NSLog(@"response = %@",json);


    if(json != nil){
        switch (type) {
            case 1:
            {

                for (NSObject *object in [json objectForKey:@"municipalities"]){
                    MunicipalityModel *muniModel = [[MunicipalityModel alloc] init];
                    [muniModel setModelValues:object];
                    [municipalitiesArray addObject:muniModel];
                }
                //municipalitiesArray = [json objectForKey:@"municipalities"];
                //MunicipalitiesModel *muniModel = [[MunicipalitiesModel alloc] init];
                //[muniModel setModelValues:municipalitiesArray[0]];
                userEmail = @"admin@example.com";
                tokenValue = [json objectForKey:@"token"];
                NSString *stringUrl = [NSString stringWithFormat:@"http://%@.quality.sentry-link.com/api/v1/meter_groups.json",[municipalitiesArray[count] muniSubdomain]];
                NSURL *url = [NSURL URLWithString:stringUrl];
                [self sendGetRequest:url requestParams:nil requestType:2];

                break;
            }
            default:
                break;
        }
        //[self performSegueWithIdentifier:@"login_success" sender:self];
    }
}];

[postDataTask resume];

}

-(void) sendGetRequest:(NSURL *)requestURL requestParams:(NSDictionary *)params requestType:(NSInteger)type{

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL];
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"GET"];

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];

NSLog(@"Request URL =====> %@",requestURL);

NSURLSessionDataTask *getDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    NSLog(@"response = %@",json);


    if(json != nil){
        switch (type) {
            case 1:
            {
                break;
            }
            case 2:
            {
                 NSMutableArray *meterGroupsArray = meterGroupsArray = [[NSMutableArray alloc] init];

                for (NSObject *object in [json objectForKey:@"meter_groups"]){
                    MeterGroupModel *meterGroupModel = [[MeterGroupModel alloc] init];
                    [meterGroupModel setModelValues:object];
                    [meterGroupsArray addObject:meterGroupModel];
                }
                count++;
                [muni_metergroup_dict setValue:meterGroupsArray forKey:[municipalitiesArray[count-1] muniSubdomain]];
                if (count < [municipalitiesArray count]) {
                    NSString *stringUrl = [NSString stringWithFormat:@"http://%@.quality.sentry-link.com/api/v1/meter_groups.json",[municipalitiesArray[count] muniSubdomain]];
                    NSURL *url = [NSURL URLWithString:stringUrl];
                    [self sendGetRequest:url requestParams:nil requestType:2];
                }
                break;
            }

            default:
                break;
        }
        if(count ==[municipalitiesArray count]){
            NSLog(@"One");
            [self performSegueWithIdentifier:@"login_success_new" sender:self];
            NSLog(@"Two");
        }

    }
}];

[getDataTask resume];
}

TableviewController:

- (void)viewDidLoad
{
[super viewDidLoad];
//tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
NSLog(@"Four");
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (IBAction)buttonClicked:(id)sender{
NSLog(@"button Clicked");
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
NSLog(@"numberOfSectionsInTableView");
return [_municipalitiesArray count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
//Number of rows it should expect should be based on the section

NSString *sectionSubdomain = [_municipalitiesArray[section] muniSubdomain];
NSArray *array = [_muni_metergroup_dict objectForKey:sectionSubdomain];
NSLog(@"numberOfRowsInSection");
return [array count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSLog(@"titleForHeaderInSection");
return [self.municipalitiesArray [section] muniName];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"cellForRowAtIndexPath");
long row = [indexPath row];
long section = [indexPath section];
NSArray *meterGroupArray = [_muni_metergroup_dict valueForKey:[_municipalitiesArray[section] muniSubdomain]];
static NSString *CellIdentifier = @"tableCell";

TableViewCell *cell = [tableView
                          dequeueReusableCellWithIdentifier:CellIdentifier
                          forIndexPath:indexPath];

// Configure the cell...

[cell.lblMeterGroupName setText:[meterGroupArray[row] groupName]];
[cell.lblMeterGroupId setText:[meterGroupArray[row] groupId]];
[cell.lblLatitude setText:[meterGroupArray[row] latitude]];
[cell.lblLongitude setText:[meterGroupArray[row] longitude]];



NSLog(@"returning cell");
return cell;
}

Thanks in advance!

¿Fue útil?

Solución

The problem, clearly displayed in your log, is that One, Two, Three, and Four are being performed on a background thread. This means, for example, that you are saying:

[self performSegueWithIdentifier:@"login_success_new" sender:self];

...on a background thread. That is so wrong. You must NEVER say anything to or about the interface on a background thread. You need to get your threading straightened out. (The fact that One, Two, Three, and Four do not happen in order is also a clue that you may have set this up incoherently.)

EDIT: In a comment, you say that you now used dispatch_async(dispatch_get_main_queue()..., thus correctly moving the call to performSegueWithIdentifier: onto the main thread. Excellent! Your logging should now show that all calls connected with the interface (including especially "Three" in prepareForSegue:) are now on the main thread.

However, you still need to be careful. Basically everything in both completion: handlers happens on a background thread! You are even calling [self sendGetRequest:...] on a background thread! And you are apparently talking to instance variables of self on this a background thread. All of that is dangerous. What I would do is step out to the main thread right at the start of each completion handler, so that even if the completion handler is called on a background thread, everything I then do happens on the main thread.

Otros consejos

Make sure that you are not performing your web request on the main thread which will block your UI and wait for the request to finish before performing the segue.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top