Предварительно визуализировать представления UITabBarController? - PullRequest
3 голосов
/ 14 января 2010

У меня есть приложение с UITabBarController, которое управляет некоторыми UINavigationControllers, которые, в свою очередь, управляют различными UIViewController.

На телефонах 3G, в первый раз, когда я вижу какой-либо конкретный вид с помощью кнопки TabBar, он запаздывает, но после этого он мгновенный. Это не заметно с телефонами 3GS. Мой вопрос заключается в том, как я могу заставить эти представления предварительно визуализировать? Я пытался запускать функции loadView, вызывая их в другом потоке при запуске, но это не делает ничего, что я не думаю.

Для ясности, вот сокращенный фрагмент моего кода, чтобы показать, что я делаю. У меня есть пять контроллеров представления, но я показываю только код для двух. PoiVC - это просто стандартный подкласс UITableViewController - у меня даже нет специальной функции init или loadView для него.

- (void)applicationDidFinishLaunching:(UIApplication *)application {

  self.mapVC = [[MapViewController alloc] init];
  NavControlBar * mapNavBar = [[[NavControlBar alloc] initWithViewController:mapVC 
                             withControlBar:[mapVC initBar]]autorelease];
  self.poiVC = [[POIViewController alloc] init];
  NavControlBar * poiNavBar = [[[NavControlBar alloc] initWithViewController:poiVC 
                             withControlBar:[poiVC initBar]]autorelease];

  NSArray *tabViewControllerArray = [NSArray arrayWithObjects:mapNavBar, poiNavBar, nil];
  self.tbc.viewControllers = tabViewControllerArray;
  self.tbc.delegate = self;

  [mapVC release];
  [poiVC release];
  [window addSubview:tbc.view];

}

Могу ли я заставить poiVC визуализировать, пока пользователь смотрит на первый экран, поэтому переход будет быстрым?

Ответы [ 2 ]

3 голосов
/ 14 января 2010
 [self.mapVC view];
 [self.poiVC view];

Вы можете просто запросить представление о контроллере вида и ничего не делать с ним. Это вернет представление и, следовательно, загрузит его для вас, если это необходимо. Недостатком является, конечно, то, что вы увеличите время запуска. Также обратите внимание, что ваше представление может быть выгружено при нехватке памяти, что снова вызывает запаздывание при переключении на эти вкладки, но (по крайней мере, пытается) поддерживать работоспособность вашего приложения (как правило, считается хорошим).

1 голос
/ 13 июня 2015

Я боролся с той же проблемой. Все ответы, которые я видел, говорят о попытке предварительно загрузить представление, совершая вызов viewController.view, но это не главное узкое место, и в лучшем случае экономит всего несколько сотен миллисекунд. Большая часть фактической работы по рендерингу происходит между viewWillAppear и viewDidAppear, поэтому вам нужно активировать рендер, если вы хотите избежать задержки во время первоначального перехода.

Чтобы сделать это, вам нужно добавить ваши контроллеры представления как дочерние контроллеры представления в вашем главном представлении. Я обнаружил, что лучшее место для этого - обратный вызов viewDidAppear на контроллере основного вида, поскольку это не замедлит загрузку основного вида. И даже если вы загружаете и добавляете дочерние представления в главном потоке, похоже, он не блокирует пользовательский интерфейс. (Я тестировал вид, на котором воспроизводится фоновое видео.)

Вот код Swift, который я написал для предварительной визуализации некоторых контроллеров представления:

enum ViewPreloadingState {
    case Pending, Preloading, Loaded
}
var viewPreloadingState = ViewPreloadingState.Pending

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    if viewPreloadingState == .Pending {
        viewPreloadingState = .Preloading

        addChildViewController(loginViewController)
        view.addSubview(loginViewController.view)
        loginViewController.didMoveToParentViewController(self)

        addChildViewController(signupViewController)
        view.addSubview(signupViewController.view)
        signupViewController.didMoveToParentViewController(self)

        // Place view controllers off screen
        let f = view.frame,
            offScreenFrame = CGRect(x: f.width, y: 0, width: f.width, height: f.height)
        loginViewController.view.frame  = offScreenFrame
        signupViewController.view.frame = offScreenFrame
    }
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if viewPreloadingState == .Preloading {
        viewPreloadingState = .Loaded

        loginViewController.willMoveToParentViewController(nil)
        loginViewController.view.removeFromSuperview()
        loginViewController.removeFromParentViewController()

        signupViewController.willMoveToParentViewController(nil)
        signupViewController.view.removeFromSuperview()
        signupViewController.removeFromParentViewController()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...