UINavigationController 푸시 전환 중 낮은 프레임 속도 (Low frame rate during UINavigationController push transition)


문제 설명

UINavigationController 푸시 전환 중 낮은 프레임 속도 (Low frame rate during UINavigationController push transition)

UINavigationController가 있고 루트 뷰 컨트롤러에서 다음 뷰 컨트롤러로 푸시합니다. 이 두 번째 보기 컨트롤러는 초기화 및 하위 보기가 많다는 점에서 상당히 "무거워" 있습니다.

제 문제는 전환 애니메이션이 끔찍하게 수행된다는 것입니다. 기본적으로 애니메이션은 프레임 속도가 매우 낮습니다("푸시" 애니메이션에서 총 3‑4개의 프레임을 얻음).

두 가지 다른 기술을 포함하여 다양한 기술을 시도했습니다. 전환을 수동으로 애니메이션하는 방법. 모든 경우에 애니메이션의 처음 0.4‑0.7초는 프레임 속도가 좋지 않습니다. 예를 들어 전환 시간을 5초로 설정하면 전반 1/2초 정도는 성능이 저하되지만 나머지 애니메이션은 부드럽고 매끄럽습니다.< /p>

이것은 전환 초기에 "무언가"가 발생하고 있다고 믿게 만듭니다. 그로 인해 기기가 매우 낮은 프레임 속도로 움직이게 됩니다.

많은 것을 주입한 후 내 코드에 NSLog 문을 추가하면 두 가지 일이 발생하는 것을 보았습니다. 첫째, 분명히 두 번째 보기는 푸시 중에 지연 로드됩니다. 푸시를 실행하기 전에 뷰 속성의 getter에 액세스하여 이 문제를 해결했습니다. 푸시 애니메이션이 시작되기 전에 모든 초기화가 발생한다는 것을 확인할 수 있습니다.

둘째, 내 앱은 대부분 전환 중에 메모리 부족 경고를 받습니다. 그러나 메모리 경고가 표시되지 않는 경우에도 애니메이션이 여전히 제대로 작동하지 않아 이 중 어느 것도 원인이 아니라고 믿게 됩니다.< /p>

내 질문: 다른 사람이 UINavigationController 푸시 전환 애니메이션에서 낮은 프레임 속도를 경험했지만 애니메이션의 처음 0.4‑0.7초 동안만 경험한 적이 있습니까? 그 원인이 되는 배후에서 다른 일이 진행되고 있고 무엇이든 할 수 있습니까?

참고로, 다음 보기를 로드하고 푸시하는 현재 코드는 다음과 같습니다. 뷰를 강제로 로드하고 전환하기 전에 초기화하기 위해 의도적으로 뷰 게터에 액세스하고 있습니다(대부분 문제를 배제하기 위해). 이 코드는 웹 서비스 콜백에 대한 응답으로 performSelectorOnMainThread:::를 사용하여 메인 스레드에서 실행됩니다.

code>UINavigationController 푸시 전환 애니메이션, 하지만 애니메이션의 처음 0.4‑0.7초 동안만? 그 원인이 되는 배후에서 다른 일이 진행되고 있고 무엇이든 할 수 있습니까?

참고로, 다음 보기를 로드하고 푸시하는 현재 코드는 다음과 같습니다. 뷰를 강제로 로드하고 전환하기 전에 초기화하기 위해 의도적으로 뷰 게터에 액세스하고 있습니다(대부분 문제를 배제하기 위해). 이 코드는 웹 서비스 콜백에 대한 응답으로 performSelectorOnMainThread:::를 사용하여 메인 스레드에서 실행됩니다.

code>UINavigationController 푸시 전환 애니메이션, 하지만 애니메이션의 처음 0.4‑0.7초 동안만? 그 원인이 되는 배후에서 다른 일이 진행되고 있고 무엇이든 할 수 있습니까?

참고로, 다음 보기를 로드하고 푸시하는 현재 코드는 다음과 같습니다. 뷰를 강제로 로드하고 전환하기 전에 초기화하기 위해 의도적으로 뷰 게터에 액세스하고 있습니다(대부분 문제를 배제하기 위해). 이 코드는 웹 서비스 콜백에 대한 응답으로 performSelectorOnMainThread:::를 사용하여 메인 스레드에서 실행됩니다.

/p>

참고로 다음 보기를 로드하고 푸시하는 현재 코드가 있습니다. 뷰를 강제로 로드하고 전환하기 전에 초기화하기 위해 의도적으로 뷰 게터에 액세스하고 있습니다(대부분 문제를 배제하기 위해). 이 코드는 웹 서비스 콜백에 대한 응답으로 performSelectorOnMainThread:::를 사용하여 메인 스레드에서 실행됩니다.

