Показать UIDocumentInteractionController из кнопки «Поделиться» на панели навигации — iOS

В моем проекте я использую WSAssetPickerController.

Несмотря на то, что панель инструментов не работает (не большая проблема), все работает нормально.

Я добавил кнопку общего доступа в контроллере представления, но я не могу вызвать вызов UIDocumentInteractionController, я попытался скопировать тот же метод, который я использую для файлов, сохраненных в папке приложений (который отлично работает). Но здесь нет.

Как работает нерелевантная страница загрузок:

NSString *fileName = [directoryContents objectAtIndex:indexPath.row];
NSString *path;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Downloads"];
path = [path stringByAppendingPathComponent:fileName];

documentController = [[UIDocumentInteractionController alloc] init];
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];
[documentController setDelegate:self];
[documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];

Как загружаются изображения:

#pragma mark - Fetching Code

    - (void)fetchAssets
    {
        // TODO: Listen to ALAssetsLibrary changes in order to update the library if it changes. 
        // (e.g. if user closes, opens Photos and deletes/takes a photo, we'll get out of range/other error when they come back.
        // IDEA: Perhaps the best solution, since this is a modal controller, is to close the modal controller.

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            [self.assetsGroup enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {

                if (!result || index == NSNotFound) {

                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self.tableView reloadData];
                        self.navigationItem.title = [NSString stringWithFormat:@"%@", [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName]];
                    });

                    return;
                }

                WSAssetWrapper *assetWrapper = [[WSAssetWrapper alloc] initWithAsset:result];

                dispatch_async(dispatch_get_main_queue(), ^{

                    [self.fetchedAssets addObject:assetWrapper];

                });

            }];
        });

        [self.tableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.5];
    }

Как я загружаю и вызываю кнопку:

- (void)viewDidLoad
{
    self.navigationItem.title = @"Loading";

    UIBarButtonItem *shareButton = [[UIBarButtonItem alloc]
                                    initWithBarButtonSystemItem:UIBarButtonSystemItemAction
                                    target:self
                                    action:@selector(shareAction:)];
    self.navigationItem.rightBarButtonItem = shareButton;
    self.navigationItem.rightBarButtonItem.enabled = NO;


    // TableView configuration.
    self.tableView.contentInset = TABLEVIEW_INSETS;
    self.tableView.separatorColor = [UIColor clearColor];
    self.tableView.allowsSelection = NO;


    // Fetch the assets.
    [self fetchAssets];
}

Должны ли и выбрали выбранные активы

#pragma mark - WSAssetsTableViewCellDelegate Methods

- (BOOL)assetsTableViewCell:(WSAssetsTableViewCell *)cell shouldSelectAssetAtColumn:(NSUInteger)column
{
    BOOL shouldSelectAsset = (self.assetPickerState.selectionLimit == 0 ||
                              (self.assetPickerState.selectedCount < self.assetPickerState.selectionLimit));

    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    NSUInteger assetIndex = indexPath.row * self.assetsPerRow + column;

    WSAssetWrapper *assetWrapper = [self.fetchedAssets objectAtIndex:assetIndex];

    if ((shouldSelectAsset == NO) && (assetWrapper.isSelected == NO))
        self.assetPickerState.state = WSAssetPickerStateSelectionLimitReached;
    else
        self.assetPickerState.state = WSAssetPickerStatePickingAssets;

    return shouldSelectAsset;
}

- (void)assetsTableViewCell:(WSAssetsTableViewCell *)cell didSelectAsset:(BOOL)selected atColumn:(NSUInteger)column
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

    // Calculate the index of the corresponding asset.
    NSUInteger assetIndex = indexPath.row * self.assetsPerRow + column;

    WSAssetWrapper *assetWrapper = [self.fetchedAssets objectAtIndex:assetIndex];
    assetWrapper.selected = selected;

    // Update the state object's selectedAssets.
    [self.assetPickerState changeSelectionState:selected forAsset:assetWrapper.asset];

    // Update navigation bar with selected count and limit variables 
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.assetPickerState.selectionLimit) {
            self.navigationItem.title = [NSString stringWithFormat:@"%@ (%lu/%ld)", [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName], (unsigned long)self.assetPickerState.selectedCount, (long)self.assetPickerState.selectionLimit];
        }
    });

    if (self.assetPickerState.selectedCount == 0) {
        self.navigationItem.rightBarButtonItem.enabled = NO;
    }
    else {
        self.navigationItem.rightBarButtonItem.enabled = YES;
    }

}

