要素:1)通信双方;2)协议;3)支持机制(系统,进行协议注册);4)数据
https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html
Using URL Schemes to Communicate with Apps
A URL scheme lets you communicate with other apps through a protocol that you define. To communicate with an app that implements such a scheme, you must create an appropriately formatted URL and ask the system to open it. To implement support for a custom scheme, you must declare support for the scheme and handle incoming URLs that use the scheme.
Note: Apple provides built-in support for the http
, mailto
, tel
, and sms
URL schemes among others. It also supports http
–based URLs targeted at the Maps, YouTube, and iPod apps. The handlers for these schemes are fixed and cannot be changed. If your URL type includes a scheme that is identical to one defined by Apple, the Apple-provided app is launched instead of your app. For information about the schemes supported by apple, see Apple URL Scheme Reference.
Sending a URL to Another App
When you want to send data to an app that implements a custom URL scheme, create an appropriately formatted URL and call the openURL:
method of the app object. The openURL:
method launches the app with the registered scheme and passes your URL to it. At that point, control passes to the new app.
The following code fragment illustrates how one app can request the services of another app (“todolist” in this example is a hypothetical custom scheme registered by an app):
NSURL *myURL = [NSURL URLWithString:@"todolist://www.acme.com?Quarterly%20Report#200806231300"]; |
[[UIApplication sharedApplication] openURL:myURL]; |
If your app defines a custom URL scheme, it should implement a handler for that scheme as described in Implementing Custom URL Schemes. For more information about the system-supported URL schemes, including information about how to format the URLs, see Apple URL Scheme Reference.
Implementing Custom URL Schemes
If your app can receive specially formatted URLs, you should register the corresponding URL schemes with the system. Apps often use custom URL schemes to vend services to other apps. For example, the Maps app supports URLs for displaying specific map locations.
Registering Custom URL Schemes
To register a URL type for your app, include the CFBundleURLTypes
key in your app’s Info.plist
file. The CFBundleURLTypes
key contains an array of dictionaries, each of which defines a URL scheme the app supports. Table 6-1 describes the keys and values to include in each dictionary.
Key |
Value |
---|---|
|
A string containing the abstract name of the URL scheme. To ensure uniqueness, it is recommended that you specify a reverse-DNS style of identifier, for example, The string you specify is also used as a key in your app’s |
|
An array of strings containing the URL scheme names—for example, |
Note: If more than one third-party app registers to handle the same URL scheme, there is currently no process for determining which app will be given that scheme.
Handling URL Requests
An app that has its own custom URL scheme must be able to handle URLs passed to it. All URLs are passed to your app delegate, either at launch time or while your app is running or in the background. To handle incoming URLs, your delegate should implement the following methods:
-
Use the
application:willFinishLaunchingWithOptions:
andapplication:didFinishLaunchingWithOptions:
methods to retrieve information about the URL and decide whether you want to open it. If either method returnsNO
, your app’s URL handling code is not called. -
Use the
application:openURL:sourceApplication:annotation:
method to open the file.
If your app is not running when a URL request arrives, it is launched and moved to the foreground so that it can open the URL. The implementation of your application:willFinishLaunchingWithOptions:
or application:didFinishLaunchingWithOptions:
method should retrieve the URL from its options dictionary and determine whether the app can open it. If it can, return YES
and let your application:openURL:sourceApplication:annotation:
(or application:handleOpenURL:
) method handle the actual opening of the URL. (If you implement both methods, both must return YES
before the URL can be opened.) Figure 6-1 shows the modified launch sequence for an app that is asked to open a URL.
If your app is running but is in the background or suspended when a URL request arrives, it is moved to the foreground to open the URL. Shortly thereafter, the system calls the delegate’s application:openURL:sourceApplication:annotation:
to check the URL and open it. Figure 6-2 shows the modified process for moving an app to the foreground to open a URL.
Note: Apps that support custom URL schemes can specify different launch images to be displayed when launching the app to handle a URL. For more information about how to specify these launch images, see Displaying a Custom Launch Image When a URL is Opened.
All URLs are passed to your app in an NSURL
object. It is up to you to define the format of the URL, but the NSURL
class conforms to the RFC 1808 specification and therefore supports most URL formatting conventions. Specifically, the class includes methods that return the various parts of a URL as defined by RFC 1808, including the user, password, query, fragment, and parameter strings. The “protocol” for your custom scheme can use these URL parts for conveying various kinds of information.
In the implementation of application:openURL:sourceApplication:annotation:
shown in Listing 6-2, the passed-in URL object conveys app-specific information in its query and fragment parts. The delegate extracts this information—in this case, the name of a to-do task and the date the task is due—and with it creates a model object of the app. This example assumes that the user is using a Gregorian calendar. If your app supports non-Gregorian calendars, you need to design your URL scheme accordingly and be prepared to handle those other calendar types in your code.
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url |
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { |
if ([[url scheme] isEqualToString:@"todolist"]) { |
ToDoItem *item = [[ToDoItem alloc] init]; |
NSString *taskName = [url query]; |
if (!taskName || ![self isValidTaskString:taskName]) { // must have a task name |
return NO; |
} |
taskName = [taskName stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; |
item.toDoTask = taskName; |
NSString *dateString = [url fragment]; |
if (!dateString || [dateString isEqualToString:@"today"]) { |
item.dateDue = [NSDate date]; |
} else { |
if (![self isValidDateString:dateString]) { |
return NO; |
} |
// format: yyyymmddhhmm (24-hour clock) |
NSString *curStr = [dateString substringWithRange:NSMakeRange(0, 4)]; |
NSInteger yeardigit = [curStr integerValue]; |
curStr = [dateString substringWithRange:NSMakeRange(4, 2)]; |
NSInteger monthdigit = [curStr integerValue]; |
curStr = [dateString substringWithRange:NSMakeRange(6, 2)]; |
NSInteger daydigit = [curStr integerValue]; |
curStr = [dateString substringWithRange:NSMakeRange(8, 2)]; |
NSInteger hourdigit = [curStr integerValue]; |
curStr = [dateString substringWithRange:NSMakeRange(10, 2)]; |
NSInteger minutedigit = [curStr integerValue]; |
NSDateComponents *dateComps = [[NSDateComponents alloc] init]; |
[dateComps setYear:yeardigit]; |
[dateComps setMonth:monthdigit]; |
[dateComps setDay:daydigit]; |
[dateComps setHour:hourdigit]; |
[dateComps setMinute:minutedigit]; |
NSCalendar *calendar = [s[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; |
NSDate *itemDate = [calendar dateFromComponents:dateComps]; |
if (!itemDate) { |
return NO; |
} |
item.dateDue = itemDate; |
} |
[(NSMutableArray *)self.list addObject:item]; |
return YES; |
} |
return NO; |
} |
Be sure to validate the input you get from URLs passed to your app; see Validating Input and Interprocess Communication in Secure Coding Guide to find out how to avoid problems related to URL handling. To learn about URL schemes defined by Apple, see Apple URL Scheme Reference.
Displaying a Custom Launch Image When a URL is Opened
Apps that support custom URL schemes can provide a custom launch image for each scheme. When the system launches your app to handle a URL and no relevant snapshot is available, it displays the launch image you specify. To specify a launch image, provide a PNG image whose name uses the following naming conventions:
<basename>-
<url_scheme><other_modifiers>.png
In this naming convention, basename represents the base image name specified by the UILaunchImageFile
key in your app’s Info.plist
file. If you do not specify a custom base name, use the string Default
. The <url_scheme> portion of the name is your URL scheme name. To specify a generic launch image for the myapp
URL scheme, you would include an image file with the name Default-myapp@2x.png
in the app’s bundle. (The @2x modifier signifies that the image is intended for Retina displays. If your app also supports standard resolution displays, you would also provide a Default-myapp.png
image.)
For information about the other modifiers you can include in launch image names, see the description of the UILaunchImageFile
name key in Information Property List Key Reference.