iOS UIActivityViewController使用UIActivityItemProvider“忘记”项目

我有一个更大的应用程序,应该可以共享多个图像。 我实现了这个使用UIActivityViewController和UIActivityItemProviderasynchronous使用的项目(所以我只需要一次准备一个图像,而不是一次填充所有的内存来分享)。

我被Apple Airdrop的例子“ AirdropSample”下载为“启发”

然而,当使用我的应用程序共享例如9个图像(相机卷==“保存9个图像”),只有4到7个图像最终在摄像机滚动,没有任何错误消息。 如果我一再重复它,有时我得到5个图像或6看似随机。

我不能在这里发布我的应用程序,但我修改了上述示例的方式,它也将随机“失败”与提供所有图像到相机辊…

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

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 

如果你这样执行样本(使用菜单项“预处理后发送图像”,按“SHARE”button),它将经常或大部分无法将全部9个图像传送到相机胶卷。

如果您取消注释“APLAsyncImageActivityItemProvider.m”中的4行,基本上只是缩放输出图像然后它将一直工作。

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

谢谢,

尼尔斯

这个问题的原因很简单。

由于应用程序可以使用的写入器线程数量有限,因此写入太多的图像可能会由于“写入繁忙”错误而同时失败。 您可以validation通过尝试使用UIImageWriteToSavedPhotosAlbum(或相应的资产/照片框架对应)手动写入这些图像。 所以,调整图像大小隐藏了真正的问题,因为写一个较小的图像需要更less的时间。

问题可以通过限制作者的数量和/或在出现错误的情况下重试来解决。 还要注意的是 – [UIActivityItemProvider item]是一个阻塞调用,但没有同步的方式来写入到画廊开箱即用。 这可以用dispatch_semaphore_wait,NSCondition等来处理。或者,如果你使用ReactiveCocoa,只需调用waitUntilCompleted。

我会去说,创build的[UIImage imageWithImage:image scaledToFitToSize:imageSize]图像是保存到相机胶卷之前的GC,但是我不知道没有代码的情况下该怎么办。 该方法不是一个正常的UIImage方法,一个类别可能?

编辑

用这段代码replace你的for循环代码添加到你的item数组中,然后取消你的resize行的注释,看看是否有效。

 NSMutableArray *itemArray = [[NSMutableArray alloc] init]; for( int i = 0; i < 9;i++) { UIImage *aiImage = [[[APLAsyncImageActivityItemProvider alloc] init] image]; [itemArray addObject:aiImage]; }