We have WKWebView in iOS 8 and SFSafariViewController in iOS 9.
I know that WKWebView subclasses from UIView, and that SFSafariViewController subclasses from UIViewController.
They are essentially different.
My question is about memory management between these two components.
Quoted from developers at Facebook, Reducing FOOMs in the Facebook iOS app
WKWebView — that actually performs most of its work in a separate process, which means that most web-view-related memory usage would not be attributed to our process.
This helps a lot in preventing our app from being killed because our process consumes a large amount of memory.
Does SFSafariViewController handle web-view-related memory in a separate process like WKWebView?
Yes, Safari View Controller runs in a separate process from your application.
Here's a link to WWDC session.
Related
I have a toy iOS app that's just for me. It's a native wrapper of a web-based WebAssembly-heavy game.
It's one of those where you set a task, and then wait for it to complete. Great for desktop browsers where you can just leave an open window in the corner of the display and work elsewhere.
WKWebView, however, seems to go inactive and stops processing game content when the app is backgrounded. I'd like any way (evil hacks accepted) to keep this from happening, so that the game does not pause or go inactive.
I've tried a number of hacks, including:
attaching the web view to the key window (deprecated in iOS 13 beta)
using an audio session to keep the app alive in the background
pumping the web view with evaluateJavaScript calls on a timer while in the background
...to no avail. Any solutions welcome!
(p.s., I'm aware of a couple other questions like this one, but want to ask my own to manage the bounty and also I'm not sure if the game being WASM makes a difference, vs. the other questions specifically calling out JavaScript)
I am not getting proper understanding of what is the main adavantage of using SFSafariViewController, if we are using [[UIApplication sharedApplication] openUrl: strUrl];
What are the difference between both?
With SFSafariViewController, you can use nearly all of the benefits of viewing web content inside Safari without forcing users to leave your app.
The majority of apps just need to provide a generalized web viewing experience. This is the perfect scenario for the safari view controller.
Before SFSafariViewController, the browsing experience was inconsistent across different apps, which may confuse the user. Some interfaces may also lack the things users expect, such as a progress bar indicating how much of the page is loaded. You don't have access to all of Safari's features. This includes the reader view, the iCloud keychain for autofill capabilities, and more.
If you wanted to have those features before iOS 9, you were forced to have the user leave your app entirely by opening the content inside Safari. SFSafariViewController solves every one of these problems.
For more see here
In case of [UIApplication openURL:], Safari is launched and your app is no longer in foreground and, generally, is not guaranteed to be running. In contrast, SFSafariViewController is a part of your app and you retain some control over it as a UIViewController or with SFSafariViewControllerDelegate methods. Which one to use depends on what you want to achieve. There is also WKWebView which gives you more control over the content and navigation but lacks some features of Safari such as content blocking.
My company uses a UIWebView to display ads. The issue I'm having is that initializing a UIWebView appears to be expensive; profiling with Time Profiler shows [UIWebView alloc] initWithFrame:CGRectMake(0,0,500,500)] to take 31–40ms. This is enough to cause noticeable frame drops in games running at 60 FPS.
Is there a way to workaround this slow initialization time? My current ideas are to create a UIWebView when the app launches (but before gameplay has started), and reuse that (potentially creating a pool of them to reuse, like how UITableViewCell works) or to try and see if WKWebView has better performance.
Here are my findings:
WKWebView does not initialize any faster. Creating WKWebViews took a similar amount of time as creating UIWebViews (in the 1 test I did, it took 46ms to create two WKWebViews.
The very first web view created takes significantly longer to create than subsequent web views. The first one takes 31–42 ms; subsequent ones take ~11ms to create. The good news here is that creating the first web view when e.g. the app launches allows future webviews to be created more cheaply, avoiding a 40ms hit while the game is running.
Creating a pool of UIWebViews was a good solution for my use case. By creating the webviews at app launch and then reusing them, I avoid causing a frame drop while the game is running.
There is not much difference in the responsiveness between UIWebView and WKWebView because WKWebView has been introduced for a consistency matter between iOS and OSX. The underlying engine is Webkit in either way and it requires a lot of initialization.
The best solution I've found recent during years has been fading a WebView starting from a view with 0.1 alpha in which the url was loaded. Be careful to not start from 0.0 and do not have your webview detached from main view hierarchy because your url would not be loaded.
When didFinishLoading is called then you can fade it to 1.0 thus providing a better user experience.
Personally I don't like the UIWebView pool because I have experienced some memory troubles when maintaining it, especially on iOS 7 devices.
How to use the UIWebview with enabled cookies? I am using lot of web apps in my iOS app, each app has their own URL to load their app.
All web apps are displayed with their name and app icon in a UITableView (app list). Whenever user tap on app from the app list, we are loading that app in UIWebview.
If user again tap on the same app we are loading from cookies not loading from the start.
In this scenario how to use UIWebview?
Normally UIWebview took lot of memory, if we opened lot of apps memory increased huge.
Please suggest how to use UIWebview with effective manner.
The reason why I am doing everything below: I have a GPS tracking application which should run in background all day long. Memory usage doesn't go down when I put application in background. It seems like views are not removed from memory when app goes into the background... That is why the app is closed in few hours of normal usage of iPhone ... From IOS6 experience - memory usage should drop to cca 8KB.
Then I tried to debug/isolate the problem ...
I created simple ViewController with UIMapKitView just to make sure that view is consuming a lot of RAM (e.g.: 12-17MB). When app goes to background app uses same amount of RAM until "Terminated due to Memory Pressure" message. Still - sometimes memory lowers to 4KB and everything is OK. Problem is because it works kind of "random" and the app is plain simple.
Can I manually release RAM which is consumed by views? E.g.: set self.view = nil? Should I do it?
I also noticed that "- (void)didReceiveMemoryWarning" is not always called before app is killed. I would expect that when OS needs more memory it would first release views, than ask me to clear anything I can via this method ... Isn't this a little bit strange?
Apple redesigned the way a VC's (view controller's) views were loaded quite a while back - I want to say starting with iOS 5? iOS 6? It used to be that the system would unload your VC's views when a VC was not front-most and it needed the memory.
With the changes, a VC's views are NEVER unloaded while the VC is active. ViewDidLoad only gets called once in the lifetime of the VC, and viewDidUnload is no longer called at all.
I don't know what would happen if you set your (non-frontmost) VCs' content views to view manually. Would the system load your view hierarchy when that view became frontmost again? You'd have to try it, but it is risky since I don't think the OS is designed that way any more.
If your VCs views are holding significant amounts of memory, you might want to re-architect your app so only the front-most app is kept around, and the other VCs are released (after saving their state.)
Apple does not make this sort of app easy to write. To the contrary, they actively discourage it. The GPS is a huge power drain, so keeping it active constantly is going to drain the user's battery fast.
I remember hearing about a new location chip in the 5s that will record a "crumb trail" of location data for your app even when it's not running, at your request. You might look into that, although it would only work on the newest devices with the A7 chip and location chip.
In my case the problem was specific IOS7 version. Every app was crashing with this version of OS. When we updated OS version, everything started working back as it should.