呃...

其實不會有什麼精深的東西,也就只是把我學習過程記錄一下...

2015年2月5日 星期四

open file by default viewer in iOS(UIDocumentInteractionController, QuickLook Framework )


Apple Official Document:
https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/DocumentInteraction_TopicsForIOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010409-SW1

Apple 提供UIDocumentInteractionController 來work with Quick Look Framework或其它App來開啟文件 - ( UIDocumentInteractionController Class Reference)
以及僅可preview的default browser的SDK - Quick Look Framework (Quick Look Framework Reference for iOS.)

UIDocumentInteractionController為了要可以preview file,所以包含Quick Look framework的功能。(那所以不要使用Quick Look ?單純使用Quick Look有沒有優點?)

單獨使用Quick Look Framework


1. 主要Class - QLPreviewController
2. 可以使用NavigationController push view,或是使用modal方式去push view ( presentModalViewController:animated:)
3. preview的title會自動使用URL的last path component,可以override  previewItemTitleaccessor去修改
4. Quick Look support的type: iWork, Office, RTF, PDF, Image, UTI, csv
5. 使用DataSource pattern 提供檔案來源,應類似tableview的方式

使用UIDocumentInteractionController的3 step:


1. 建立UIDocumentInteractionController的instance
2. 在UI上放一個file
3. 當tap這個file時,使用UIDocumentInteractionController去present它。

presentation的時候UIDocumentInteractionController提供三種UI:


1. preview file:
call presentPreviewAnimated:,並且必須implement documentInteractionControllerViewControllerForPreview: ,如果return值為nil或沒有其他view controller,則file不會被present

2. preview file或其他App開啟的選項:
call presentOptionsMenuFromRect:inView:animated: or presentOptionsMenuFromBarButtonItem:animated:
這邊還可以另外加入copy和print options (此兩種method與UIDocumentInteractionController的delegate有關)

3. 提示使用者要用其他App開啟:
 presentOpenInMenuFromRect:inView:animated: or presentOpenInMenuFromBarButtonItem:animated:

UIDocumentInteractionController也具有file sharing的功能,詳情見(see UI State Preservation in iOS Technology Overview and the DocInteraction sample code project)

UIDocumentInteractionController包含filename, type, url, icon等properties可供使用。
UIDocumentInteractionController另外有annotation property可提供客製化information給其他App。
UIDocumentInteractionController會自動handle view的dismiss,但也有另外提供兩種方式來進行手動關閉view。dismissMenuAnimated: or dismissPreviewAnimated:

Registering the File Types Your App Supports


如果在Info.plist有註明自己的App有support特定格式檔案的話,則其他App若需要開啟此格式檔案則可以呼叫本身的App。若要讓自己的App可以support其他App去開啟檔案,則需要在Info.plist中使用 CFBundleDocumentTypes。
CFBundleDocumentTypes是dictionary型態,有四個key:
1. CFBundleTypeName - 文件型態的名稱
2. CFBundleTypeIconFiles - 是array型態,用來放文件icon的image
3. LSItemContentTypes - contains an array of strings with the UTI types that represent the supported file types in this group.
4. LSHandlerRank - 說明App是文件的owner或是只能打開檔案而已

Apple官方文件中的XML例子如下:
<dict>
   <key>CFBundleTypeName</key>
   <string>My File Format</string>
   <key>CFBundleTypeIconFiles</key>
       <array>
           <string>MySmallIcon.png</string>
           <string>MyLargeIcon.png</string>
       </array>
   <key>LSItemContentTypes</key>
       <array>
           <string>com.example.myformat</string>
       </array>
   <key>LSHandlerRank</key>
   <string>Owner</string>
</dict>

當其他App 使用UIDocumentInteractionController  call自己的App時,其他App會丟information到  application:willFinishLaunchingWithOptions: or application:didFinishLaunchingWithOptions:,若有自行定義的document type,則需override method去處理收到的information並初始化自己的App。
丟來的資訊存放在上述方法中dictionary型態的options,有幾個key:
1. UIApplicationLaunchOptionsURLKey  - 檔案的URL
3.UIApplicationLaunchOptionsSourceApplicationKey - 想開檔案的其他App的bundle identifier
3.UIApplicationLaunchOptionsURLKey - 其他App傳來的plist file

以下是非常簡單的Quick Look Framework 範例


#import "ViewController.h"
#import <QuickLook/QuickLook.h>

@interface ViewController ()<QLPreviewControllerDataSource,QLPreviewControllerDataSource>{
    NSURL *url;
}
@property (nonatomic, strong) QLPreviewController *qlController;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *strURL=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    strURL=[strURL stringByAppendingPathComponent:@"簡介Doxygen.doc"];
    url=[NSURL fileURLWithPath:strURL];

    // Do any additional setup after loading the view, typically from a nib.
    self.qlController=[[QLPreviewController alloc]init];
    self.qlController.dataSource=self;
}

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    [[self.qlController navigationItem] setRightBarButtonItem:nil];
    [self presentViewController:self.qlController animated:YES completion:nil];
}

-(NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller{
    return 1;
}
-(id<qlpreviewitem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index{
    return url;
}
@end

再來是UIDocumentInteractionController 的範例

#import "ViewController.h"

@interface ViewController ()<UIDocumentInteractionControllerDelegate>{
    NSURL *url;
}
@property(nonatomic,strong) UIDocumentInteractionController *docController;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *strURL=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    strURL=[strURL stringByAppendingPathComponent:@"簡介Doxygen.doc"];
    url=[NSURL fileURLWithPath:strURL];
    self.docController=[UIDocumentInteractionController interactionControllerWithURL:url];
    self.docController.delegate=self;
    
    // Do any additional setup after loading the view, typically from a nib.
}

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    [self.docController presentPreviewAnimated:YES];
}

-(UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller{
    return self.navigationController;
}
-(void)documentInteractionControllerWillBeginPreview:(UIDocumentInteractionController *)controller{

}
@end

以上兩個範例都很簡單,官方文件也有其他範例可以看。 比較要注意的兩點:
1. 使用QLViewController時,若有使用NavigationController,可以用navigation的push
2. UIDocumentInteractionController 在delegation method的return要return navigationController,若是不用navigation則直接return self就可以。

最後重申一次,QLViewController只能preview,而UIDocumentInteractionController 則是可以support其他App或做比較細節一點的設定,像是可以設定action sheet讓 user選擇要preview、使用其他App開啟或是view dismiss要進行什麼動作之類的。
若只是要preview,QLViewController就可以滿足,其他狀況 UIDocumentInteractionController 還是比較方便。

沒有留言:

張貼留言