Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove SFSafariViewController as a child view controller correctly?

I am using the technique provided by this SO answer to preload some URL in SFSafariViewController like this:

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

And I try to remove the Safari View controller with following code:

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

Now I can preload the URL and show the Safari View without problem. However, after I repeat the process (preload/show/remove) several times (probably 30+ times) , the app will crash due to some memory issue because the log shows Memory level is not normal or this app was killed by jetsam when the app crashes.

Before crash, I saw some logs about possible-leak warnings:

<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

Am I doing it correctly when removing the Safari View controller? Am I missing something? Or any suggestion to work around this issue?

like image 317
Joe Huang Avatar asked Feb 24 '16 09:02

Joe Huang


People also ask

What is sfsafariviewcontroller in iOS?

SFSafariViewController is part of the SafariServices framework, and lets your users browse a web page, or a website right inside your app. With it, people can enjoy the same web browsing experience they get in Safari — including features like Password Autofill, Reader, and Secure Browsing — without ever having to leave your app.

How do I add a view controller as a child?

When added as a child, a view controller is automatically resized according to the size of the app’s window — but just like a subview of a stand-alone UIView, a child view controller’s view can be resized and repositioned using either frames or Auto Layout constraints. To add a view controller as a child, we use the following three API calls:

Can a view controller be used as a navigation controller?

When a piece of UI is implemented as a view controller, it can be used in many different contexts — including both being pushed onto a navigation controller, as well as being embedded as a child.


1 Answers

If your adding child view controller code is as you have specified above then I think its order should be a bit different as per the documentation.

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

You should first add the child view and then call didMoveToParentViewController. Try this and see if it works.

Listing 5-1Adding a child view controller to a container

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

In the preceding example, notice that you call only the didMoveToParentViewController: method of the child. That is because the addChildViewController: method calls the child’s willMoveToParentViewController: method for you. The reason that you must call the didMoveToParentViewController: method yourself is that the method cannot be called until after you embed the child’s view into your container’s view hierarchy.

like image 147
Pradeep K Avatar answered Oct 11 '22 10:10

Pradeep K