AppDelegate, rootViewController и presentViewController

Я занимаюсь учебным пособием по интеграции в Facebook, я хочу показать свой MainViewViewController, если у пользователя есть действительный токен для текущего состояния, иначе я хочу показать LoginViewController.

MainViewAppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) { // To-do, show logged in view } else { // No, display the login page. [self showLoginView]; } return YES; } - (void)showLoginView { UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; LoginViewController* loginViewController = [mainstoryboard instantiateViewControllerWithIdentifier:@"LoginViewController"]; [self.window.rootViewController presentViewController:loginViewController animated:YES completion:NULL]; } 

Ошибка консоли:

 Warning: Attempt to present  on  whose view is not in the window hierarchy! 

Я не хочу использовать NavigationController.

Я была такая же проблема. Основываясь на ответе на этот вопрос , я добавил [self.window makeKeyAndVisible] непосредственно перед presentViewController:animated:completion: и это исправило его для меня.

В вашем случае showLoginView становится

 - (void)showLoginView { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; LoginViewController *loginViewController = [storyboard instantiateViewControllerWithIdentifier:@"LoginViewController"]; [self.window makeKeyAndVisible]; [self.window.rootViewController presentViewController:loginViewController animated:YES completion:NULL]; } 

Иногда представление модального controllerа просмотра из window.rootViewController может привести к тому же предупреждению и не иметь никакого эффекта. Пример такой иерархии диспетчеров представлений:

  1. [ MYUITableViewController ] (представленный MYUIViewController)
  2. [ MYUIViewController ] (rootViewController UINavigationController ниже)
  3. [ UINavigationController ] (root)

Теперь вызов

 [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:[UIViewController new] animated:YES completion:nil]; 

(это будет проверено как на iOS6 & 7 Sim)

Решение: вместо использования rootViewController – используйте верхнюю часть, представленную им:

  UIViewController *topRootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; while (topRootViewController.presentedViewController) { topRootViewController = topRootViewController.presentedViewController; } [topRootViewController presentViewController:yourController animated:YES completion:nil]; 
  • Иногда keyWindow может быть заменен окном с nil rootViewController (показывая UIAlertViews, UIActionSheets на iPhone и т. Д.), В этом случае вы должны использовать свойство windows UIView.

Ответ Степана Генералова был правильным для меня в Swift 3 !!!
Конечно, с новым синтаксисом и т. Д., Поэтому я скопирую его здесь:

 let sb = UIStoryboard(name: "Main", bundle: nil) let vc = sb.instantiateViewController(withIdentifier: "MainApp") as! ViewController var topRootViewController: UIViewController = (UIApplication.shared.keyWindow?.rootViewController)! while((topRootViewController.presentedViewController) != nil){ topRootViewController = topRootViewController.presentedViewController! } topRootViewController.present(vc, animated: true, completion: nil) 

В этом случае «MainApp» является моим главным идентификатором controllerа.

Я знаю, что есть другие способы, но если вам нужно иметь разные схемы URL для открытия разных частей вашего приложения, вы должны обрабатывать его в AppDelegate, так что это прекрасно, потому что в

 func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {} 

метод, вы можете просто проверить, какой url является строкой, а затем решить, выполняете ли вы вышеуказанный письменный код или, возможно, похожий код с другим идентификатором для другого controllerа представления ( withIdentifier )

В Swift 3: –

 let storyboard = UIStoryboard(name: "Login", bundle: nil) let viewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController") window?.makeKeyAndVisible() window?.rootViewController?.present(viewController, animated: true, completion: nil) 

В случае, если вы не используете раскадровку. Сначала вам нужно создать YourViewController. Файл Go -> New -> File … (или shortCut – команда + N) введите описание изображения здесь

После этого выберите Cocoa Touch Class. Нажмите «Далее» или «Ввод». введите описание изображения здесь

Введите имя типа для вашего контроля над просмотром и нажмите «Далее». введите описание изображения здесь

 #import "AppDelegate.h" #import "YourViewController.h" @interface AppDelegate () @end @implementaion AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Init window self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; [self.window makeKeyAndVisible]; // Init YourViewController YourViewController *viewController = [[YourViewController alloc] init]; // Init YourNavigationController UINavigationController *navigationContoller = [[UINavigationController alloc] initWithRootViewController: viewController]; // Set rootViewController self.window.rootViewController = navigationContoller; return YES; } @end 

Пример Swift 3/4

 import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { //1-st step window = UIWindow(frame: UIScreen.main.bounds) window?.makeKeyAndVisible() //2-nd - create a window root controller, and create a layout let layout = UICollectionViewFlowLayout() window?.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout)) return true 

}

  • Что делает @synthesize window = _window?
  • SplitView как приложение Facebook на iPhone
  • Содержимое HTML соответствует UIWebview без масштабирования
  • Поиск расстояния от значения RSSI устройства Bluetooth с низким энергопотреблением
  • Как включить / выключить флэш-память iPhone?
  • Могу ли я получить доступ к брелкам на iPhone?
  • Множественное перечисление значений в Obj-C
  • Использование MPMediaItems с AVAudioPlayer
  • Изменить цвет курсора в UITextField
  • iPhone: конвертировать строку даты в относительную отметку времени
  • как отобразить тестовый баннер IAd в симуляторе
  • Давайте будем гением компьютера.