在 UIActivity:activityViewController 期间显示 UIAlertView

Posted

技术标签:

【中文标题】在 UIActivity:activityViewController 期间显示 UIAlertView【英文标题】:Show UIAlertView during UIActivity:activityViewController 【发布时间】:2013-08-07 15:54:22 【问题描述】:

我有一组 UIActivities,我将数据准备为给定格式,然后将其附加到用户可以发送的电子邮件中。我正在使用 UIActivity 的子类,我正在 -(void)activityViewController 中完成所有工作:

- (UIViewController *)activityViewController

    [self.alert show];

    NSString *filename = [NSString stringWithFormat:@"%@.gpx", self.activity.title];
    __block MFMailComposeViewController *mailComposeVC = [[MFMailComposeViewController alloc] init];
    mailComposeVC.mailComposeDelegate = self;
    [mailComposeVC setSubject:[NSString stringWithFormat:@"GPX export for %@ activity", self.activity.title]];
    [mailComposeVC setMessageBody:@"Generated with Slopes" ishtml:NO];

    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^
        CBCFileExporter *exporter = [[CBCFileExporter alloc] init];
        NSData *exportContents = [exporter exportActivity:self.activity inFileFormat:CBCFileExportTypeGPX error:nil];
        [mailComposeVC addAttachmentData:exportContents mimeType:@"application/gpx+xml" fileName:filename];
    );

    [self.alert dismissWithClickedButtonIndex:0 animated:YES];

    return mailComposeVC;

我遇到的具体问题是 UIAlertView 直到 dispatch_sync 完成才真正显示。我意识到 dispatch_sync 可能(?)在等待时阻塞了主线程,但问题是我需要等到附件生成后再从该方法调用返回(MFMailComposeViewController 文档说一旦视图是你就不能添加附件介绍)。

如何在主线程必须等待完成的重要任务必须运行时显示警报视图?

【问题讨论】:

同步请求意味着您必须等到完成...使用异步请求。 @TheTiger 如果我这样做,附件是在 显示邮件 VC 之后生成的,这意味着未添加附件。 (他们在显示 VC 后阻止添加附件) 您应该在块中添加附件,然后在完成后显示邮件编辑器 @TheTiger 不太确定我是否关注你。将其添加到块中会起作用,但使其异步会导致 VC 在块完成之前显示。 UIActivities 的工作方式是你必须返回 UIViewController 以从该方法显示给用户,我不能推迟显示它,直到块完成之后。 【参考方案1】:

鉴于邮件视图控制器明确禁止在邮件撰写视图控制器显示附件后添加附件,您可能需要在这里创建并显示一个带有不确定进度指示器的“插页式”视图控制器,开始在后台导出过程,然后当该过程完成时,创建并使用附件完全填充邮件撰写视图控制器,然后呈现它。

在呈现之前完全填充它的要求意味着不可能有简单的“在后台执行此操作并给我回电”的方法。

【讨论】:

【参考方案2】:

伊克。

为了它的价值,我不得不放弃(在与各种块、performOnThread 等斗争了 4 个小时之后)使用 activityViewController 方法直接返回一个 UI,而是改用 performActivity 方法。 PerformActivity 应该用于无 UI 的活动,但它是唯一可异步兼容的活动。

我必须将我的主 ViewController(显示活动表的那个)设置为 UIActivities 的委托,然后在导出准备好后用消息 VC 调用我的委托:

- (void)performActivity

    __block UIAlertView *alert = [[UIAlertView alloc] init];
    alert.title = @"Generating Export";
    [alert show];

    //get rid of the activity sheet now - can't present the mail modal if this is active
    [self activityDidFinish:YES];

    __block CBCGPXEmailActivity *weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^
        CBCFileExporter *exporter = [[CBCFileExporter alloc] init];
        NSString *filename = [NSString stringWithFormat:@"%@.gpx", weakSelf.activity.title];
        NSData *exportContents = [exporter exportActivity:weakSelf.activity inFileFormat:CBCFileExportTypeGPX error:nil];

        //dispatch after to make sure there was time to remove the action sheet
        double delayInSeconds = 0.1;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
            MFMailComposeViewController *mailComposeVC = [[MFMailComposeViewController alloc] init];
            [mailComposeVC setSubject:[NSString stringWithFormat:@"GPX export for %@ activity", weakSelf.activity.title]];
            [mailComposeVC setMessageBody:@"Generated with Slopes" isHTML:NO];
            [mailComposeVC addAttachmentData:exportContents mimeType:@"application/gpx+xml" fileName:filename];

            [weakSelf.delegate showMailViewController:mailComposeVC];
            [alert dismissWithClickedButtonIndex:0 animated:YES];
        );
    );

【讨论】:

以上是关于在 UIActivity:activityViewController 期间显示 UIAlertView的主要内容,如果未能解决你的问题,请参考以下文章

秋的潇洒在啥?在啥在啥?

上传的数据在云端的怎么查看,保存在啥位置?

在 React 应用程序中在哪里转换数据 - 在 Express 中还是在前端使用 React?

存储在 plist 中的数据在模拟器中有效,但在设备中无效

如何在保存在 Mongoose (ExpressJS) 之前在模型中格式化数据

如何在保存在 Mongoose (ExpressJS) 之前在模型中格式化数据