/p>

참고로 다음 보기를 로드하고 푸시하는 현재 코드가 있습니다. 뷰를 강제로 로드하고 전환하기 전에 초기화하기 위해 의도적으로 뷰 게터에 액세스하고 있습니다(대부분 문제를 배제하기 위해). 이 코드는 웹 서비스 콜백에 대한 응답으로 performSelectorOnMainThread:::를 사용하여 메인 스레드에서 실행됩니다.

PlayingFieldViewController *v = [[PlayingFieldViewController alloc] initWithNibName:@"PlayingFieldView" bundle:[NSBundle mainBundle]];
UIView *lazy = v.view;
[appDelegate.navigationController pushViewController:v animated:YES];
[v release];

또한 몇 가지 다른 애니메이션 기법을 시도했지만 모두 동일한 결과를 얻었습니다.

CATransition *transition = [CATransition animation];
transition.duration = 1.0;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[appDelegate.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[appDelegate.navigationController pushViewController:v animated:NO];

및:

[UIView 
  transitionWithView:appDelegate.navigationController.view
  duration:1.0
  options:UIViewAnimationOptionTransitionCurlUp
  animations:^{
   [appDelegate.navigationController pushViewController:v animated:NO];
  }
  completion:NULL];

## 참조 솔루션 #### 방법 1:

After further testing, I was able to diagnose the problem. The second view involved includes many UIImageViews. Removing those views or hiding them fixes the problem.

What threw me off was the fact that only the first portion of the animation suffered from frame rate issues, while the remainder of the animation was perfectly smooth (in the case of longer animations). This shows me that the device is quite capable of animating the transition smoothly, even with all the subviews present.

I'm still not an expert on iOS compositing, but I'm guessing the various layers are being laid out and cached, leading to the slowdown. The workaround is to push to the view with most of the subviews hidden, then show them using another animation once the view is visible.

방법 2:

I have not stumbled upon this with the navigation controller but I got much the same result when updating a table view from another thread, the UI was really slow to update at first but after a short delay everything was showing again. As Justin points out in a comment, you should do UI work on the main thread. A simple way to accomplish this is wrap your call to the UI in a GCD block:

dispatch_sync(dispatch_get_main_queue(), ^{
// Do UI stuff here
});

or use

performSelectorOnMainThread:withObject:waitUntilDone:

(by Jeremy FullerJeremy FullerRobert Höglund)

참조 문서

  1. Low frame rate during UINavigationController push transition (CC BY‑SA 3.0/4.0)

#uinavigationcontroller #caanimation #iphone #iOS #catransition






관련 질문

세로에서 가로로 회전할 때 UIBarButtonItem 크기를 변경하는 방법은 무엇입니까? (how to change the UIBarButtonItem size when rotate from the portrait to landscape?)

performSegueWithIdentifier는 식별자 오류가 있는 segue를 생성하지 않습니다. (performSegueWithIdentifier produce no segue with identifier error)

UIAlertController는 leftBarButtonItem을 아래로 이동합니다. (UIAlertController moves leftBarButtonItem down)

현재 모달 보기는 탐색 스택에서 탐색 모음을 숨깁니다. (present modal view hides the navigation bar in navigation stack)

테이블 뷰 셀을 선택할 때 뷰 컨트롤러를 푸시할 수 없습니다. (Can't push my view controller when I select a table view cell)

프로그래밍 방식으로 탐색 컨트롤러의 초기 viewController 설정(레이어 SDK) (Set initial viewController in Navigation controller programmatically (Layer SDK))

UIViewController 유형의 표현식으로 UINavigationController를 초기화하는 호환되지 않는 포인터 유형 (Incompatible pointer types initializing UINavigationController with an expression of type UIViewController)

탐색 컨트롤러 도구 모음 크기 및 위치 - iOS Swift (Navigation Controller Toolbar Size & Location - iOS Swift)

Segue는 뒤로 막대 버튼에 데이터를 저장합니다. (Segue saves data on back bar button)

UINavigationController 푸시 전환 중 낮은 프레임 속도 (Low frame rate during UINavigationController push transition)

뷰 컨트롤러에서 탐색 모음의 모양 재설정 (Reset the appearance of navigation bar in a view controller)

탐색 모음 제목 보기 내에서 분할된 제어 스위치를 처리하려고 합니다. (Trying to handle segmented control switch inside of navigation bar title view)







코멘트