限于iOS的沙盒机制(sandbox),不能跨app访问数据。所以想分享App A的数据到App B中使用,需要借助Open In来操作。
本文介绍如何实现通过“Open In”方式来分享数据到其它App当中,以及在实现时,踩到的坑(前车之鉴)。
1. 涉及的类
Cocoa框架为我们提供了类UIDocumentInteractionController来实现Open In分享。
2. 实现步骤
简单说来,我们需要准备数据,弹出Open In窗口,调用UIDocumentInteractionController分享数据。
2.1 准备数据
推荐将要分享的数据拷贝到一个目录文件夹做备用。当然如果将分享的数据体积较大,也可省略这一步,但必须保证数据在分享过程中可用;
NSString *fromPath = @"demoFromPath";
NSString *toPath = @"demoToPath";
NSError *err = nil;
NSFileManager*fileManager =[NSFileManager defaultManager];
[fileManager copyItemAtPath:fromPath toPath:toPath error:&err];
另外还需初始化一个分享类实例对象,并声明类遵循UIDocumentInteractionControllerDelegate协议。
首先声明一个UIDocumentInteractionController属性实例:
@property (nonatomic, strong) UIDocumentInteractionController *documentViewController;
@synthesize documentController;
在分享前确保初始化该属性实例:
NSString *demoFilePath = @"./demo.jpg";
NSURL *demoFileUrl = [NSURL fileURLWithPath:demoFilePath];
if (!self.documentViewController) {
//init an instance with method:interactionControllerWithURL
self.documentViewController = [UIDocumentInteractionController interactionControllerWithURL:demoFileUrl];
self.documentViewController.UTI = demoFileUrl.lastPathComponent;
self.documentViewController.delegate = self;
}
2.2 弹出Open In窗口
Cocoa框架的 UIDocumentInteractionController 类里面提供了5个相关的函数来展示Open In窗口。当Open In窗口弹出时,会列出支持该数据类型(通常是文件类型)的App列表,所以若需要测试分享到微信,微博等真实的App时,必须在真机中测试。
// This is the default method you should call to give your users the option to quick look, open, or copy the document. // Presents a menu allowing the user to Quick Look, open, or copy the item specified by URL. // This automatically determines the correct application or applications that can open the item at URL. // Returns NO if the options menu contained no options and was not opened. // Note that you must implement the delegate method documentInteractionControllerViewControllerForPreview: to get the Quick Look menu item.
- (BOOL)presentOptionsMenuFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated; - (BOOL)presentOptionsMenuFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;
// Bypasses the menu and opens the full screen preview window for the item at URL. Returns NO if the item could not be previewed.
// Note that you must implement the delegate method documentInteractionControllerViewControllerForPreview: to preview the document.
- (BOOL)presentPreviewAnimated:(BOOL)animated;
// Presents a menu allowing the user to open the document in another application. The menu
// will contain all applications that can open the item at URL.
// Returns NO if there are no applications that can open the item at URL.
- (BOOL)presentOpenInMenuFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated;
- (BOOL)presentOpenInMenuFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;
在项目当中我用的较多的方法是:
- (BOOL)presentOpenInMenuFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated;
比较灵活使用。
2.3 实现delegate:UIDocumentInteractionControllerDelegate中的方法:
展示将要分享的信息:
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application
在分享完成时给提示或进行其它操作:
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application
3. 注意的问题
在分享时,UIDocumentInteractionController必须作为一个非栈空间对象来操作,否则弹不出Open In窗口,这涉及到iOS的内存管理机制了,在栈上所申请的内存空间,当我们出了变量所在的作用域后,系统会自动我们回收这些空间。建议声明为类的属性来实现。