Добавить контроллер детского представления в текущий контроллер представления

Я пытаюсь добавить контроллер детского представления в код, в текущий контроллер представления из раскадровки, используя следующий код:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
LogInTutorialViewController *lvc = [[LogInTutorialViewController alloc] init];
lvc = (LogInTutorialViewController *)[storyboard instantiateViewControllerWithIdentifier:@"LogInTutorialViewControllerID"];
[self displayContentController:lvc];

- (void) displayContentController: (LogInTutorialViewController*) content;
{

    //add as childViewController
    [self addChildViewController:content];
    [content didMoveToParentViewController:self];
    [content.view setFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
    [self.view addSubview:content.view];

}

Похоже, что представление отображается на симуляторе, но в консоли я получаю много ошибок или ошибок:

 <Error>: CGContextSaveGState: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

А также одно и то же описание, но другая ошибка:

CGContextSetLineWidth, CGContextSetLineJoin, CGContextSetLineCap, CGContextSetMiterLimit, CGContextSetFlatness, CGContextAddPath, CGContextDrawPath, CGContextRestoreGState

все эти ошибки регистрируются дважды.

Кто-нибудь знает, что я делаю неправильно?

также я прочитал несколько сообщений, и в некоторых из них было предложено выделить и запустить контроллер представления перед передачей данных, я также пробовал это без везения.

Ответы

Ответ 1

didMoveToParentViewController должен быть последним.

Ответ 2

почему вы не пробовали этот код для добавления представления, я думаю, что это просто и легко.

self.loginView = [self.storyboard instantiateViewControllerWithIdentifier:@"LOGIN"];
[self addChildViewController:self.loginView];
[self.loginView.view setFrame:CGRectMake(0.0f, 0.0f, self.contentView.frame.size.width, self.contentView.frame.size.height)];
[self.contentView addSubview:self.loginView.view];
[self.loginView didMoveToParentViewController:self]; 

для получения дополнительной информации проверьте эту ссылку .

Ответ 3

  • Настройка контейнера в построителе интерфейсов.

Чтобы создать отношения между родительским и дочерним контейнерами во время разработки, добавьте объект просмотра контейнера в сцену раскадровки, как показано на рисунке ниже. Объект представления контейнера является объектом-заполнителем, который представляет содержимое контроллера дочернего представления. Используйте этот вид для определения размера и расположения корневого представления childs по отношению к другим представлениям в контейнере.

введите описание изображения здесь

При загрузке контроллера вида с одним или несколькими видами контейнера Interface Builder также загружает дочерние контроллеры представления, связанные с этими представлениями. Дети должны быть созданы одновременно с родителем, чтобы можно было создать соответствующие отношения родитель-потомок.

Если вы не используете Interface Builder для настройки отношений между родительским и дочерним контейнерами, вы должны создать эти отношения программно, добавив каждый ребенок в контроллер представления контейнера, как описано в разделе Добавление контроллера детского просмотра в ваше содержимое.

  • Добавление контроллера детского просмотра в ваш контент.

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

  • Вызовите метод addChildViewController: вашего контроллера контейнера. Этот метод сообщает UIKit, что теперь контроллер представления контейнера управляет представлением контроллера дочернего представления.
  • Добавьте представление корня childs в иерархию представлений ваших контейнеров. Всегда помните, чтобы установить размер и положение кадра childs как часть этого процесса.
  • Добавьте ограничения для управления размером и положением корневого представления childs.
  • Вызвать метод didMoveToParentViewController: для контроллера дочернего представления.

Вот код для этого.

- (void)displayContentController:(UIViewController *)content {
    [self addChildViewController:content];
    content.view.frame = [self frameForContentController];
    [self.view addSubview:self.currentClientView];
    [content didMoveToParentViewController:self];
}

Более подробное объяснение того же примера приведено в Руководство по программированию разработчиков Apple.

Ответ 4

Решение в Swift (Swift 4 на момент написания этой статьи):

//load the view controller and add as child
storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
loginVC = storyboard.instantiateViewController(withIdentifier: "LOGIN")
addChildViewController(loginVC)

//make sure that the child view controller view is the right size
loginVC.view.frame = contentView.bounds
contentView.addSubview(loginVC.view)

//you must call this at the end per Apple documentation
loginVC.didMove(toParentViewController: self)

Примечания:

  • Название раскадровки - "Главное".
  • Просмотр идентификатора контроллера в раскадровке называется "ВХОД".
  • Это использует раскадровку для создания нагрузки контроллера просмотра, но то же самое можно сделать программным путем. Просто убедитесь, что представление загружено в память, прежде чем вы попытаетесь получить доступ к кадру представления, или вы получите сбой (сделайте что-то вроде представления диспетчера представлений по умолчанию).