Показване на 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 doc директно< /sup>


Пример:

//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
Ще го пробвам, когато се прибера. Но работата е там, че това не е конкретен файл. Това е избраният актив, който се избира. Т.е. изображенията от библиотеката ohoti, за които помогнахте в последния ми въпрос. - person ChrisOSX; 05.08.2014
comment
@ChrisOSX : разбира се, няма проблеми. както и да е... за изображения, можете да използвате @"public.image" като UTI вместо това. Също така, за по-голяма яснота, NSLog променливата path и посочете това във вашия въпрос. - person staticVoidMan; 05.08.2014
comment
Получавам грешката: Операцията не може да бъде завършена. (Грешка в Cocoa 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