작업 로그인 및 기본보기 컨트롤러로 설정된 스토리 보드가 있으며, 후자는 로그인이 성공할 때 사용자가 탐색하는보기 컨트롤러입니다. 내 목표는 인증 (키 체인에 저장 됨)이 성공하면 즉시 메인 뷰 컨트롤러를 표시하고 인증이 실패하면 로그인 뷰 컨트롤러를 표시하는 것입니다. 기본적으로 AppDelegate에서이 작업을 수행하고 싶습니다.
// url request & response work fine, assume success is a BOOL here
// that indicates whether login was successful or not
if (success) {
// 'push' main view controller
} else {
// 'push' login view controller
}
나는 performSegueWithIdentifier 메소드에 대해 알고있다. 그러나이 메소드는 UIViewController의 인스턴스 메소드이므로 AppDelegate 내에서 호출 할 수 없다. 기존 스토리 보드를 사용하여이 작업을 수행하려면 어떻게합니까?
편집하다:
Storyboard의 초기보기 컨트롤러는 이제 아무것도 연결되지 않은 탐색 컨트롤러입니다. MainIdentifier가 UITabBarController이기 때문에 setRootViewController : 구분을 사용했습니다. 그러면 내 라인은 다음과 같습니다.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
BOOL isLoggedIn = ...; // got from server response
NSString *segueId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:segueId];
if (isLoggedIn) {
[self.window setRootViewController:initViewController];
} else {
[(UINavigationController *)self.window.rootViewController pushViewController:initViewController animated:NO];
}
return YES;
}
제안 / 개선을 환영합니다!
답변
스토리 보드가 “기본 스토리 보드”( UIMainStoryboardFile
Info.plist의 키)로 설정되어 있다고 가정합니다 . 이 경우 UIKit은 스토리 보드를로드하고 application:didFinishLaunchingWithOptions:
AppDelegate로 보내기 전에 초기보기 컨트롤러를 창의 루트보기 컨트롤러 로 설정합니다.
또한 스토리 보드의 초기보기 컨트롤러가 기본 또는 로그인보기 컨트롤러를 푸시하려는 탐색 컨트롤러라고 가정합니다.
창에 루트 뷰 컨트롤러를 요청하고 performSegueWithIdentifier:sender:
메시지를 보낼 수 있습니다.
NSString *segueId = success ? @"pushMain" : @"pushLogin";
[self.window.rootViewController performSegueWithIdentifier:segueId sender:self];
답변
여기에서 제안 된 몇 가지 솔루션에 놀랐습니다.
스토리 보드에 더미 탐색 컨트롤러가 필요하지 않고 viewDidAppear에서 뷰를 숨기고 segue를 실행하거나 다른 해킹을 할 필요가 없습니다.
plist 파일에 스토리 보드를 구성하지 않은 경우 창과 루트 뷰 컨트롤러를 직접 만들어야합니다 .
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
BOOL isLoggedIn = ...; // from your server response
NSString *storyboardId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:storyboardId];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initViewController;
[self.window makeKeyAndVisible];
return YES;
}
스토리 보드 가 앱의 plist에 구성되어있는 경우 application : didFinishLaunching :이 호출 될 때 창과 루트 뷰 컨트롤러가 이미 설정되어 있고 makeKeyAndVisible이 창에서 호출됩니다.
이 경우 더 간단합니다.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
BOOL isLoggedIn = ...; // from your server response
NSString *storyboardId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier";
self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:storyboardId];
return YES;
}
답변
스토리 보드의 진입 점이 다음이 아닌 경우 UINavigationController
:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Your View Controller Identifiers defined in Interface Builder
NSString *firstViewControllerIdentifier = @"LoginViewController";
NSString *secondViewControllerIdentifier = @"MainMenuViewController";
//check if the key exists and its value
BOOL appHasLaunchedOnce = [[NSUserDefaults standardUserDefaults] boolForKey:@"appHasLaunchedOnce"];
//if the key doesn't exist or its value is NO
if (!appHasLaunchedOnce) {
//set its value to YES
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"appHasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
//check which view controller identifier should be used
NSString *viewControllerIdentifier = appHasLaunchedOnce ? secondViewControllerIdentifier : firstViewControllerIdentifier;
//IF THE STORYBOARD EXISTS IN YOUR INFO.PLIST FILE AND YOU USE A SINGLE STORYBOARD
UIStoryboard *storyboard = self.window.rootViewController.storyboard;
//IF THE STORYBOARD DOESN'T EXIST IN YOUR INFO.PLIST FILE OR IF YOU USE MULTIPLE STORYBOARDS
//UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"YOUR_STORYBOARD_FILE_NAME" bundle:nil];
//instantiate the view controller
UIViewController *presentedViewController = [storyboard instantiateViewControllerWithIdentifier:viewControllerIdentifier];
//IF YOU DON'T USE A NAVIGATION CONTROLLER:
[self.window setRootViewController:presentedViewController];
return YES;
}
스토리 보드의 진입 점이 UINavigationController
교체 인 경우 :
//IF YOU DON'T USE A NAVIGATION CONTROLLER:
[self.window setRootViewController:presentedViewController];
와:
//IF YOU USE A NAVIGATION CONTROLLER AS THE ENTRY POINT IN YOUR STORYBOARD:
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
[navController pushViewController:presentedViewController animated:NO];
답변
AppDelegate의 application:didFinishLaunchingWithOptions
메서드에서 return YES
줄 앞에 다음을 추가합니다.
UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController;
YourStartingViewController *yourStartingViewController = [[navigationController viewControllers] objectAtIndex:0];
[yourStartingViewController performSegueWithIdentifier:@"YourSegueIdentifier" sender:self];
교체 YourStartingViewController
실제 첫 번째 뷰 컨트롤러 클래스 (당신이 반드시 표시하지 않는 한)의 이름과 YourSegueIdentifier
SEGUE의 실제 이름 사이의 컨트롤러와 실제로합니다 (SEGUE 후 하나에 시작하려는 일을 시작 ).
if
항상 발생하는 것을 원하지 않는 경우 해당 코드를 조건부로 래핑하십시오 .
답변
이미 스토리 보드를 사용하고 있음을 감안할 때, 당신은 MyViewController, 사용자 정의 컨트롤러 (끓는 아래로 사용자에게 제공하기 위해 이것을 사용할 수 있습니다 followben의 대답은 조금).
에서 AppDelegate.m :
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MyCustomViewController *controller = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"MyCustomViewController"];
// now configure the controller with a model, etc.
self.window.rootViewController = controller;
return YES;
}
instantiateViewControllerWithIdentifier에 전달 된 문자열은 인터페이스 빌더에서 설정할 수있는 Storyboard ID를 참조합니다.
필요에 따라 이것을 논리로 감싸십시오.
하지만 UINavigationController로 시작하는 경우이 접근 방식은 탐색 컨트롤을 제공하지 않습니다.
인터페이스 빌더를 통해 설정 한 탐색 컨트롤러의 시작점에서 ‘앞으로 점프’하려면 다음 접근 방식을 사용하십시오.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UINavigationController *navigation = (UINavigationController *) self.window.rootViewController;
[navigation.visibleViewController performSegueWithIdentifier:@"my-named-segue" sender:nil];
return YES;
}
답변
먼저 나타나는 로그인 화면이 나오지 않는 이유는 사용자가 이미 로그인되어 있는지 확인하고 바로 다음 화면을 푸시하는 것입니다. 모두 ViewDidLoad에 있습니다.
답변
동일한 신속한 구현 :
UINavigationController
스토리 보드의 진입 점으로 사용 하는 경우
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var rootViewController = self.window!.rootViewController as! UINavigationController;
if(loginCondition == true){
let profileController = storyboard.instantiateViewControllerWithIdentifier("ProfileController") as? ProfileController
rootViewController.pushViewController(profileController!, animated: true)
}
else {
let loginController = storyboard.instantiateViewControllerWithIdentifier("LoginController") as? LoginController
rootViewController.pushViewController(loginController!, animated: true)
}