我有一个应用程序,可以根据 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 发出异步请求。