我正在使用UIActivityItemProvider
子类来提供自定义数据。但有时获取数据会失败,我不想展示活动(例如消息编写器)。尝试[self cancel]
并return nil;
在item
方法中,但消息编辑器仍然显示(带有空消息)。
2 回答
如果您在从 -(id)item 返回之前关闭 UIActivityViewController,它将不会显示用户选择的活动。
为此,您首先需要在activityViewControllerPlaceholderItem 中获取activityViewController。在 -(id)item 在 dispatch_async 中运行代码以更新进度并在完成/错误时关闭,我正在使用 Promise lib 执行此操作。
在您的 UIActivityItemProvider 的子类中,执行类似于以下示例的操作。
-(id) activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{ self.avc = activityViewController;
return NSURL;
}
-(id)item
{ __block BOOL fileProcDone = NO;
dispatch_async(dispatch_get_main_queue(), ^
{ self.pvc = [[ProgressAlertVC alloc] init];
[self.vc presentViewController:self.pvc animated:YES completion:nil];
[[[[self promiseMakeFile]
progressed:^(float progress)
{ self.pvc.progress = progress;
}]
fulfilled:^(id result)
{ [self.pvc dismissViewControllerAnimated:YES completion:^
{ fileProcDone = YES;
}];
}]
failed:^(NSError *error)
{ [self.pvc dismissViewControllerAnimated:YES completion:^
{ [self.vc dismissViewControllerAnimated:YES completion:^
{ fileProcDone = YES;
}];
}];
}];
});
while (!fileProcDone)
{ [NSThread sleepForTimeInterval:0.1];
};
return NSURL;
}
这将导致来自活动扩展的控制台日志消息,但只要它们正确处理错误,一切都应该没问题。如果您从 -(id)activityViewController: itemForActivityType: 返回 nil,您不会收到控制台错误,但即使您此时关闭 UIActivityViewController,也会获得用户选择的活动。
你只需要调用cancel
UIActivityItemProvider 的方法。由于 UIActivityItemProvider 是一个 NSOperation,调用cancel
将标记操作取消。
此时,您有几个选项可以实际停止长时间运行的任务,具体取决于任务的结构。您可以覆盖该cancel
方法并在那里取消,只要确保也调用[super cancel]
。第二个选项是检查方法isCancelled
内的值item
。
示例项目提供者
import UIKit
import Dispatch
class ItemProvider: UIActivityItemProvider {
override public var item: Any {
let semaphore = DispatchSemaphore(value: 0)
let message = "This will stop the entire share flow until you press OK. It represents a long running task."
let alert = UIAlertController.init(title: "Hello", message: message, preferredStyle: .alert)
let action = UIAlertAction.init(title: "OK", style: .default, handler:
{ action in
semaphore.signal()
})
let cancel = UIAlertAction.init(title: "CANCEL", style: .destructive, handler:
{ [weak self] action in
self?.cancel()
semaphore.signal()
})
alert.addAction(action)
alert.addAction(cancel)
//Truly, some hacking to for the purpose of demonstrating the solution
DispatchQueue.main.async {
UIApplication.shared.delegate?.window??.rootViewController?.presentedViewController!.present(alert, animated: true, completion: nil)
}
// We can block here, because our long running task is in another queue
semaphore.wait()
// Once the item is properly cancelled, it doesn't really matter what you return
return NSURL.init(string: "blah") as Any
}
}
在视图控制器中,像这样启动一个共享活动。
let provider = ItemProvider.init(placeholderItem: "SomeString")
let vc = UIActivityViewController.init(activityItems: [provider], applicationActivities: nil)
self.present(vc, animated: true, completion: nil)