6

내가 완전히 난처한 상황에 빠진 나는 다른 모든 시간을 작동합니까, 여기 상황이다 목록으로 표시합니다. 아무 문제 없습니다.왜 popViewController 만

배터리를 절약하기 위해 서버에서 데이터를받은 후 GPS 서비스를 끕니다. 사용자가 앱을 사용하는 동안 주위를 돌아 다니며 탐색 컨트롤러에서 "새로 고침"을 클릭하고 CLLocation 서비스가 다시 활성화되면 서버에서 새로운 데이터 배치가 검색되고 테이블이 다시 그려집니다.

앱이 내 서버에서 데이터를 가져 오는 동안 "로드 중입니다. 기다려주세요"라는 회전하는 지구본이있는 로딩 화면을로드하고 탐색 바를 숨겨 "뒤로"누르지 않습니다.

따라서 서버의 초기 데이터 수집은 완벽하게 진행됩니다.

처음 새로 고침을 누르면 모든 코드가 실행되어 새 위치를 가져오고 서버에 새 데이터 목록을 핑하고 셀을 업데이트합니다. 그러나 테이블 뷰를로드하는 대신 테이블 뷰의 탐색 컨트롤러 막대를 복원해야하지만 기본 창에서로드 뷰를 계속 보여줍니다. 이것은 기기에만 해당되며 시뮬레이터에서는 모든 것이 정상적으로 작동합니다.

두 번째로 새로 고침을 누르면 기능이 정상적으로 작동합니다.

내가 새로 고침 한 세 번째 시간은 위와 같이 실패합니다.

내가 새로 고침 한 네 번째 시간은 정상적으로 작동합니다.

내가 처음으로 새로 고침을 한 경우 위와 같이 실패합니다.

등, 심지어 새로 고침이 성공하고 홀수 새로 고침이 실패합니다. 모든 코드를 한 줄씩 밟았으며 모든 것이 정상적으로 실행되는 것 같습니다. 실제로 핵심 지침을 계속해서 실행하고 거대한 양의 "step over"를 클릭하면 테이블 뷰가 실제로 CFRunLoopRunSpecific의 일부 지점에서 화면에 표시된다는 것을 알았지 만 그 다음에 "계속"을 클릭하고 로딩 뷰를 넘겼습니다 화면.

나는 정말 당혹 스럽다. 도와주세요!! 당신의 통찰에 미리 감사드립니다.

Video of the strange behavior:

관련 코드 :

RootViewControllerMethods

- (void)viewDidLoad { 
    //Start the Current Location controller as soon as the program starts. The Controller calls delegate methods 
    //that will update the list and refresh 
    [MyCLController sharedInstance].delegate = self; 
    [[MyCLController sharedInstance].locationManager startUpdatingLocation]; 
    lv = [[LoadingViewController alloc] initWithNibName:@"Loading" bundle:nil]; 
    [self.navigationController pushViewController:lv animated:YES]; 
    [super viewDidLoad]; 
} 



- (void)updateClicked { 
    //When the location is successfully updated the UpdateCells method will stop the CL manager from updating, so when we want to update the location 
    //all we have to do is start it up again. I hope. 
    [[MyCLController sharedInstance].locationManager startUpdatingLocation]; 
    [self.navigationController pushViewController:lv animated:YES]; 
    //LV is a class object which is of type UIViewController and contains my spinning globe/loading view. 
} 



-(void)updateCells { 
    //When the Core Location controller has updated its location it calls this metod. The method sends a request for a JSON dictionary 
    //to trailbehind and stores the response in the class variable jsonArray. reloadData is then called which causes the table to 
    //re-initialize the table with the new data in jsonArray and display it on the screen. 

    [[MyCLController sharedInstance].locationManager stopUpdatingLocation]; 

    if(self.navigationController.visibleViewController != self) { 
     self.urlString = [NSString stringWithFormat:@"http://www.trailbehind.com/iphone/nodes/%@/%@/2/10",self.lat,self.lon]; 
     NSURL *jsonURL = [NSURL URLWithString:self.urlString]; 
     NSString *jsonData = [[NSString alloc] initWithContentsOfURL:jsonURL]; 
     NSLog(@"JsonData = %@ \n", jsonURL); 
     self.jsonArray = [jsonData JSONValue]; 
     [self.tableView reloadData]; 
     [self.navigationController popToRootViewControllerAnimated:YES]; 
     [jsonData release]; 
    } 
} 

CLController 방법은 (이것은이 TableView 프로젝트의 기본보기) : 기본적으로 그냥 RootViewController

바로 다시 모든 데이터를 전송
// 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]; 
    } 
} 
+0

디버거에서 이러한 방법을 수행 했습니까? 인스트루먼트를 실행하여 오브젝트 생성/삭제가 예상 한 결과인지 확인하십시오. 죄송합니다. 귀하의 정보를 모욕하는 것이지만 빠른보기에서 문제가 보이지 않으면 다음 단계는 단계별로 시작하는 것입니다. – mikeh

+0

앱을 탈퇴해도 팝업이 발생합니까? 비디오에서 GPS 수정 사항을 얻을 수있는 충분한 시간을 앱에 제공하지 않는 것처럼 보입니다. locationManager 메소드에서 중단 점을 설정하십시오. –

답변

0

응용 프로그램을 디버깅하여 updateCells를 호출 할 때 컨트롤이 어디로 이동하는지 확인할 수 있습니까? 분명히 앱에 문제가있는 것 같지 않습니다.

