Re: iOS app launching speed
Re: iOS app launching speed
- Subject: Re: iOS app launching speed
- From: Conrad Shultz <email@hidden>
- Date: Tue, 15 May 2012 10:16:21 -0700
Responses below.
(Sent from my iPad.)
--
Conrad Shultz
On May 15, 2012, at 9:48, Alex Zavatone <email@hidden> wrote:
> Very enlightening Fritz. Thanks.
>
> One approach I took on purpose was to use a synchronous load of a JSON data set on startup.
>
Given your statement below I interpret this to mean that you are doing a synchronous download, not just synchronous deserialization. Never, ever do synchronous network I/O on the main thread - there is no guarantee that it will EVER complete. This applies throughout, not just at launch.
> I didn't want to display the main screen (TVC), until the main data had loaded (a 4 KB data set) and serialized.
>
Why? This directly contravenes the Human Interface Guidelines for the reasons Fritz indicated. You should display a non-localized (i.e. text-free) image of a blank TVC if that's the first screen.
> I'm wondering if with a larger data set, the approach should be to have the first scene use the same graphic as the launch screen, fire off an async http load (through GDC or which preferred method?), display a little spinner if the delay takes longer then 1.25 seconds, then segue to the TVC with data when it loads serializes and plops itself into my data singleton.
>
Well, first, as discussed, don't use a launch/splash screen.
What occurs to me is that you really only need wait until you have a screen of data. I'm not sure whether your data model can be easily broken into chunks, but the best approach would probably be to initially fetch only the data for the first, say, 10 rows. Once processed you would display them and start loading the remaining data in the background. That way, if the user doesn't scroll down too quickly they will have the illusion of the whole data set having loaded immediately.
If they do scroll fast enough to hit unavailable rows you just display a placeholder until the real data can be swapped into place.
> Does that sound like a sane approach, overengineering or completely off base?
Responsiveness is one of the most important usability traits, particularly on a mobile device. I'd say you're nowhere near the point of overengineering so long as your goal is responsiveness.
>
> Thanks again.
> - Alex Zavatone.
>
> On May 15, 2012, at 09:20 AM, Fritz Anderson <email@hidden> wrote:
>
> On 15 May 2012, at 10:05 AM, Alex Zavatone wrote:
>
>> Was just wondering if there are any techniques to speed up the launching of iOS apps.
>> Back in the Director day, I would create a shell executable that would launch rather quickly and present a splash screen, then an animation that indicated to the user that the test of the application was loading. After that, the shell read a config file, loaded the rest of the app and started up.
>> This approach got feedback to the user as quick as possible and provided the impression of a quick launching responsive app, right from the get go.
>> in the case that our apps start launching sluggishly (I've seen this during development sometimes) are there any approaches to take along this vein?
>
> Only some obvious things. You know them already, so maybe all you'll learn from me is that iOS doesn't have a "run more fast" toggle…
>
> 1. It's not a splash screen.
>
> Using the recommended default PNGs — screenshots without localizable content — gives the impression that the app's functionality is coming online. "Splash screens" give users the impression that you are delaying their access to the application so you can show them advertising. Small things can infuriate people.
>
> 2. Make the application faster.
>
> The app doesn't have to complete its initialization quickly — it only has to show that it's running.
>
> a) Profile the startup
>
> Use the Time Profiler instrument to find performance hotspots. Do this _on the phone_; the simulator is too fast and has too much memory to provide an honest profile. (Much of the startup delay in the simulator is due to debugger gymnastics.) If you load data during your startup, use an absurdly large dataset (embedding it in the app for testing purposes, if that's convenient). That will catch scaling issues.
>
> b) Do all the initialization you can on a background thread.
>
> Something I learned from an app I did for teaching purposes. It used Core Data internally, but at startup it loaded the CD store from a large raw-data file. The particular example probably not useful to you, but it illustrates the larger point.
>
> My profiling showed me that some Core Data operations were irreducible. I put initialization in a background thread, on a thread-specific MOC. My main thread observed the update notifications from the background thread, and updated its own MOC accordingly. Objects became available to the user as soon as they arrived in the main database — with an NSFetchedResultsController, it looked pretty cool. Even if you have to block access until the whole dataset is loaded, the constantly-updating tables demonstrate that the app is doing something.
> Obviously, storing the data in a Core Data file in the first place would have saved this trouble, but the general point is that if you have something time-consuming to do, put it into the background and call back into the main thread to update the UI as it progresses.
> As a bonus, keeping the main thread free prevents the watchdog timer from killing your app after 20 seconds. (The watchdog won't kill you while debugging or profiling, because the development tools allow you unlimited time to debug the whole process.)
>
> c) Proceed regardless
>
> If you have a startup subprocess that is inherently time-consuming (Core Location, and ANY networking), use the asynchronous API, and make your UI show the resulting degradation in functionality gracefully (dimmed controls, overlaid progress/activity indicators). NEVER use the synchronous networking API, nor the Foundation -…WithContentsOfURL: methods (for schemes other than file:). Timeouts will be on the order of 30 seconds, and to repeat, the watchdog allows you only 20.
>
> d) Consider not using Core Data at all.
>
> Do you need complex indexes and searches, extensive object-relational links, or faulting large numbers of records to storage? If not, maybe a tree of NSArrays, NSDictionaries, NSSortDescriptors, and NSPredicates will work better for you.
> For smaller, less complex data sets, they're faster. How much faster, and for how many records, depends on exactly what you're doing, but I'd guess that the line could be at least N=2000.
>
> e) Do what you can just-in-time.
>
> If your architecture is master/detail, consider whether building detail data sets one at a time on demand would be less annoying than taking time out of startup to build N sets all at once.
>
>
> — F
>
> --
> Fritz Anderson -- Xcode 4 Unleashed: Coming 21 May 2012 -- <http://x4u.manoverboard.org/>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden