App Thinning for iOS, tvOS and watchOS

20 / Jan / 2016 by Ashish Jain 0 comments

App thinning is a concept for modern day interactive apps where there are a lot of resources. The App Store and OS install the app according to the device, with a minimal footprint. This helps in making the app which occupies less space, are easy to download and make use of all features. Faster downloads and minimum space occupancy gives a better app experience.

There are three ways to implement App Thinning.

  1. Slicing
  2. Bitcode
  3. On-Demand Resources.



Slicing is the process of creating different variations of app bundle for different target devices. A variant contains only the executable architecture and resources those are needed for the target device. The store will create and deliver different variants based on the devices your app supports. Image resources are sliced according to their resolution and device family. GPU resources are sliced according to device capabilities. For tvOS apps, assets in catalogs shared between iOS and tvOS targets are sliced and large app icons are removed. When the user installs an app, a variant for the user’s device is downloaded and installed.

Note: Sliced apps are supported on devices running 9.0 and later; otherwise, the store delivers universal apps to customers.


Bitcode is an intermediate representation of a compiled program. Apps you upload to iTunes Connect that contain bitcode will be compiled and linked on the store. Including bitcode will allow Apple to re-optimize your app binary in the future without the need to submit a new version of your app to the store.

Xcode hides symbols generated during build time by default, so they are not readable by Apple. Only if you choose to include symbols when uploading your app to iTunes Connect would the symbols be sent to Apple. You must include symbols to receive crash reports from Apple.

On-Demand Resources

On-demand resources are resources—such as images and sounds—that you can tag with keywords and request in groups, by tag. The store hosts the resources on Apple servers and manages the downloads for you. On-demand resources enable faster downloads and smaller app sizes, improving the first-time launch experience. For example, a game app may divide resources into game levels and request the next level of resources only when the app anticipates that the user will move to that level. Similarly, the app can request In-App Purchase resources only when the user buys the corresponding in-app purchase.

Implementing On-Demand Resource management in app
Initializing a Resource Request

init(tags:) and init(tag:bundle:) are used to Initialize a resource request for managing the on-demand resources marked with any of the set of specified tags. The managed resources are loaded into the main bundle or specific bundle respectively.

Basically, three methods are used to access the resources.

  • func beginAccessingResourcesWithCompletionHandler(_:)
  • func conditionallyBeginAccessingResourcesWithCompletionHandler(_:)
  • func endAccessingResources()

func beginAccessingResourcesWithCompletionHandler(_:)

This method requests access to the resources marked with the managed tags. If any of the resources are not on the device, they are requested from the App Store.

func conditionallyBeginAccessingResourcesWithCompletionHandler(_:)

This method first checks availability on the device then requests access to the resources marked with the managed tags. If any of the resources are not on the device, they are requested from the App Store.

func endAccessingResources()

This method informs the system that you have finished accessing the resources marked with the tags managed by the request.

This code snippet shows how to implement the method in swift.

let tags = NSSet(array: [“tag1″,”tag2″])

let resourceRequest = NSBundleResourceRequest(tags: tags as! Set<String>)

resourceRequest.conditionallyBeginAccessingResourcesWithCompletionHandler {(resourcesAvailable: Bool) -> Void in

   if resourcesAvailable {

       // Do something with the resources

   } else {

       resourceRequest.beginAccessingResourcesWithCompletionHandler {(err: NSError?) -> Void in

           if let error = err {

               print(“Error: \(error)”)

           } else {

               // Do something with the resources






Leave a comment -