Iphone 根据NSURL请求的结果更新接口
我有一个应用程序,根据NSURL请求的结果更新界面。我将其设置为,当我的应用程序进入前台时,仅当当前视图控制器名为“ProfileViewController”时,才会触发请求 我的问题是,每次我从后台带回应用程序时,界面都会锁定几秒钟。我试图完全理解主线程/后台线程,但不确定在执行NSURL检查时如何使应用程序保持响应。任何帮助都会很好!谢谢 在我看来,加载方法:Iphone 根据NSURL请求的结果更新接口,iphone,ios,objective-c,Iphone,Ios,Objective C,我有一个应用程序,根据NSURL请求的结果更新界面。我将其设置为,当我的应用程序进入前台时,仅当当前视图控制器名为“ProfileViewController”时,才会触发请求 我的问题是,每次我从后台带回应用程序时,界面都会锁定几秒钟。我试图完全理解主线程/后台线程,但不确定在执行NSURL检查时如何使应用程序保持响应。任何帮助都会很好!谢谢 在我看来,加载方法: -(void)viewDidLoad { [super viewDidLoad]; [[NSNotificat
-(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];
}
}
- (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];
}
}
然后在我的应用程序中返回活动方法:
-(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];
}
}
- (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];
}
}
最后,在我的Did-Update-Location方法中,我得到了用户和位置之间的距离。如果结果等于1,则更新界面以显示不同的按钮。这就是界面冻结的地方:
-(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];
}
}
- (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];
}
}
新方法:
-(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];
}
}
- (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。你可以使用的一个简单的基础API是:
要解决您的问题,请将创建代码的按钮移动到一个单独的方法中,并从旧方法(通过CoreLocation委托协议在单独的线程上调用)通过“performSelectorOnMainThread
”调用该新方法,这样您就可以开始了
NSData *distanceURLResult = [NSData dataWithContentsOfURL:[NSURL
URLWithString:distanceURL]];
是一个同步呼叫。这意味着您的代码将等待网络调用的结果继续。您应该使用NSURLConnection()或AFNetworking发出异步请求。感谢您的响应!!!我是否应该将didUpdateLocation方法中的所有内容都放在即将创建的新方法中?我假设我会把几乎所有的东西都放在if(currentLocation!=nil)行下面。在我自己的代码中,如果我需要从后台线程中修改主线程上的UI,我会在单独的线程上尽可能多地做,以保持用户界面(和用户体验)尽可能精神饱满。似乎在工作!!一个相关的小问题。当我在新方法中包含包含currentLocation.coordinate.longitude的NSString时,我得到一个错误,我可以修复它吗?当然,您可以修复它。其中一个参数是“
withObject
”。为什么不把那串东西传过去?哇。太明显了。你太棒了!事实上,我需要更新我的问题并发布我到目前为止的代码,因为无论我做了什么,我的应用程序都会崩溃。好的,迈克尔,刚刚更新过。有什么想法吗?非常感谢。