简体   繁体   English

使用 swiftUI 在 iOS 15 中创建共享表

[英]Create a share sheet in iOS 15 with swiftUI

I am trying to create a share sheet to share a Text, it was working fine in iOS 14 but in iOS 15 it tells me that我正在尝试创建一个共享表来共享文本,它在 iOS 14 中运行良好,但在 iOS 15 中它告诉我

"'windows' was deprecated in iOS 15.0: Use UIWindowScene.windows on a relevant window scene instead". “'windows' 在 iOS 15.0 中已弃用:在相关的窗口场景上使用 UIWindowScene.windows”。

how can I make it work on iOS 15 with SwiftUI如何使用 SwiftUI 使其在 iOS 15 上运行

   Button {
    let TextoCompartido = "Hola 😀 "
                                    
    let AV = UIActivityViewController(activityItems: [TextoCompartido], applicationActivities: nil)
        
UIApplication.shared.windows.first?.rootViewController?.present(AV, animated: true, completion: nil)
    
    }

I think you would be best served using SwiftUI APIs directly.我认为最好直接使用 SwiftUI API。 Generally, I would follow these steps.一般来说,我会遵循这些步骤。

  1. Create SwiftUI View named ActivityView that adheres to UIViewControllerRepresentable .创建名为ActivityView的 SwiftUI View ,它遵循UIViewControllerRepresentable This will allow you to bring UIActivityViewController to SwiftUI.这将允许您将UIActivityViewController带到 SwiftUI。
  2. Create an Identifiable struct to contain the text you'd like to display in the ActivityView .创建一个Identifiable结构以包含您希望在ActivityView中显示的文本。 Making this type will allow you to use the SwiftUI sheet API and leverage SwiftUI state to tell the app when a new ActivityView to be shown.制作此类型将允许您使用 SwiftUI 表单 API并利用 SwiftUI 状态来告诉应用程序何时显示新的ActivityView
  3. Create an optional @State variable that will hold on to your Identifiable text construct.创建一个可选的@State变量,该变量将保留您的可Identifiable文本构造。 When this variable changes, the sheet API will perform the callback.当此变量发生变化时,工作表 API将执行回调。
  4. When the button is tapped, update the state of the variable set in step 3.点击按钮时,更新步骤 3 中设置的变量的状态。
  5. Use the sheet API to create an ActivityView which will be presented to your user.使用工作表 API创建将呈现给您的用户的ActivityView

The code below should help get you started.下面的代码应该可以帮助您入门。


import UIKit
import SwiftUI

// 1. Activity View
struct ActivityView: UIViewControllerRepresentable {
    let text: String

    func makeUIViewController(context: UIViewControllerRepresentableContext<ActivityView>) -> UIActivityViewController {
        return UIActivityViewController(activityItems: [text], applicationActivities: nil)
    }

    func updateUIViewController(_ uiViewController: UIActivityViewController, context: UIViewControllerRepresentableContext<ActivityView>) {}
}

// 2. Share Text
struct ShareText: Identifiable {
    let id = UUID()
    let text: String
}

struct ContentView: View {
    // 3. Share Text State
    @State var shareText: ShareText?
    
    var body: some View {
        VStack {
            Button("Show Activity View") {
                // 4. New Identifiable Share Text
                shareText = ShareText(text: "Hola 😀")
            }
            .padding()
        }
        // 5. Sheet to display Share Text
        .sheet(item: $shareText) { shareText in
            ActivityView(text: shareText.text)
        }
    }
}

For the future, iOS 16 will have the ShareLink view which works like this:未来,iOS 16 将拥有ShareLink视图,其工作方式如下:

Gallery(...)
   .toolbar {
      ShareLink(item: image, preview: SharePreview("Birthday Effects")
   }

Source: https://developer.apple.com/videos/play/wwdc2022/10052/来源: https ://developer.apple.com/videos/play/wwdc2022/10052/

Time code offset: 20 minutes 17 seconds时间码偏移:20分17秒

you could try the following using the answer from: How to get rid of message " 'windows' was deprecated in iOS 15.0: Use UIWindowScene.windows on a relevant window scene instead" with AdMob banner?您可以使用来自的答案尝试以下操作: 如何使用 AdMob 横幅摆脱消息“'windows' 在 iOS 15.0 中已弃用:在相关窗口场景上使用 UIWindowScene.windows 代替”?

Note that your code works for me, but the compiler give the deprecation warning.请注意,您的代码对我有用,但编译器会给出弃用警告。

public extension UIApplication {
    func currentUIWindow() -> UIWindow? {
        let connectedScenes = UIApplication.shared.connectedScenes
            .filter({
                $0.activationState == .foregroundActive})
            .compactMap({$0 as? UIWindowScene})
        
        let window = connectedScenes.first?
            .windows
            .first { $0.isKeyWindow }

        return window
        
    }
}

struct ContentView: View {
    let TextoCompartido = "Hola 😀 "
    
    var body: some View {
        Button(action: {
            let AV = UIActivityViewController(activityItems: [TextoCompartido], applicationActivities: nil)
 
 UIApplication.shared.currentUIWindow()?.rootViewController?.present(AV, animated: true, completion: nil)
            
// This works for me, but the compiler give the deprecation warning
// UIApplication.shared.windows.first?.rootViewController?.present(AV, animated: true, completion: nil)
        }) {
            Text("Hola click me")
        }
    }
}

To avoid warning, change the way you retrieve the window scene.为避免警告,请更改检索窗口场景的方式。 Do the following:请执行下列操作:

Button {
   let TextoCompartido = "Hola 😀 "
                                
   let AV = UIActivityViewController(activityItems: [TextoCompartido], applicationActivities: nil)
    
   let scenes = UIApplication.shared.connectedScenes
   let windowScene = scenes.first as? UIWindowScene
    
   windowScene?.keyWindow?.rootViewController?.present(AV, animated: true, completion: nil)

}

Tested in in iOS 15 with SwiftUI使用 SwiftUI 在 iOS 15 中测试

 func shareViaActionSheet() {
        if vedioData.vedioURL != nil {
            let activityVC = UIActivityViewController(activityItems: [vedioData.vedioURL as Any], applicationActivities: nil)
            UIApplication.shared.currentUIWindow()?.rootViewController?.present(activityVC, animated: true, completion: nil)
        }
    }

To avoid iOS 15 method deprecation warning use this extension为避免 iOS 15 方法弃用警告,请使用此扩展

public extension UIApplication {
    func currentUIWindow() -> UIWindow? {
        let connectedScenes = UIApplication.shared.connectedScenes
            .filter { $0.activationState == .foregroundActive }
            .compactMap { $0 as? UIWindowScene }
        
        let window = connectedScenes.first?
            .windows
            .first { $0.isKeyWindow }
        return window
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM