Iphone 为什么popViewController每隔一段时间才工作
我完全被难住了,情况如下: 我的应用程序使用核心位置框架获取用户的当前位置,然后ping我的服务器以查找附近感兴趣的位置,并将其显示为列表。没问题 为了节省电池,我在从服务器获取数据后关闭GPS服务。如果用户在使用应用程序时四处移动,并想要一个新列表,他单击导航控制器上的“刷新”,然后再次激活CLLocation服务,则会从服务器检索一批新数据并重新绘制该表 当应用程序从我的服务器抓取数据时,我加载了一个加载屏幕,屏幕上有一个旋转的地球仪,上面写着“正在加载,请稍候”,我隐藏了导航栏,这样他们就不会点击“返回” 因此,从服务器抓取的初始数据是完美的 我第一次点击refresh时,所有代码都会执行以获取新位置,再次ping服务器以获取新的数据列表并更新单元格。但是,它没有像应该的那样加载表视图,而是恢复了表视图的导航控制器栏,但仍然在主窗口中显示我的加载视图。这只在设备上是真实的,在模拟器中一切都很好 第二次点击刷新时,该功能正常工作 第三次按刷新时,它失败,如上所述 我第四次按“刷新”时,它工作正常 第五次按刷新时,它失败,如上所述 以此类推,偶数刷新成功,奇数刷新失败。我一行一行地检查了我所有的代码,似乎一切都在正常执行。实际上,我继续浏览核心指令,在大量单击“逐步浏览”之后,我发现在CFRunLoopRunSpecific中的某个点上,表视图确实显示在屏幕上,但我随后单击了“继续”,我的加载视图接管了屏幕 我完全困惑不解。请帮忙!!非常感谢您的洞察力 相关代码: RootViewControllerMethods(这是此TableView项目的基础视图) CLController方法:基本上只是将所有数据直接发送回RootViewControllerIphone 为什么popViewController每隔一段时间才工作,iphone,cocoa-touch,uiviewcontroller,uinavigationcontroller,Iphone,Cocoa Touch,Uiviewcontroller,Uinavigationcontroller,我完全被难住了,情况如下: 我的应用程序使用核心位置框架获取用户的当前位置,然后ping我的服务器以查找附近感兴趣的位置,并将其显示为列表。没问题 为了节省电池,我在从服务器获取数据后关闭GPS服务。如果用户在使用应用程序时四处移动,并想要一个新列表,他单击导航控制器上的“刷新”,然后再次激活CLLocation服务,则会从服务器检索一批新数据并重新绘制该表 当应用程序从我的服务器抓取数据时,我加载了一个加载屏幕,屏幕上有一个旋转的地球仪,上面写着“正在加载,请稍候”,我隐藏了导航栏,这样他们就
// Called when the location is updated
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(@"New Location: %@ \n", newLocation);
NSLog(@"Old Location: %@ \n", oldLocation);
@synchronized(self) {
NSNumber *lat = [[[NSNumber alloc] init] autorelease];
NSNumber *lon = [[[NSNumber alloc] init] autorelease];
lat = [NSNumber numberWithFloat:newLocation.coordinate.latitude];
lon = [NSNumber numberWithFloat:newLocation.coordinate.longitude];
[self.delegate noteLat:lat];
[self.delegate noteLon:lon];
[self.delegate noteNewLocation:newLocation];
[self.delegate updateCells];
}
}
在调用updateCells时,是否可以尝试调试应用程序以查看控件的位置?应用程序似乎没有任何明显的问题 确保在LoadingViewController类中没有内存警告。如果出现内存警告,并且正在释放RootViewController的视图,则在弹出RootViewController时,将再次调用viewDidLoad
在viewDidLoad和updateCells中保留断点。您确定没有在其他任何地方调用LoadingViewController吗?第一个想法是,在推送加载视图之前,您可能不想将startUpdatingLocation发送到CLLocationManager。通常,第一条-locationManager:didUpdateToLocation:fromLocation:消息会与缓存的GPS数据一起立即出现。只有当您处理每条消息,而不是如示例代码所示过滤GPS数据时,这才重要。但是,这不会导致您描述的情况-它会导致加载屏幕卡住 在另一种情况下,我也经历过类似的奇怪行为,在切换到其他选项卡时,我试图弹出根视图控制器,但调用没有在正确的位置进行。我相信popToRootViewController为我打了两次电话。我怀疑你的加载视图不是被推了两次就是被弹出了两次 我建议在加载ViewController时只需最少的日志记录即可实现-viewWillAppease:、-viewDidAppease:、-viewWillEveal:和-viewDidEveal:
- (void)viewWillAppear:(BOOL)animated {
NSLog(@"[%@ viewWillAppear:%d]", [self class], animated);
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
NSLog(@"[%@ viewDidAppear:%d]", [self class], animated);
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
NSLog(@"[%@ viewWillDisappear:%d]", [self class], animated);
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
NSLog(@"[%@ viewDidDisappear:%d]", [self class], animated);
[super viewDidDisappear:animated];
}
然后,在设备上运行测试,查看它们是否总是发送到视图控制器以及发送频率。您可以向-updateClicked添加一些日志记录,以显示双击
另一种想法是,尽管@synchronized块是个好主意,但它只会阻止其他线程执行这些语句,直到第一个线程退出该块。我建议将-stopUpdatengLocation消息移动到@synchronized块中的第一条语句。这样,一旦你决定对一些新的GPS数据采取行动,你就会立即告诉CLLocationManager停止发送新数据。所以,我从来没有让它起作用。我只在每次以编程方式调用popViewController时才在设备上观察到这种行为,而不是允许导航控制器上的默认后退按钮进行弹出操作 我的解决方法是构建一个自定义加载视图,每次由于访问互联网而出现延迟时,都将屏幕翻转到该视图。我的方法使用一个布尔变量yes或no-yes切换到加载屏幕,no切换回正常视图。代码如下:
- (void)switchViewsToLoading:(BOOL)loading {
// Start the Animation Block
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:self.tableView cache:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:.75];
// Animations
if(loading) {
if (lv == nil) { lv = [[LoadingViewController alloc] initWithNibName:@"Loading" bundle:nil]; }
[self.view addSubview:lv.view];
[self.view sendSubviewToBack:self.tableView];
self.title = @"TrailBehind";
}
else {
[lv.view removeFromSuperview];
}
// Commit Animation Block
[UIView commitAnimations];
//It looks kind of dumb to animate the nav bar buttons, so set those here
if(loading) {
self.navigationItem.rightBarButtonItem = nil;
self.navigationItem.leftBarButtonItem = nil;
self.title = @"TrailBehind";
}
else {
UIBarButtonItem *feedback = [[UIBarButtonItem alloc] initWithTitle:@"Feedback" style:UIBarButtonItemStylePlain target:self action:@selector(feedbackClicked)];
self.navigationItem.rightBarButtonItem = feedback;
UIBarButtonItem *update = [[UIBarButtonItem alloc] initWithTitle:@"Move Me" style:UIBarButtonItemStylePlain target:self action:@selector(updateClicked)];
self.navigationItem.leftBarButtonItem = update;
[feedback release];
[update release];
}
}查看您的原始代码,我非常怀疑这一块:
- (void)viewDidLoad {
...
lv = [[LoadingViewController alloc] initWithNibName:@"Loading" bundle:nil];
[self.navigationController pushViewController:lv animated:YES];
[super viewDidLoad];
}
viewDidLoad
在每次加载NIB时都会被调用,这种情况可能会发生多次,特别是当内存不足时(考虑到您的评论,这可能只发生在设备上)。我建议您实施-didReceiveMemoryWarning
,在调用super之后,至少打印一份日志,以便查看是否发生在您身上
上面的代码让我感到困扰的是,几乎可以肯定的是,您正在泄漏
lv
,这意味着可能会有越来越多的加载ViewController
。你说这是一个类变量。你真的是说它是一个实例变量吗?IVAR应始终使用访问者(self.lv
或[self-lv]
而不是lv
)。不要直接分配给他们;你几乎总是做错事(因为你可能在这里做错事)。我在搜索完全相同的问题时遇到了这个问题,
- (void)viewDidLoad {
...
lv = [[LoadingViewController alloc] initWithNibName:@"Loading" bundle:nil];
[self.navigationController pushViewController:lv animated:YES];
[super viewDidLoad];
}