Как правильно удалить SFSafariViewController в качестве контроллера дочернего представления?

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

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

И я пытаюсь удалить контроллер Safari View со следующим кодом:

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

Теперь я могу предварительно загрузить URL-адрес и без проблем показать Safari View. Однако после того, как я повторю процесс (предварительная загрузка/показ/удаление) несколько раз (вероятно, 30+ раз), приложение вылетит из-за какой-то проблемы с памятью, потому что журнал показывает Memory level is not normal or this app was killed by jetsam при сбое приложения.

Перед сбоем я видел несколько логов с предупреждениями о возможных утечках:

<Warning>: notify name "UIKeyboardSpringBoardKeyboardShow" has been registered 20 times - this may be a leak

<Warning>: notify name "com.apple.SafariViewService-com.apple.uikit.viewService.connectionRequest" has been registered 20 times - this may be a leak

Правильно ли я делаю это при удалении контроллера Safari View? Я что-то упускаю? Или любое предложение обойти эту проблему?


person Joe Huang    schedule 24.02.2016    source источник


Ответы (2)


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

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

Сначала вы должны добавить дочернее представление, а затем вызвать didMoveToParentViewController. Попробуйте это и посмотрите, работает ли это.

Листинг 5-1. Добавление дочернего контроллера представления в контейнер

  • (void) displayContentController: (UIViewController*) content { [self addChildViewController: content]; content.view.frame = [self frameForContentController]; [self.view addSubview:self.currentClientView]; [содержимое didMoveToParentViewController:self]; }

Обратите внимание, что в предыдущем примере вы вызываете только метод didMoveToParentViewController: дочернего элемента. Это потому, что метод addChildViewController: вызывает для вас метод willMoveToParentViewController: дочернего элемента. Причина, по которой вы должны вызывать метод didMoveToParentViewController: самостоятельно, заключается в том, что этот метод нельзя вызвать до тех пор, пока вы не встроите дочернее представление в иерархию представлений вашего контейнера.

person Pradeep K    schedule 29.02.2016
comment
попробовал предложенный порядок, но все та же проблема остается. - person Joe Huang; 01.03.2016
comment
Сможете ли вы использовать WKWebkitView и добавить его в качестве подпредставления к вашему основному VC вместо использования SVC? - person Pradeep K; 01.03.2016
comment
Можете ли вы прислать мне весь код для тестирования или примерный прототип, демонстрирующий эту проблему? - person Pradeep K; 03.03.2016

вы, вероятно, пропускаете svc. обнулить его после удаления.

svc.willMoveToParentViewController(nil)
svc.view.removeFromSuperview()
svc.removeFromParentViewController()
svc = nil

если это не решит, попробуйте включить зомби или использовать инструмент утечки

person Casey    schedule 03.03.2016