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.
Related
I am guessing an iOS App's size has direct impact on its launch latency, since iOS needs to load the App into memory before launching it. If so, I wonder how much is the impact?
Let's say if I reduce my iOS app from 100M to 80M, how much launch latency improvement I can expect?
Does anyone has experience on this?
Consider that programming a faster App Launch experience is not bound to App Size at all. You could assume even the opposite because in some (i would even say in most) cases coding a faster launch process to start up can (and will) involve more code to make it a very short interaction interrupt experience and so your app size would increase without even delivering more valuable content.
In other words just because you deliver more dynamic or static content does not increase launch time unless you load and instanciate everything you need later on in your app life cycle in UIApplicationDelegate instead of allocating objects at the time of its use.
The same ideals apply to tear down processing (dealloc or saving app state user defaults) if needed. But this experience is usually not seen as a visible interruption of interaction with the device and so often forgotten to be part of the apps life cycle.
You can avoid this prolonged start up experience for users with clever use of LaunchScreen storyboards or similar techniques like partly buffered content for the first seconds. Some apps even take screenshots to be presented at the next start up to make the user feel the last app state is loaded already while building up the real interface.
A common mistake, which you may have seen also very often, is to make use of introduction videos or animations to bridge the time in waiting for the window/view to appear after app launch. So just making use of Launch Screens is never the best solution but a wise decision if the content that needs to be loaded first hand will take a noticeably longer time and can not be avoided.
LaunchScreens are just entertaining/informing about processing and keeping the user engaged while it can be beneficial what you and your app want to represent.
So abbreviated launch time is clearly a design pattern issue and is not bound to app size. Ok, apart from downloading band width if that is needed.
I have an iOS Xcode project that previously would load fast, but from time to time, now will hang for five seconds or more during loading. When the app is run on an iPhone, the launch screen displays instantly, but sometimes, not always, and unpredictably, the app just hangs for around 5 seconds or more until the actual interface is displayed. It occurs both on the simulator and device across different iOS versions 7, 8, 9.
Recently, a UIView's class that contains a drawRect function was changed slightly, it has an outlet connection to one of the ViewControllers, but no significant changes made overall. One ViewController has code in the ViewDidLoad, ViewWillAppear, ViewDidAppear functions. All these things I'm investigating if they are impacting the load time.
When I terminate the app, the next time I try running it, it loads super fast without issue. I have no idea what to make of this load behaviour.
Questions
1 - What methods can I use in Xcode to debug an app that loads slowly at irregular and unpredictable times?
2 - What obvious items should I be on the look out in the project that typically cause slow or prolonged load times?
3 - Does Xcode include tools to monitor the processes operating live while loading occurs?
4 - Is it possible to print output for load processes I can review?
Any experienced advice really appreciated. Thanks.
Not sure if you have looked instrumentation. It is the best way to determine this kind of issues with your app.
https://developer.apple.com/library/watchos/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/index.html
When I terminate the app, the next time I try running it, it loads super fast without issue. I have no idea what to make of this load behavior.
Do you mean exiting the app? Or actually killing it? Cause if it is the former, then the reason is the app was just launched from a suspended state.
I would suggest take a closer look at didFinishLaunchingWithOptions:, and check if you are doing something that takes more time than needed. Run your app with the time profiler instrument, it will tell you where is your bottleneck.
It seems like the fade animation between the launch screen and my first view is really slow.
I don't think it used to be like that. Is there a way to control the speed of that transitional animation?
I looked at some apps on my phone and the launch screen doesn't fade as slowly as mine. What things could I have done to affect that?
(No I don't have slow animations turned on, only the fade animation is slow)
In WWDC 2012 video iOS App Performance: Responsiveness they enumerate a whole list of issues that have impact on the app startup time, ranging from attaching to unnecessary frameworks, optional linking to frameworks that you really could make required, the use of static initializers, overly complicated initial scenes, too much information stored in preferences, etc.
That video covers a range of topics, like the above, which impact startup time. In the demonstration, they show how one might benchmark the startup time. Unfortunately, in my experience, there's a good chance that you might not be able to do anything to fix this issue (e.g. you need certain features and therefore need certain frameworks), but it's still an illuminating video and it might give you some ideas of things you can try to alleviate the start-up performance issues.
If your app splash screen show more time, so please check following things in your app.
1. AppDelegate.m
in didFinishLaunchingWithOptions method have you called any heavy method which takes more time for finish task if yes then change that method location, basically in appDelegate class don't write any heavy methods.
2. first view of your app.
check viewDidLoad() method, if you call many method or any heavy method from here then your launch image will show still your control not come out from viewDidLoad method, so if you want call any methods at view launch time then call them from viewWillAppear or viewDidAppear method (in viewDidAppear method don't call any UI related methods)
I never figured out what was going on here, but the next day when I started up xCode and the simulator it was back to the normal loading time.
We have a complex app that uses a UIWebView to display some information at a certain point. We have an OpenGL layer that stops drawing while the UIWebview is displayed, and we're using about 128 Meg of ram (according to monitors). The page is about 10 screens worth of table, and is static content. Javascript is used on setup, but that's it.
We've noticed that the page loads and is responsive, and then after scrolling the view up and down a few times, the CPU hits about 18% - not in our code. This happens on DidReceiveMemory warning (though the device is not short of memory), so it feels like a garbage collector or something. The 18% then remains until the view is freed off. Returning to the view again and the newly created UIWebview will be responsive again, with the same behaviour of slowing down after a bit of brisk scrolling.
We clear the NSURLCache on didReceiveMemoryWarning (and give the OS back lots of ram). Does anyone have other suggestions, as the responsiveness drops off a cliff on older devices?
It turns out if you present the Renderbuffer from the OpenGL layer every frame while a UIWebView is visible, this slow down kicks in. The other instance we used a UIWebview we had paused the renderer, so it didn't matter
Ensuring that
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[m_pContext presentRenderbuffer:GL_RENDERBUFFER];
Does not run (or pausing the display link) fixed the problem for us. Hope it is useful to someone, as it has been puzzling us for days.
I don't have any hardcore data supporting this, but generally, you'll notice that any app you play with or one you're working on, when the app first loads, doing something such as displaying a modal view controller is slow the first time, but every subsequent time, it's really fast. For my app, when I present a modal view controller the first time, it takes about 3 seconds, but if I do it over and over again after that, it takes less than a second every time. What is the reason for this?
There's a bunch of possible explanations here.
Something's been cached. The first time, it had to load something from "disk," the second time it was already in memory. This could be an entire framework, or NIBs or graphic resources in the OS itself.
Memory management. iOS didn't have enough memory to satisfy the request the first time. iOS spent some time clearing out memory, possibly quitting background applications. The second time, it's already available.
Probably many others.
Caching. Off the top of my head, images are often cached, and I wouldn't be surprised if the nib was cached as well.
No, I don't notice this in my app. The cause of what you are seeing could be a hundred different things, so we need a bit more data to make an informed answer.
Suggest you run Instruments, narrow down the time window to the initial 3-second pause, then see what the machine is doing during that time. Run it multiple times and look at CPU, IO, memory, anything that could be slowing it down.