从 NSURL 请求的结果更新接口



我有一个应用程序,可以根据 NSURL 请求的结果更新界面。我已经设置了它,以便在我的应用程序进入前台时触发请求,并且仅当当前视图控制器称为"ProfileViewController"时。

我的问题是每次我从后台恢复应用程序时,界面都会锁定几秒钟。我正在尝试完全了解主/后台线程,但不确定在执行 NSURL 检查时我能做些什么来使应用程序保持响应。任何帮助都会很棒!谢谢!

在我看来确实加载方法:

-(void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(appReturnsActive) name:UIApplicationDidBecomeActiveNotification
    object:nil];
    //additional code
}

然后在我的应用程序中返回活动方法:

- (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];    
    }
}

最后,在我的"确实更新了位置方法"中,我得到了用户和位置之间的距离。如果结果等于 1,则我更新界面以显示不同的按钮。这是界面冻结的地方:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation 
*)newLocation fromLocation:(CLLocation *)oldLocation {
    CLLocation *currentLocation = newLocation;
    if (currentLocation != nil) {
        [self performSelectorOnMainThread:@selector(buttonUpdate:)
        withObject:NULL waitUntilDone:NO];
    }
}

新方法:

-(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];
        }
}

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

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

performSelectorOnMainThread:withObject:waitUntilDone:

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

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 发出异步请求。

最新更新