1

I have an app that updates the interface depending on the result of a NSURL request. I have set it up so that the request is fired when my app comes into the foreground, and only if the current view controller is called "ProfileViewController".

My problem is that the interface locks up for a few seconds every time I bring the app back from the background. I am trying to fully understand main/background threads, but am not sure what I can do to make the app remain responsive while the NSURL check is being performed. Any assistance would be great! Thanks!

In my View Did Load Method:

-(void)viewDidLoad {

    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(appReturnsActive) name:UIApplicationDidBecomeActiveNotification
    object:nil];

    //additional code
}

Then in my App Returns Active Method:

- (void)appReturnsActive {

    [myTimer invalidate];
    myTimer = nil;

    //ONLY WANT TO PERFORM THE UPDATE IF VIEWING THE PROFILE VIEW CONTROLLER
    UIViewController *currentVC = self.navigationController.visibleViewController;
    NSString * name = NSStringFromClass([currentVC class]);
    if ([name isEqualToString:@"ProfileViewController"]) { 

        [activityIndicator startAnimating];
        [activityIndicatorTwo startAnimating];
        locationManagerProfile.delegate = self;
        locationManagerProfile.desiredAccuracy = kCLLocationAccuracyBest;
        [locationManagerProfile startUpdatingLocation];    
    }
}

Finally, in my Did Update Location Method, I get the distance between the user and the location. If the result is equal to 1, then I update the Interface to show different buttons. This is where the interface freezes up:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation 
*)newLocation fromLocation:(CLLocation *)oldLocation {

    CLLocation *currentLocation = newLocation;
    if (currentLocation != nil) {

        [self performSelectorOnMainThread:@selector(buttonUpdate:)
        withObject:NULL waitUntilDone:NO];

    }
}

New Method:

-(void)buttonUpdate {

NSString *userLongitude =[NSString stringWithFormat:@"%.8f", 
        currentLocation.coordinate.longitude];
        NSString *userLatitude = [NSString stringWithFormat:@"%.8f", 
        currentLocation.coordinate.latitude];
        [locationManagerProfile stopUpdatingLocation];
        NSString *placeLatitude = [[NSUserDefaults standardUserDefaults]
                                   stringForKey:@"savedLatitude"];
        NSString *placeLongitude = [[NSUserDefaults standardUserDefaults]
                                    stringForKey:@"savedLongitude"];
        NSString *distanceURL = [NSString 
        stringWithFormat:@"http://www.website.com/page.php?
        lat1=%@&lon1=%@&lat2=%@&lon2=%@",userLatitude, userLongitude, placeLatitude, 
        placeLongitude];

        NSData *distanceURLResult = [NSData dataWithContentsOfURL:[NSURL 
        URLWithString:distanceURL]];

        NSString *distanceInFeet = [[NSString alloc] initWithData:distanceURLResult 
        encoding:NSUTF8StringEncoding];

        if ([distanceInFeet isEqualToString:@"1"])
        {
            UIBarButtonItem *btnGo = [[UIBarButtonItem alloc] initWithTitle:@"Button 1" 
            style:UIBarButtonItemStyleBordered target:self 
            action:@selector(actionTwo)];
            self.navigationItem.rightBarButtonItem = btnGo;

            UIBarButtonItem *btnGoTwo = [[UIBarButtonItem alloc] initWithTitle:@"Button 
            Two" style:UIBarButtonItemStyleBordered target:self 
            action:@selector(actionOne)];
            self.navigationItem.rightBarButtonItem = btnGoTwo;

            self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:btnGo, 
            btnGoTwo, nil];
        }
}
4

2 回答 2

0
NSData *distanceURLResult = [NSData dataWithContentsOfURL:[NSURL 
    URLWithString:distanceURL]];

是同步调用。这意味着您的代码将等待网络调用的结果继续。您应该使用 NSURLConnection ( http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html ) 或 AFNetworking 发出异步请求。

于 2013-06-21T10:31:28.160 回答
0

您的 CoreLocation 委托方法(例如“ didUpdateToLocation”等)都发生在后台,在辅助线程上,而与 UI 相关的所有事情都需要在主线程上发生

要解决您的问题,您应该在主线程上修改您的 UI。您可以使用的方便的基础 API 之一是:

performSelectorOnMainThread:withObject:waitUntilDone:

要解决您的问题,请将您的按钮创建代码移动到一个单独的方法中,并通过performSelectorOnMainThread旧的“”调用该新方法(通过 CoreLocation 委托协议在单独的线程上调用),您应该很高兴。

于 2013-06-21T10:05:10.223 回答