iOS 창의 루트 뷰 컨트롤러 변경
iOS 창의 루트 뷰 컨트롤러는 일반적으로 처음에 한 번 탭 모음 컨트롤러 또는 탐색 컨트롤러로 초기화됩니까? 앱 내에서 루트 뷰 컨트롤러를 여러 번 변경해도됩니까?
사용자 작업에 따라 상위 뷰가 다른 시나리오가 있습니다. 스플래시 화면 이미지가있는 탑 뷰 컨트롤러가있는 내비게이션 컨트롤러를 갖고 필요에 따라 뷰 컨트롤러를 밀거나 터뜨릴 생각이었습니다. 또는 창의 상단보기 컨트롤러를 계속 변경할 수 있습니다. 더 나은 접근 방법은 무엇입니까?
"presented view controller"( presentViewController:animated:completion:
) 를 사용하는 것이 더 일반적 입니다. 루트 뷰 컨트롤러 앞에 효과적으로 나타나고 기본적으로 대체하여 원하는만큼 많은 것을 가질 수 있습니다. 원하지 않는 경우 애니메이션이있을 필요가 없거나있을 수 있습니다. 제시된 뷰 컨트롤러를 해제하여 원래의 루트 뷰 컨트롤러로 돌아갈 수 있지만, 그럴 필요는 없습니다. 제시된 뷰 컨트롤러는 원하는 경우 영원히있을 수 있습니다.
내 책에서 제시된 뷰 컨트롤러에 대한 섹션은 다음과 같습니다.
http://www.apeth.com/iOSBook/ch19.html#_presented_view_controller
이 다이어그램 (해당 장의 앞부분)에서 제시된 뷰 컨트롤러는 앱 인터페이스를 완전히 인수했습니다. 루트 뷰 컨트롤러 및 하위 뷰는 더 이상 인터페이스에 없습니다. 루트 뷰 컨트롤러는 여전히 존재하지만 이것은 가볍고 중요하지 않습니다.
iOS 8.0, Xcode 6.0.1, ARC 사용
대부분의 질문에 답변했습니다. 하지만 최근에 스스로 처리해야했던 문제를 해결할 수 있습니다.
앱 내에서 루트 뷰 컨트롤러를 여러 번 변경해도 괜찮습니까?
대답은 ' 예' 입니다. 최근에 앱의 일부인 초기 UIView 이후 UIView 계층 구조를 재설정하기 위해이 작업을 수행해야했습니다. 시동이 더 이상 필요하지 않았습니다. 즉, 앱 종료 후 언제든지 다른 UIViewController에서 "rootViewController"를 재설정 할 수 있습니다. "didFinishLoadingWithOptions".
이것을하기 위해...
1) 앱에 대한 참조를 선언하십시오. 델리게이트 ( "Test"라는 앱) ...
TestAppDelegate *testAppDelegate = (TestAppDelegate *)[UIApplication sharedApplication].delegate;
2) "rootViewController"를 만들려는 UIViewController를 선택하십시오. 스토리 보드에서 또는 프로그래밍 방식으로 정의 ...
-
a) 스토리 보드 (ID, 즉 storyboardID가 UIViewController에 대한 ID 검사기에 존재하는지 확인) :
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
NewRootViewController *newRootViewController = [mainStoryBoard instantiateViewControllerWithIdentifier:@"NewRootViewController"];
-
b) 프로그래밍 방식 (subview 등을 추가 할 수 있음)
UIViewController *newRootViewController = [[UIViewController alloc] init];
newRootViewController.view = [[UIView alloc] initWithFrame:CGRectMake(0, 50, 320, 430)];
newRootViewController.view.backgroundColor = [UIColor whiteColor];
3) 모두 합치면 ...
testAppDelegate.window.rootViewController = newRootViewController;
[testAppDelegate.window makeKeyAndVisible];
4) 애니메이션을 던질 수도 있습니다 ...
testAppDelegate.window.rootViewController = newRootViewController;
[testAppDelegate.window makeKeyAndVisible];
newRootViewController.view.alpha = 0.0;
[UIView animateWithDuration:2.0 animations:^{
newRootViewController.view.alpha = 1.0;
}];
이것이 누군가를 돕기를 바랍니다! 건배.
창의 루트 뷰 컨트롤러입니다.
루트 뷰 컨트롤러는 창의 콘텐츠 뷰를 제공합니다. 이 속성에 뷰 컨트롤러를 할당하면 (프로그래밍 방식으로 또는 인터페이스 빌더를 사용하여) 뷰 컨트롤러의 뷰가 창의 콘텐츠 뷰로 설치됩니다. 창에 기존보기 계층이있는 경우 새보기가 설치되기 전에 이전보기가 제거됩니다. 이 속성의 기본값은 nil입니다.
* 2015 년 9 월 2 일 업데이트
아래 설명이 지적했듯이 새 뷰 컨트롤러가 표시 될 때 이전 뷰 컨트롤러 제거를 처리해야합니다. 이를 처리 할 전환 뷰 컨트롤러를 선택할 수 있습니다. 이를 구현하는 방법에 대한 몇 가지 힌트는 다음과 같습니다.
[UIView transitionWithView:self.containerView
duration:0.50
options:options
animations:^{
//Transition of the two views
[self.viewController.view removeFromSuperview];
[self.containerView addSubview:aViewController.view];
}
completion:^(BOOL finished){
//At completion set the new view controller.
self.viewController = aViewController;
}];
serge-k의 답변에 대한 의견에서 이전 rootViewController 위에 제시된 모달 뷰 컨트롤러가있을 때 이상한 동작을 해결하는 작업 솔루션을 구축했습니다.
extension UIView {
func snapshot() -> UIImage {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.mainScreen().scale)
drawViewHierarchyInRect(bounds, afterScreenUpdates: true)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result
}
}
extension UIWindow {
func replaceRootViewControllerWith(_ replacementController: UIViewController, animated: Bool, completion: (() -> Void)?) {
let snapshotImageView = UIImageView(image: self.snapshot())
self.addSubview(snapshotImageView)
let dismissCompletion = { () -> Void in // dismiss all modal view controllers
self.rootViewController = replacementController
self.bringSubview(toFront: snapshotImageView)
if animated {
UIView.animate(withDuration: 0.4, animations: { () -> Void in
snapshotImageView.alpha = 0
}, completion: { (success) -> Void in
snapshotImageView.removeFromSuperview()
completion?()
})
}
else {
snapshotImageView.removeFromSuperview()
completion?()
}
}
if self.rootViewController!.presentedViewController != nil {
self.rootViewController!.dismiss(animated: false, completion: dismissCompletion)
}
else {
dismissCompletion()
}
}
}
To replace the rootViewController just use:
let newRootViewController = self.storyboard!.instantiateViewControllerWithIdentifier("BlackViewController")
UIApplication.sharedApplication().keyWindow!.replaceRootViewControllerWith(newRootViewController, animated: true, completion: nil)
Hope this helps :) tested on iOS 8.4; also tested for navigation controllers support (should support also tab bar controllers etc., but I did not test it)
Explanation
If there is a modal view controller presented over old rootViewController, the rootViewController is replaced, but the old view still remains hanging below the new rootViewController's view (and can be seen for example during Flip Horizontal or Cross Dissolve transition animations) and the old view controller hierarchy remains allocated (which may cause severe memory problems if replacement happens multiple times).
So the only solution is to dismiss all modal view controllers and then replace the rootViewController. A snapshot of the screen is placed over the window during dismissal and replacement to hide the ugly flashing process.
응용 프로그램 수명주기 동안 창의 rootViewController를 변경할 수 있습니다.
UIViewController *viewController = [UIViewController alloc] init];
[self.window setRootViewController:viewController];
rootViewController를 변경할 때 여전히 UIImageView를 창에 하위보기로 추가하여 스플래시 이미지 역할을 할 수 있습니다. 나는 이것이 의미가 있기를 바랍니다.
- (void) addSplash {
CGRect rect = [UIScreen mainScreen].bounds;
UIImageView *splashImage = [[UIImageView alloc] initWithFrame:rect];
splashImage.image = [UIImage imageNamed:@"splash.png"];
[self.window addSubview:splashImage];
}
- (void) removeSplash {
for (UIView *view in self.window.subviews) {
if ([view isKindOfClass:[UIImageView class]]) {
[view removeFromSuperview];
}
}
}
iOS8의 경우 아래 두 매개 변수를 YES로 설정해야합니다.
providesPresentationContextTransitionStyle
definesPresentationContext
다음은 iOS 6 이상용 탐색 컨트롤러 아래에 투명한 모델보기 컨트롤러를 표시하는 코드입니다.
ViewController *vcObj = [[ViewController alloc] initWithNibName:NSStringFromClass([ViewController class]) bundle:nil];
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:vcObj];
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
navCon.providesPresentationContextTransitionStyle = YES;
navCon.definesPresentationContext = YES;
navCon.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:navCon animated:NO completion:nil];
}
else {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[self presentViewController:navCon animated:NO completion:^{
[navCon dismissViewControllerAnimated:NO completion:^{
appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:navCon animated:NO completion:nil];
appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationFullScreen;
}];
}];
}
참고 URL : https://stackoverflow.com/questions/15774003/changing-root-view-controller-of-a-ios-window
'developer tip' 카테고리의 다른 글
R의 모형 행렬에있는 요인의 모든 수준 (0) | 2020.11.30 |
---|---|
node.js에서 마지막으로 수정 된 파일 날짜 (0) | 2020.11.30 |
Python : 여러 값으로 사전 목록을 정렬하는 방법은 무엇입니까? (0) | 2020.11.30 |
HTML-속성 대 속성 (0) | 2020.11.30 |
카메라 롤 액세스 권한 요청 (0) | 2020.11.29 |