在react-native开发中有一个功能需求为,打开之前已经下载到Documents中的文件。一开始本想用webview来加载文件。后来发现有UIDocumentInteractionController
这个api来更好的完成这个功能。
首先在RN引用的类中加入UIDocumentInteractionControllerDelegate
我们要用到这个来呈现预览视图:
NativeUtil.h
#import <Foundation/Foundation.h>
#import "RCTBridgeModule.h"
#import "UIView+React.h" //要引入这个头文件,在rn中创建和加载原声视图
@interface NativeUtil : NSObject <RCTBridgeModule,UIDocumentInteractionControllerDelegate>
@end
在NativeUtil.m中实现该委托。定义一个暴露给RN的方法,在js中调用:
RCT_EXPORT_METHOD(ShowFileChooser: (RCTResponseSenderBlock)callback){
NSString *filePath = @"ceshi007"; callback(@[[NSNull null],filePath]); //测试callback,从native向rn传值。
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //获取应用本沙盒内的目录。
NSString *documentpath = paths[0]; //获取document的路径
NSString *fileName = [documentpath stringByAppendingPathComponent:@"Screenshot_2016-12-15-21-29-07-50.png"]; //指定上述图片的路径。
NSURL *fileURL = [NSURL fileURLWithPath:fileName];
dispatch_async(dispatch_get_main_queue(), ^{ //运行主线程来加载界面,并初始化UIDocumentInteractionController
UIDocumentInteractionController *documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
documentInteractionController.delegate =self ;
[documentInteractionController presentPreviewAnimated:YES]; //present出来文件的预览界面。
});
}
之后定义(UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
方法,要加载出来预览的界面,上述方法必须实现,且返回一个当前的页面的ViewController。用于作为预览视图的父ViewController来弹出modal。
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller{
UIViewController *newVC =[self getPresentedViewController]; //获取当前屏幕中present出来的viewcontroller。
return newVC;
};
这里我们是在一个非视图类创建并在加载一个视图,所以我们要先获取到当前界面的ViewController
,将被展示的view
加到当前view
的子视图,或用当前view presentViewController
,或pushViewContrller
。这里我从网上找到了两个方法:
//获取当前屏幕显示的viewcontroller
- (UIViewController *)getCurrentVC
{
UIViewController *result = nil;
UIWindow * window = [[UIApplication sharedApplication] keyWindow];
if (window.windowLevel != UIWindowLevelNormal)
{
NSArray *windows = [[UIApplication sharedApplication] windows];
for(UIWindow * tmpWin in windows)
{
if (tmpWin.windowLevel == UIWindowLevelNormal)
{
window = tmpWin;
break;
}
}
}
UIView *frontView = [[window subviews] objectAtIndex:0];
id nextResponder = [frontView nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]])
result = nextResponder;
else
result = window.rootViewController;
return result;
}
//获取当前屏幕中present出来的viewcontroller
- (UIViewController *)getPresentedViewController
{
UIViewController *appRootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *topVC = appRootVC;
if (topVC.presentedViewController) {
topVC = topVC.presentedViewController;
}
return topVC;
}
在RN中,使用modal组件之后,弹出的modal视图的viewcontroller相当于present出来的viewcontroller.
之后使用[self getPresentedViewController]
就可以获得viewcontroller
来加载视图。