LoadingViewController 클래스에있는 동안 메모리 경고가 없는지 확인하십시오. 메모리 경고가 있고 RootViewController의 뷰가 해제되면 RootViewController에 팝업 할 때 viewDidLoad가 다시 호출됩니다.

viewDidLoad 및 updateCells에 중단 점을 유지합니다. LoadingViewController를 다른 곳에서 호출하지 않았습니까?

+0

두 함수 모두에 중단 점을 넣었으며로드하는 화면이 팝되면 viewDidLoad가 호출되지 않습니다. 또한 didRecieveMemoryError 함수 중 아무 것도 호출되지 않습니다. updateCells가 호출되면 컨트롤이 핵심 스택으로 돌아오고, 거기에있는 어떤 것이 나를 망쳐 놓을 수도 있습니다. –

1

첫 번째 생각은로드 뷰를 밀어 넣기 전까지는 startUpdatingLocation을 CLLocationManager에 보내지 않는 것이 좋습니다. 종종 첫 번째 -locationManager : didUpdateToLocation : fromLocation : 메시지가 캐시 된 GPS 데이터와 함께 즉시 나타납니다. 이것은 모든 메시지에 대해 행동하고 샘플 코드에 표시된대로 GPS 데이터를 필터링하지 않는 경우에만 중요합니다. 그러나 이렇게하면 설명 된 상황이 발생하지 않습니다.로드하는 화면이 멈추는 원인이됩니다.

다른 탭으로 전환 할 때 루트보기 컨트롤러로 팝업하려고하는 다른 상황에서 이와 비슷한 이상한 동작이 발생했으며 정확한 위치에서 통화가 이루어지지 않았습니다. popToRootViewController 나를 위해 두 번 호출되는 믿습니다. 내 생각 엔로드보기가 두 번 푸시되거나 두 번 튀어 오르는 것입니다.

LoadingViewController에서 최소한의 로깅으로 -viewWillAppear :, -viewDidAppear :, -viewWillDisappear : 및 -viewDidDisappear :를 구현하는 것이 좋습니다.

- (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 블록이 좋은 생각이지만 첫 번째 스레드가 블록을 종료 할 때까지는 다른 스레드가 해당 명령문을 실행하지 못하게합니다. 그 동기화 된 블록 내부의 첫 번째 명령문으로 -stopUpdatingLocation 메시지를 옮기는 것이 좋습니다. 그렇게하면, 일단 새로운 GPS 데이터에 대해 행동하기로 결정하면 CLLocationManager에 새로운 데이터 전송을 중단하도록 즉시 알립니다.

0

이렇게 나는 결코 작동하지 못했습니다. 나는 팝핑을하기 위해 네비게이션 컨트롤러의 기본 뒤로 버튼을 허용하는 대신 프로그래밍 방식으로 popViewController를 호출 할 때마다 장치에서이 동작을 관찰합니다.

제 해결 방법은 사용자 지정로드보기를 작성하고 인터넷 액세스로 인해 지연 될 때마다 해당보기로 화면을 전환하는 것입니다. 내 메서드는 부울 변수 yes 또는 no를 사용합니다. 예는로드하는 화면으로 전환하고 다시 정상적인보기로 전환하지 않습니다. 여기에 코드입니다 :}

0

- (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이로드 될 때마다 호출, 다중 어떤 일이 일어날 수 있습니다 특히 메모리가 부족한 경우 (특히 장치에서만 발생하는 것으로 보이는 경우) -didReciveMemoryWarning을 구현하고 super를 호출 한 후 로그를 인쇄하면 로그가 있는지 여부를 확인할 수 있습니다.

위의 코드에 대해 저를 괴롭히는 것은 lv을 거의 유출한다는 것입니다. 즉, LoadingViewControllers의 숫자가 증가 할 수 있습니다. 클래스 변수라고 말하면됩니다. 정말로 그것이 인스턴스 변수라는 것을 의미합니까? ivars는 항상 lv이 아닌 접근 자 (self.lv 또는 [self lv])를 사용해야합니다. 직접 할당하지 마십시오. 당신은 거의 틀릴 것입니다 (당신이 여기에있을 가능성이 있기 때문에).

0

정확하게 똑같은 문제를 검색하는 동안이 문제가 발생 했으므로 지금까지 문제를 이미 해결 했으면서 다른 누군가가 문제를 해결할 수 있도록 솔루션을 게시하겠다고 생각했습니다.

이 오류는 인터페이스 작성기의 동일한 UIButton에 IBActions를 두 개 할당 할 때 발생하는 것으로 보입니다. 그것은보기 컨트롤러를 스택에 밀어 넣기 위해 사용 된 버튼이 두 개의 IBActions에 할당되고 각 컨트롤러가 navigationController의 스택에 다른 컨트롤러를 밀어 넣는 것으로 나타났습니다.하지만 그 중 하나만 보게 될 것입니다. 하나라고 부름). 그래서 어쨌든 맨 위의보기에서 뒤로 버튼을 눌러도 실제로 해제되지 않습니다 (또는 보이지 않는 두 번째 컨트롤러를 닫을 수도 있음). 두 번 누르면 다시 돌아와야합니다.

어쨌든 버튼을 확인하고 하나의 IBAction에만 지정되어 있는지 확인하십시오. 그것을 위해 그것을 고정.

관련 문제