Работа, необходимая для ниже, с примером из кода загрузки, который я использовал ранее.

-(void)shareAction:(id)sender {

        //Launch UIDocumentInteractionController for selected images

        documentController =[[UIDocumentInteractionController alloc]init];
        documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath://Code needed here??//]];
        documentController.delegate=self;
        [documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
}

Что было бы наилучшей практикой для этого?

Спасибо.

ОБНОВЛЕНИЕ 8/4:

-(void)shareAction:(id)sender {

        //Launch UIDocumentInteractionController for selected images
    if (self.assetPickerState.selectedCount >= 1) {


        documentController = [[UIDocumentInteractionController alloc] init];
        documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:@"public.image"]];
        [documentController setDelegate:self];
        [documentController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];

    }

}
Returns: Unable to get data for URL: The operation couldn’t be completed. (Cocoa error 260.)

person ChrisOSX    schedule 03.08.2014    source источник


Ответы (1)


Ваш interactionControllerWithURL: не кажется проблемой, но я заметил, что -presentOpenInMenuFromRect: не отображается, если нет приложений, которые могут открыть файл.

Если ваша цель — поделиться файлом, и обычно это не означает открыть файл в обычном смысле, вместо:
-presentOpenInMenuFromRect:inView:animated:
используйте
-presentOptionsMenuFromRect:inView:animated:

Первый — OpenInMenu, а второй — OptionsMenu.
Незначительную разницу см. в моем связанном ответе. или проверьте документ Apple напрямую< / суп>


Пример:

//this seems fine
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];

//do this
[documentController presentOptionsMenuFromRect:CGRectZero 
                                        inView:self.view
                                      animated:YES];

Кроме того..., непосредственно перед тем, как представить documentInteractionController, рекомендуется указать файл UTI, чтобы documentInteractionController мог заполнить себя соответствующими параметрами, которые можно выполнить, и списком всех приложений, которые могут обрабатывать этот файл:

Пример:

//assuming the file is a PDF
[documentController setUTI:@"com.adobe.pdf"];

//or... same thing but a more standardized way would be
[documentController setUTI:(NSString *)kUTTypePDF];
//but for this second style you'll need to add the `MobileCoreServices` framework
//to your project bundle and specify the following in your .h or .m
//#import <MobileCoreServices/MobileCoreServices.h>

Дополнительно: Справочник по унифицированным идентификаторам типов Apple

person staticVoidMan    schedule 04.08.2014
comment
Я попробую, когда вернусь домой. Но дело в том, что это не конкретный файл. Это выбранный актив, который выбирается. То есть изображения из библиотеки охоти, которые вы помогли мне в моем последнем вопросе. - person ChrisOSX; 05.08.2014
comment
@ChrisOSX: конечно, никаких проблем. в любом случае... для изображений вместо UTI можно использовать @"public.image". Кроме того, для ясности NSLog переменную path укажите в своем вопросе. - person staticVoidMan; 05.08.2014
comment
Я получаю сообщение об ошибке: Операция не может быть завершена. (Ошибка какао 260.) когда я использую обновленный код, показанный в вопросе. - person ChrisOSX; 05.08.2014
comment
@ChrisOSX: хороший знак, но теперь URL неверен. у вас есть [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:@"public.image"]];, но вам нужно [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:[NSURL fileURLWithPath:path]]]; - person staticVoidMan; 05.08.2014
comment
@ChrisOSX : Примечание: @"public.image" — это UTI, а не URL. Надеюсь, я не запутал вас зря. - person staticVoidMan; 05.08.2014
comment
Нет, вы меня не смутили :) Единственная запутанная часть сейчас — это попытка определить путь к изображениям в библиотеке фотографий. - person ChrisOSX; 05.08.2014
comment
@ChrisOSX: хм... хорошо, тогда... NSLog path после path = [path stringByAppendingPathComponent:fileName]; и добавьте строку пути к своему вопросу. - person staticVoidMan; 05.08.2014