[英]Presenting UIActivityViewController initiating from inside UITableViewCell
[英]Presenting UIActivityViewController from SwiftUI View
我正在尝试从 SwiftUI 视图中呈现UIActivityViewController
(共享表)。 我创建了一个符合UIViewControllerRepresentable
的名为ShareSheet
的视图来配置UIActivityViewController
,但事实证明它并不是那么简单。
struct ShareSheet: UIViewControllerRepresentable {
typealias UIViewControllerType = UIActivityViewController
var sharing: [Any]
func makeUIViewController(context: UIViewControllerRepresentableContext<ShareSheet>) -> UIActivityViewController {
UIActivityViewController(activityItems: sharing, applicationActivities: nil)
}
func updateUIViewController(_ uiViewController: UIActivityViewController, context: UIViewControllerRepresentableContext<ShareSheet>) {
}
}
通过.sheet
天真地这样做会导致以下结果。
.sheet(isPresented: $showShareSheet) {
ShareSheet(sharing: [URL(string: "https://example.com")!])
}
有没有办法像通常呈现的那样呈现这个? 就像覆盖一半屏幕一样?
希望对你有帮助,
struct ShareSheetView: View {
var body: some View {
Button(action: actionSheet) {
Image(systemName: "square.and.arrow.up")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 36, height: 36)
}
}
func actionSheet() {
guard let data = URL(string: "https://www.apple.com") else { return }
let av = UIActivityViewController(activityItems: [data], applicationActivities: nil)
UIApplication.shared.windows.first?.rootViewController?.present(av, animated: true, completion: nil)
}
}
有一个UIModalPresentationStyle
可用于显示某些演示文稿:
case pageSheet
一种部分覆盖基础内容的演示样式。
应用演示风格的方式:
func makeUIViewController(context: UIViewControllerRepresentableContext<ActivityView>) -> UIActivityViewController {
let v = UIActivityViewController(activityItems: sharing, applicationActivities: nil)
v.modalPresentationStyle = .pageSheet
return v
}
可以在此处找到演示文稿列表:
https://developer.apple.com/documentation/uikit/uimodalpresentationstyle
我还没有自己测试过它们,所以如果最终没有像你预期的那样工作,我提前道歉。
或者,您可以查看他们提到第三方库的这个答案,这将允许您以通常呈现的方式创建半模态。
它不漂亮,但您可以像这样直接调用它(考虑到您的应用程序只有 1 个窗口):
UIApplication.shared.windows.first?.rootViewController?.present(activityViewController, animated: true, completion: nil)
如果你得到一些警告blablabla:
警告:尝试呈现……已经在呈现……
你可以做这样的事情来获得最顶部的视图 controller并调用它。
In iOS 14, Swift 5, Xcode 12.5 at least, I was able to accomplish this fairly easily by simply wrapping the UIActivityViewController
in another view controller. 它不需要检查视图层次结构或使用任何 3rd 方库。 唯一骇人听闻的部分是异步呈现视图 controller,这甚至可能没有必要。 有更多 SwiftUI 经验的人可能能够提供改进建议。
import Foundation
import SwiftUI
import UIKit
struct ActivityViewController: UIViewControllerRepresentable {
@Binding var shareURL: URL?
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> some UIViewController {
let containerViewController = UIViewController()
return containerViewController
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
guard let shareURL = shareURL, context.coordinator.presented == false else { return }
context.coordinator.presented = true
let activityViewController = UIActivityViewController(activityItems: [shareURL], applicationActivities: nil)
activityViewController.completionWithItemsHandler = { activity, completed, returnedItems, activityError in
self.shareURL = nil
context.coordinator.presented = false
if completed {
// ...
} else {
// ...
}
}
// Executing this asynchronously might not be necessary but some of my tests
// failed because the view wasn't yet in the view hierarchy on the first pass of updateUIViewController
//
// There might be a better way to test for that condition in the guard statement and execute this
// synchronously if we can be be sure updateUIViewController is invoked at least once after the view is added
DispatchQueue.main.asyncAfter(deadline: .now()) {
uiViewController.present(activityViewController, animated: true)
}
}
class Coordinator: NSObject {
let parent: ActivityViewController
var presented: Bool = false
init(_ parent: ActivityViewController) {
self.parent = parent
}
}
}
struct ContentView: View {
@State var shareURL: URL? = nil
var body: some View {
ZStack {
Button(action: { shareURL = URL(string: "https://apple.com") }) {
Text("Share")
.foregroundColor(.white)
.padding()
}
.background(Color.blue)
if shareURL != nil {
ActivityViewController(shareURL: $shareURL)
}
}
.frame(width: 375, height: 812)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.