iOS UIActivityViewController 使用 UIActivityItemProvider "forgets"项

标签 ios objective-c uiactivityviewcontroller

我有一个更大的应用程序,应该能够共享多个图像。 我使用 UIActivityViewController 和 UIActivityItemProvider 实现了这个以异步使用项目(这样我一次只需要准备一个图像,而不必一次用所有图像填充内存来共享它们)。

Apple Airdrop 示例“启发”了我: AirdropSample download

然而,当使用我的应用分享时,例如9 张图像(到相机胶卷 ==“保存 9 张图像”)只有 4 到 7 张图像最终出现在相机胶卷中,没有任何错误消息。 如果我一遍又一遍地重复它,有时我会得到 5 张图像或 6 张看似随机的图像。

我不能在这里发布我的应用程序,但我修改了上面的示例,它也会随机“失败”将所有图像传送到相机胶卷...

如果您下载上面的示例并用这些替换 4 个文件,则会显示问题:

APLAsyncImageViewController.h:

#import <UIKit/UIKit.h>
#import "APLAsyncImageActivityItemProvider.h"

@interface APLAsyncImageViewController : UIViewController
@end

APLAsyncImageViewController.m:

#import "APLAsyncImageViewController.h"
#import "APLProgressAlertViewController.h"

NSString * const kProgressAlertViewControllerIdentifier = @"APLProgressAlertViewController";


@interface APLAsyncImageViewController ()

@property (strong, nonatomic) UIWindow *alertWindow;
@property (strong, nonatomic) APLProgressAlertViewController *alertViewController;
@property (strong, nonatomic) UIPopoverController *activityPopover;

@property (weak, nonatomic) IBOutlet UIButton *shareImageButton;

- (IBAction)openActivitySheet:(id)sender;

@end


@implementation APLAsyncImageViewController


- (IBAction)openActivitySheet:(id)sender
{
    NSMutableArray *itemArray = [[NSMutableArray alloc] init];
    for( int i = 0; i < 9;i++)
    {
        APLAsyncImageActivityItemProvider *aiImageItemProvider = [[APLAsyncImageActivityItemProvider alloc] init];
        [itemArray addObject: aiImageItemProvider];
    }

    //Create an activity view controller with the activity provider item. UIActivityItemProvider (AsyncImageActivityItemProvider's superclass) conforms to the UIActivityItemSource protocol
    UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:itemArray applicationActivities:nil];

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        //iPhone, present activity view controller as is
        [self presentViewController:activityViewController animated:YES completion:nil];
    }
    else
    {
        //iPad, present the view controller inside a popover
        if (![self.activityPopover isPopoverVisible]) {
            self.activityPopover = [[UIPopoverController alloc] initWithContentViewController:activityViewController];
            [self.activityPopover presentPopoverFromRect:[self.shareImageButton frame] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
        }
        else
        {
            //Dismiss if the button is tapped while pop over is visible
            [self.activityPopover dismissPopoverAnimated:YES];
        }
    }
}
@end

APLAsyncImageActivityItemProvider.h:

#import <UIKit/UIKit.h>
@interface APLAsyncImageActivityItemProvider : UIActivityItemProvider
@end

APLAsyncImageActivityItemProvider.m:

#import "APLAsyncImageActivityItemProvider.h"
#import "UIImage+Resize.h"

@implementation APLAsyncImageActivityItemProvider


- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
    return [[UIImage alloc] init];
}

- (id)item
{
    UIImage *image = [UIImage imageNamed:@"Flower.png"];

    //CGSize imageSize;
    //imageSize.height = 1000;
    //imageSize.width = 1000;
    //image = [UIImage imageWithImage:image scaledToFitToSize:imageSize];

    return image;
}

- (UIImage *)activityViewController:(UIActivityViewController *)activityViewController thumbnailImageForActivityType:(NSString *)activityType suggestedSize:(CGSize)size
{
    //The filtered image is the image to display on the other side.
    return [[UIImage alloc] init];
}

@end

如果您像这样执行示例(使用菜单项“预处理后发送图像”,按“分享”按钮),它通常或大部分无法将所有 9 张图像传送到相机胶卷。

如果您取消注释“APLAsyncImageActivityItemProvider.m”中基本上只是缩放输出图像的 4 行,那么它将始终有效。

你能告诉我为什么吗?我觉得如果我知道那个谜语的答案,我也可以修复我的应用程序。

谢谢,

尼尔斯

最佳答案

这个问题的原因很简单。

应用程序可用的写入器线程数量有限,因此同时写入过多图像可能会因“写入忙”错误而失败。您可以通过尝试使用 UIImageWriteToSavedPhotosAlbum(或相应的 Assets /照片框架对应项)手动写入这些图像来验证这一点。 因此,调整图像大小只是隐藏了真正的问题,因为写入较小的图像花费的时间较少。

问题可以通过限制编写器的数量和/或在出错时重试来解决。 另请注意 -[UIActivityItemProvider item] 是一个阻塞调用,但没有开箱即用的同步方式写入画廊。这可以通过 dispatch_semaphore_wait 、 NSCondition 等来处理。 或者,如果您正在使用 ReactiveCocoa,只需调用 waitUntilCompleted。

关于iOS UIActivityViewController 使用 UIActivityItemProvider "forgets"项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25874568/

相关文章:

objective-c - RestKit 对象映射与奇怪的 JSON

ios - 如何将多个数组加载到 UITableView 中?

ios - UIImage 在 UIScrollView 上缩放时 UIButton 的位置

objective-c - 使用 XCode 3 对 iPhone 静态库进行单元测试

objective-c - 如何在 Objective-C/Xcode/iOS 中的 .lib 文件中隐藏 url

ios - 为 Facebook Messenger iPhone App 实现 UIActivity 子类?

ios - Unity iOS 项目 'FBSDKShareKit/FBSDKShareKit.h' 找不到文件

ios - 如何将 TabBar 图像添加到每个选项卡?在 XCode 8.1 上

ios - UIActivityViewController - 仅为某些事件附加 URL

ios - 确定使用了哪个共享扩展