在iOS 8中,UIViewController新增了一个扩展上下文的属性extensionContext,用以处理容器应用和扩展之间的通信,上下文的类型是NSExtensionContext。我们可以通过它来获取相应数据,进行返回容器应用的界面等操作。
我们可以先看一下NSExtensionContext的定义
// Class representing the extension request's context
@available(iOS 8.0, *)
open class NSExtensionContext : NSObject {
// 该数据存放着容器应用传入给NSExtensionContext的NSExtensionItem数组。其中每个NSExtensionItem标识了一种类型的数据,要想获取数据主要操作该属性。
open var inputItems: [Any] { get }
// 通知载体程序扩展已经完成请求。调用该方法后,扩展的UI会关闭并返回容器程序中。其中的items参数就是返回载体程序的数据项。
open func completeRequest(returningItems items: [Any]?, completionHandler: ((Bool) -> Swift.Void)? = nil)
// 通知载体程序的扩展已取消请求。调用该方法后,扩展的UI会关闭并返回容器程序中。其中error参数为错误的描述信息。
open func cancelRequest(withError error: Error)
// 打开容器应用的一个方法
open func open(_ URL: URL, completionHandler: ((Bool) -> Swift.Void)? = nil)
}
// NSExtensionItem的userInfo属性中对应的错误信息键名
@available(iOS 8.0, *)
public let NSExtensionItemsAndErrorsKey: String
extension NSNotification.Name {
// 载体程序将要返回前台通知
@available(iOS 8.2, *)
public static let NSExtensionHostWillEnterForeground: NSNotification.Name
// 载体程序进入后台通知
@available(iOS 8.2, *)
public static let NSExtensionHostDidEnterBackground: NSNotification.Name
// 载体程序被挂起通知
@available(iOS 8.2, *)
public static let NSExtensionHostWillResignActive: NSNotification.Name
// 载体程序被激活通知
@available(iOS 8.2, *)
public static let NSExtensionHostDidBecomeActive: NSNotification.Name
}
通过对NSExtensionContext的了解,我们发现如果需要操作NSExtensionContext的数据的时候,我们需要了解它的inputItems属性。inputItems是包含NSExtensionItem类型对象的数组,那么,需要处理里面的数据就应该先了解一下NSExtensionItem的数据结构。
@interface NSExtensionItem : NSObject<NSCopying, NSSecureCoding>
// 标题
@property(nullable, copy, NS_NONATOMIC_IOSONLY) NSAttributedString *attributedTitle;
// 内容
@property(nullable, copy, NS_NONATOMIC_IOSONLY) NSAttributedString *attributedContentText;
// 附件数组,包含图片、视频、连接等资源,封装在NSItemProvider类型中
@property(nullable, copy, NS_NONATOMIC_IOSONLY) NSArray *attachments;
// 一个key-value结构的数据。NSExtensionItem中的属性都会在这个属性中一一映射。
@property(nullable, copy, NS_NONATOMIC_IOSONLY) NSDictionary *userInfo;
@end
// 对应userInfo结构中的NSExtensionItem属性的键名
// 标题的键名
FOUNDATION_EXTERN NSString * __null_unspecified const NSExtensionItemAttributedTitleKey NS_AVAILABLE(10_10, 8_0);
// 内容的键名
FOUNDATION_EXTERN NSString * __null_unspecified const NSExtensionItemAttributedContentTextKey NS_AVAILABLE(10_10, 8_0);
// 附件的键名
FOUNDATION_EXTERN NSString * __null_unspecified const NSExtensionItemAttachmentsKey NS_AVAILABLE(10_10, 8_0);
从上面的定义可以看出除了文本内容以外,其他类型的内容都是作为附件存储的,而附件又是封装在一个叫做NSItemProvider类型中的,下面我们接着了解一下NSItemProvider的定义。
open class NSItemProvider : NSObject, NSCopying {
// 初始化方法,item参数表示为附件数据,typeIdentifier表示为附件对应的类型标示
public init(item: NSSecureCoding?, typeIdentifier: String?)
// 根据指定的文件路径进行初始化
public convenience init?(contentsOf fileURL: URL!)
// 为资源类型自定义加载过程,这个方法主要针对自定义资源使用,例如自己定的类或者文件格式等。当调用`open func loadItem(forTypeIdentifier typeIdentifier: String, options: [AnyHashable : Any]? = nil, completionHandler: NSItemProvider.CompletionHandler? = nil)`方法时就会出发定义的加载过程
open func registerItem(forTypeIdentifier typeIdentifier: String, loadHandler: @escaping NSItemProvider.LoadHandler)
// Returns the list of registered type identifiers
open var registeredTypeIdentifiers: [Any] { get }
// 用于判断是否有typeIdentifier所指定的资源存在,存在则返回true,否则返回false.该方法结合`open func loadItem(forTypeIdentifier typeIdentifier: String, options: [AnyHashable : Any]? = nil, completionHandler: NSItemProvider.CompletionHandler? = nil)`方法使用。
open func hasItemConformingToTypeIdentifier(_ typeIdentifier: String) -> Bool
// 加载typeIdentifier指定的资源。加载是一个异步过程,加载完成会触发completionHandler回调。
open func loadItem(forTypeIdentifier typeIdentifier: String, options: [AnyHashable : Any]? = nil, completionHandler: NSItemProvider.CompletionHandler? = nil)
}
// Common keys for the item provider options dictionary.
@available(iOS 8.0, *)
public let NSItemProviderPreferredImageSizeKey: String // NSValue of CGSize or NSSize, specifies image size in pixels.
extension NSItemProvider {
// 自定义的预览图处理回调
@available(iOS 8.0, *)
open var previewImageHandler: NSItemProvider.LoadHandler?
// 加载资源的预览图片
@available(iOS 8.0, *)
open func loadPreviewImage(options: [AnyHashable : Any]! = [:], completionHandler: NSItemProvider.CompletionHandler!)
}
// Keys used in property list items received from or sent to JavaScript code
// If JavaScript code passes an object to its completionFunction, it will be placed into an item of type kUTTypePropertyList, containing an NSDictionary, under this key.
@available(iOS 8.0, *)
public let NSExtensionJavaScriptPreprocessingResultsKey: String
// Arguments to be passed to a JavaScript finalize method should be placed in an item of type kUTTypePropertyList, containing an NSDictionary, under this key.
@available(iOS 8.0, *)
public let NSExtensionJavaScriptFinalizeArgumentKey: String
extension NSItemProvider {
@available(iOS 8.0, *)
public class let errorDomain: String
// 错误码
@available(iOS 8.0, *)
public enum ErrorCode : Int {
case unknownError
case itemUnavailableError
case unexpectedValueClassError
@available(iOS 9.0, *)
case unavailableCoercionError
}
public typealias CompletionHandler = (NSSecureCoding?, Error!) -> Swift.Void
public typealias LoadHandler = (NSItemProvider.CompletionHandler!, Swift.AnyClass!, [AnyHashable : Any]!) -> Swift.Void
}