AppExtension Programming Guide-App Extension Essentials AppExtension Programming Guide: Extension Basics 3
Creating an App Extension
V10.10 iOS8 / OS X
App Extension Programming Guide App Extensions Essentials
Creating an application extension
V10.10 iOS8 / OS X
When you are ready to develop an application extension, start by selecting an extension point that supports the task you want to perform. Then select the Xcode template that applies to the extension point of your choice, enhancing the default file with custom code and custom user interface if desired. Finally, after you debug and optimize your application extensions, you can package them into your application for users to use.
Start by selecting the right extension point
Each extension point is for a well-defined user scenario, and you need to know what the application offers users, so choose an extension point that supports that functionality. This is critical because each extension point defines a different API that gives you different functionality to develop, so if you choose the wrong extension point, you may not be able to achieve the desired functionality. Table 1-1 lists all the extension points supported in iOS and OS X.
After selecting an extension point suitable for application extension, you will have a new Target in your containing app. The easiest way to add an application extension Target is to use the templates provided by Xcode, which provide pre-configuration for extension points.
You can add a New Target to your Xcode project by selecting File > New > Target from the menu. In the left sidebar, select the Application Extension option for iOS or OS X, and then select the Application Extension template you want to create from the Xcode template displayed in the right pane, as shown below:
With the template selected and Target added to the project, you can try compiling and running the project before customizing the extension code. If you are creating an extension based on a template provided by Xcode, then when compiled successfully, an application extension pack with the.appex extension will be generated.
Note 64-bit Architectures: An application extension within an Architectures setting must include the ARM64 architecture or it will be rejected when uploading to the App Store. After creating an application extension, you can set the ARM64 architecture in Xcode’s “Standard Architectures” setting option.
If your application contains extensions that use embedded frameworks, your application must also include the ARM64 architecture, otherwise it will be rejected when uploading to the App Store.
For more information about 64-bit architecture development environments, see the 64-bit Transition Guide for Cocoa Touch or the 64-bit Transition Guide for Cocoa, depending on your target platform.
In most cases, you can test the default application extension by enabling it or granting permissions in System Preferences or Settings, which can then be accessed through other applications. For example, you can test the share extension in OS X by opening a page in Safari, clicking the Share button, and selecting the extension you want to test.
Check the default extension template
Typically, each extension template contains a property list file (that is, the info.plist file), a View Controller class, and a default UI defined by extension points. The default View Controller class (or Principal Class) has methods that extend the point corresponding to the functionality that we need to implement.
The info.plist file for the application extension Target lists the details of the application extension in addition to identifying extension points. This file contains at least the NSExtension dictionary and any other key value dictionary specified by the extension point. Such as NSExtensionPointIdentifier key value is the reverse DNS name extension points, such as com. Apple. Widgets – the extension. There are other keys and values in the NSExtension dictionary of the application extension:
NSExtensionAttributes: This is a dictionary that describes the specific attributes of extension points, like PHSupportedMediaTypes in the photo editing extension.
NSExtensionPrincipalClass: this is the main part of the extension templates to create the view controller class, such as SharingViewController. When the host App calls the extension, the extension point instantiates the class.
NSExtensionMainStoryboard (only applicable for iOS) : extend the default Storyboard file, usually called MainInterface.
In addition to being set in the property list, extension templates can also set some default functions. Each extension point can define the functionality supported by the extension point for a particular type of task. For example, a iOS Document Provider extension contains com. Apple. Security. The function of the application – groups.
All OS X extension template by default contain application sandbox and com. Apple. Security. The files. The user – selected. The read – only function. If you’re developing an extension that needs to work on the web, or access a user’s photo album, or access a user’s address book, then you need to define these additional capabilities.
Note: In general, if the user allows the containing app to access their private data, the extension in the containing app will also have this permission.
Respond to the Host App request
As you learned in the Understand How an Extension Works document, the Extension opens when the user selects an Extension in the Host App and has the host App make a request to the Extension. To be more specific, your extension will receive requests based on user actions, perform tasks for the user, and then complete or close the request. For example, a sharing extension receives a request from the Host app, and the extension opens the corresponding view to respond to the request. The user can then edit the content to be shared in the interface, the user can choose to send or not to send, and finally the extension completes or closes the request according to the user’s behavior.
When the Host app makes a request to an extension, it generally indicates the context in which the extension is running. For many extensions, the most important part is to set up a work item that the user will work with when using the extension. For example, the context of a share extension might contain a text that the user chooses to share.
When the host app sends a request (usually is called beginRequestWithExtensionContext: method), you can use the extension of the main extensionContext attribute to get the context of trying to controller, The NSExtensionContext class is then used to parse the context and get the work item. Typically, the context is parsed in the loadView method of the view controller and the work item is retrieved so that the information can be displayed in the view interface after the view is loaded. To get the extension context, use the following code:
NSExtensionContext *myExtensionContext = [self extensionContext];
Copy the code
Of interest is the inputItems property of the content object, which contains the work items that the application extension needs to use. The inputItems property contains an array of type NSExtensionItem, each member of which contains an executable work item. To get work items from the context, use the following code:
NSArray *inputItems = [myExtensionContext inputItems];
Copy the code
Each NSExtensionItem object contains several properties that describe the work item, such as title, text content, attachment information, and user information.
Note the attachments property, which contains an array of media data associated with the work item. For example, a work item on a share request, the attachments attribute might contain information from the web page that the user wants to share.
When a user’s work item is finished, the application extension usually gives the user two choices: complete the task or cancel the task. According to user selection, expansion will call completeRequestReturningItems: expirationHandler: completion: The cancelRequestWithError: method returns the work item to host app, or the cancelRequestWithError: method is called, returning an error code.
In iOS, your application extension may take more time to handle potentially lengthy tasks, such as uploading content to the Web. In this case, you use the NSURLSession class to turn the task into a background task. Because switching to background processing tasks requires a separate thread, it can still be processed after the extension completes the main application request and closes. To learn more about the use of the NSURLSession class in the extension, see Performing Uploads and Downloads.
Important: While you can set up a background URL to upload or download tasks, some types of background tasks, such as supporting VoIp or playing music in the background, cannot be implemented through extensions.
If your App extension’s info.plist file contains the UIBackgroundModes keyword, it will be rejected when uploading to the App Store. (For more Information about the UIBackgroundModes keyword, see UIBackgroundModes in the Information Property List Key Reference.)
Optimize efficiency and performance
Application extensions have a significantly lower memory usage priority than currently running applications. In both iOS and OS X, the system does not hesitate to terminate the extension because the user wants to return to the primary target in the Host App. However, some application extensions have a higher memory usage priority than others. Widgets, for example, are more demanding because they display information in real time, because the average user prefers to have multiple widgets open at the same time.
Your application extension does not have a main loop thread, so you need to follow this rule in order to get the best performance from the extension in the main loop thread. For example, if your application extension blocks the main loop thread, it can cause a very poor user experience when using the main application. One thing to keep in mind is that the GPU is a shared resource in the system, so application scaling is not a high priority. For example, if you are playing a game that is very GPU intensive, it may choose to turn off the Today Widget due to high memory pressure.
Design a streamlined user interface
Most extension points require you to provide the user with some custom interface that is presented to the user when they open your application extension. In general, the interface for application extensions should be as simple, introverted, and focused on a single task as possible. To improve performance and user experience, avoid interfaces that are irrelevant to this extension.
Most of the application extension templates provided by Xcode contain an initial interface file from which you can start designing the interface.
In the habitual thinking of users, they generally identify the extension function by the icon of the application extension. In general, the icon of an application extension is the same as the icon of its main application. Using the icon of the host application as the icon of the application extension helps the user to determine the source of the extension, that is, to assure the user that the extension is from the host application they have installed. There are some exceptions, of course.
In iOS, the icon of a custom Action extension uses the icon of its main application. In OS X, if the body of an extension is used only to install the package of the extension, the extension must provide a separate icon, otherwise the icon of the body application will be used.
Use a short, semantically clear name for your application extensions. This helps users associate extensions with your main application and allows them to better manage extensions within their system. Set the name of the extension Target by applying the CFBundleDisplayName attribute, which you can modify in the info.plist file. If you don’t set a value for CFBundleDisplayName, that is, you don’t set a name for the extension, then the application extension will use the name of its main application, which is the value in the CFBundleName property.
Some application extensions also require a brief explanation. For example, Widget extensions in OS X display a simple description, which helps users better select the Widget extensions they want to display in today’s notifications. The description of the extension can be set in the widget.description property of the InfoPlist. Strings file.
Make sure your iOS App extension works on all devices
You must ensure that the submitted application extension is generic: it must work with iPhone, iPod Touch and iPad. This requirement applies regardless of which target device family you choose for the included application. The application extension template in Xcode is configured correctly for the common family of target devices.
To declare that your application extension is universal, specify the “iPhone/iPad” value using the target Device Family build Settings in Xcode.
Make sure your application extensions are universal
- In the Xcode project navigator of Keyboard Project, select the project file. If the Project and Targets lists in the project editor are hidden, show them. To do this, click the button to the left of the Project editor TAB bar.
- In the Targets group of the Project and Targets lists, select targets to apply the extension.
- Select the Build Settings TAB in the Project editor. Make sure Basic and the Combined button are selected to make it easier to find the Settings you want.
- In the Deployment Group of the Project editor, look at the “Targeted Device Family” setting. For Debug and Release configurations, the value should be “iPhone/iPad”. If you find a different value, correct it to “iPhone/iPad”.
Use the Auto Layout and Size classes classes when designing and building application extensions. Test your application extension to make sure it matches your expected behavior for all device sizes and orientations. As described in the “Simulator User Guide, do this in the iOS emulator and, if possible, test the physical device in both directions.
Keep in mind that even if your containing app is only for the iPad family, your containing app extension will run in compatibility mode within the iPhone app.
Important to pass App Review, you must specify “iPhone/iPad” (sometimes called Universal) as the target device family for the application extension, regardless of which target device family you choose for the containing App.
In future iOS updates, application extensions will only run on the natively supported devices (or device compatibility mode) on which the extension body applies. For example, when using aN iPhone app in compatible mode, the extension provided by the containing app of only iPad will not be visible. In order to ensure the best user experience, we suggest that your containing App and its application extensions should be common.
Debug, configure, and test your application extensions
Note: Make sure that all extensions in the main application use the same signed code. All targets in an Xcode project must be code signed the same way. For example, during testing, you can use temporary code signatures or developer certificates, but you must use the same method for all targets in your project. To submit to the App Store, use your distribution certificate to get all targets.
Debugging an application extension with Xcode is basically the same as debugging any other application, with the only difference being that you choose a carrier application that has access to the extension. When you compile and run the application extension, Xcode will run the carrier application, wait for you to use the extension and trigger the pilot to debug the extension. You specify a carrier application for the extension in Scheme (a Scheme encapsulates the instructions for Target compilation).
When you add an application extension Target to the main application project, Xcode creates a scheme for the application extension by default. The Application extension Scheme allows you to specify which application will call your extension during debugging, i.e. specify a debug carrier application. By default, when you compile and run an extension, you are asked which carrier application you use to invoke the extension.
Before you compile and run an application extension, you should make sure that a Scheme is selected for your extension. You can set the Scheme for the application extension by going to Product > Scheme > MyExtensionName or by using the Xcode menu bar to call out the Scheme menu and select MyExtensionName.
Note: If you run Scheme for the main application instead of Scheme for the application extension, Xcode will tell you when you compile the project that it is waiting to debug the application extension.
When you compile and run an application extension, Xcode lists the carrier applications that you are allowed to call the extension. When you select a carrier application and run it, the debugger is ready to work, ready to intercept at the breakpoint you hit. When you use an extension in a carrier application, you can Debug the application extension. You debug application extensions the same way you debug any other process using Xcode.
In OS X, before you access an extension in a carrier application, make sure that the extension is allowed to be used. In general, turn extensions on or off in the Extension panel of System Preferences (you can also turn on the Application Extension panel in the Share or Action menus). It is important to note that when debugging a Widget extension using the Widget emulator in OS X, you do not need to turn it on. You must enable Keyboard Keyboards when debugging Keyboard extensions (you can use Settings > General > Keyboard > Keyboards > Keyboards).
During debugging, Xcode creates a continuous session in OS X to compile application extensions. This means that if you want to use an extension under OS X, you need to use Finder to copy it from the build to a place like the Applications Folder.
Note: In Xcode’s debug console log, the binary value of the application extension may be associated with the CFBundleIdentifier property, not the CFBundleDisplayName property.
Since application extensions must be responsive and efficient, it is best to check the Debug Evacuate in the Debug navigator when running an application extension. Debug metrics show how the extension uses CPU, memory, and other system resources at run time. When you find performance issues like abnormal CPU usage, such as abnormal spikes in CPU usage, you can use Instruments to analyze your extensions and identify areas for improvement. You can open Instruments during a debug session by clicking on the configuration file in Instruments in any debug meter report (to view the debug meter report, click on the meter in the debug area). To learn about the Debug monitor, check out Debug Your App. To learn more about Instruments, see the Instruments User Guide.
Note: Selecting Product > Profile in Xcode compiles and runs application extensions directly in Instruments. Instruments uses the set of executable files in the Profile section of the schema as the vehicle for the extension.
If you want to test your application extensions using the testing frameworks provided by Xcode (such as the XCTest APIs), you need to write some test case code in the main application. To learn more about XCTest, see Testing with Xcode.
Distribute the extension principal application
You can’t upload an App extension directly to the App Store unless it’s included in the main App, and you can’t transfer an App extension from one App to another.
If you want users to use your App extensions, you must submit a host application to the App Store, and the host application must not contain only extensions if it has other features.
If you want to submit OS X App extensions, it’s recommended that you submit your main App to the App Store, but that’s not the only way. In OS X, the main application can contain only application extensions without providing additional functionality beyond the extensions.
Note: If you do not use the App Store to deliver the host application and OS X extensions to users, Gatekeeper will not allow the extensions to take effect until the host application is approved. Also, if you do not upload the main application to the App Store, the main application cannot sign your developer ID name, so the user must explicitly reload Gatekeeper from the main application for the extension to take effect.