どこでもDooor

参加した勉強会 / 読んだ技術書 / 見聞きした備忘録 を気ままに書いていきます

【iOS8】ドキュメントプロバイダ 実装

実装編

  1. Host appへUIDocumentMenuViewControllerを追加
  2. Containing appからDocument Providerにデータを渡す
  3. DocumentPickerViewControllerの編集

1. Host appへUIDocumentMenuViewControllerを追加

- デリゲート設定
<UIDocumentMenuDelegate, UIDocumentPickerDelegate>
- UIDocumentMenuViewController追加
// UIDocumentMenuViewControllerをImportモードで表示
- (IBAction)showImportMenu:(id)sender {
    NSArray *utis = @[(NSString *)kUTTypeRTF,(NSString *)kUTTypePNG,(NSString *)kUTTypeText,
                      (NSString *)kUTTypePlainText,(NSString *)kUTTypePDF, (NSString *)kUTTypeImage];
    UIDocumentMenuViewController *menu = [[UIDocumentMenuViewController alloc]
                                        initWithDocumentTypes:utis inMode:UIDocumentPickerModeImport];
    menu.delegate = self;
    [self presentViewController:menu animated:YES completion:nil];
}

// UIDocumentMenuViewControllerをExportモードで表示
- (IBAction)showExportMenu:(id)sender {
    NSURL *path = [[NSBundle mainBundle] URLForResource:@"2" withExtension:@"jpeg"];
    UIDocumentMenuViewController *menu = [[UIDocumentMenuViewController alloc]
                                          initWithURL:path inMode:UIDocumentPickerModeExportToService];
    menu.delegate = self;
    [self presentViewController:menu animated:YES completion:nil];
}

// メニューの中から選択されたUIDocumentPickerViewControllerを表示
- (void)documentMenu:(UIDocumentMenuViewController *)documentMenu didPickDocumentPicker:(UIDocumentPickerViewController *)documentPicker{
    documentPicker.delegate = self;
    [self presentViewController:documentPicker animated:YES completion:nil];
}

- (void)documentMenuWasCancelled:(UIDocumentMenuViewController *)documentMenu{
    NSLog(@"cancel");
}
- UIDocumentPickerViewControllerのデリゲートメソッド
// UIDocumentPickerViewControllerで選択したデータのURLが返ってくる
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url{
    NSLog(@"%@",url);
}

// 失敗した場合か、キャンセルされた時に呼ばれる
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller{
    NSLog(@"cancel");
}

2. Containing appからDocument Providerにデータを渡す

  • Document ProviderはContaining appとは異なるサンドボックスを持っているため、Document ProviderからContaining app内のデータへアクセスはできない。そのため、あらかじめデータを渡しておかなければならない。
- NSUserDefaultsでデータを渡す場合
NSUserDefaults *df = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.ContainingApp"];
[df setObject:@"sample" forKey:@"hello"];
- NSFileManagerからデータを渡す場合
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *url = [fm containerURLForSecurityApplicationGroupIdentifier:@"group.com.ContainingApp"];
NSData *imgData = [[NSData alloc] initWithData:UIImagePNGRepresentation([UIImage imageNamed:@"1.jpg"])];
NSString *path = [[url path] stringByAppendingPathComponent:@"1.jpg"];
if (![fm fileExistsAtPath:path]) {
    BOOL success = [fm createFileAtPath:path contents:imgData attributes:nil];
    if (!success) {
        NSLog(@"error");
    }
}

3. DocumentPickerViewControllerの編集

- UIDocumentPickerMode毎のUIの設定など
- (void)prepareForPresentationInMode:(UIDocumentPickerMode)mode {
    if (mode == UIDocumentPickerModeImport) {
        self.exportButton.alpha = 0.0;
    } else if (mode == UIDocumentPickerModeExportToService) {
        self.importButton.alpha = 0.0;
    }
}
- Host appにURLを返すためのメソッド
// UIDocumentPickerModeImportの場合
- (IBAction)import:(id)sender {
    NSFileManager *fm = [NSFileManager defaultManager];
    NSURL *documentURL = [fm containerURLForSecurityApplicationGroupIdentifier:@"group.com.ContainingApp"];
    NSString *path = [[documentURL path] stringByAppendingPathComponent:@"1.jpg"];
    [self dismissGrantingAccessToURL:[NSURL fileURLWithPath:path]];
}

// UIDocumentPickerModeExportToServiceの場合
- (IBAction)export:(id)sender {
    [self dismissGrantingAccessToURL:self.originalURL];
}

4. HostAppで渡されたデータを確認する

・HostAppのNSTemporaryDirectoryにデータが保存されている
・保存先は指定されているので、指定されたディレクトリへのアクセスが必要

// HostApp内で行い、allFileNamesに保存されたデータ名が入っている
NSFileManager *fm = [NSFileManager defaultManager];
NSString *tmp = NSTemporaryDirectory();
NSString *path = [tmp stringByAppendingPathComponent:@"DocumentPickerIncoming"];
NSArray *allFileNames = [fm contentsOfDirectoryAtPath:path error:nil];

余裕があったのでexportについても少しですが調べられました。 設定は同じなので、導入編で確認してください。