SwiftUI导出或共享文件 [英] SwiftUI exporting or sharing files

查看:368
本文介绍了SwiftUI导出或共享文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有一种通过SwiftUI导出或共享文件的好方法.似乎没有办法包装UIActivityViewController并直接呈现它.我已经使用UIViewControllerRepresentable包装了一个UIActivityViewController,如果我将它呈现在SwiftUI模式中,它将崩溃.

I'm wondering if there is a good way export or share a file through SwiftUI. There doesn't seem to be a way to wrap a UIActivityViewController and present it directly. I've used the UIViewControllerRepresentable to wrap a UIActivityViewController, and it crashes if I, say, present it in a SwiftUI Modal.

我能够创建一个通用的UIViewController,然后从那里调用一个呈现UIActivityViewController的方法,但这很麻烦.

I was able to create a generic UIViewController and then from there call a method that presents the UIActivityViewController, but that's a lot of wrapping.

如果我们想使用SwiftUI从Mac共享,是否可以包装NSSharingServicePicker?

And if we want to share from the Mac using SwiftUI, is there a way to wrap NSSharingServicePicker?

无论如何,如果有人举了一个例子说明他们如何做到这一点,将不胜感激.

Anyway, if anyone has an example of how they're doing this, it would be much appreciated.

推荐答案

删除了所有代码和对UIButton的引用.

Removed all code and references to UIButton.

感谢@Matteo_Pacini对此问题的回答向我们展示这种技术.就像他的回答(和评论)一样,(1)边缘有些粗糙,(2)我不确定这是Apple希望我们使用UIViewControllerRepresentable的方式,我真的希望他们提供更好的SwiftUI( "SwiftierUI"?)在将来的测试版中替换.

Thanks to @Matteo_Pacini for his answer to this question for showing us this technique. As with his answer (and comment), (1) this is rough around the edges and (2) I'm not sure this is how Apple wants us to use UIViewControllerRepresentable and I really hope they provide a better SwiftUI ("SwiftierUI"?) replacement in a future beta.

我在UIKit中做了很多工作,因为我希望它在iPad上看起来不错,在iPad上需要sourceView作为弹出框.真正的技巧是显示(SwiftUI)View,该View在视图层次结构中获取UIActivityViewController并从UIKit触发present.

I put in a lot of work in UIKit because I want this to look good on an iPad, where a sourceView is needed for the popover. The real trick is to display a (SwiftUI) View that gets the UIActivityViewController in the view hierarchy and trigger present from UIKit.

我的需求是展示一个共享的图像,所以事情就朝那个方向发展.假设您有一个图像,该图像存储为@State变量-在我的示例中,该图像称为 vermont.jpg ,是的,事情为此进行了硬编码.

My needs were to present a single image to share, so things are targeted in that direction. Let's say you have an image, stored as a @State variable - in my example the image is called vermont.jpg and yes, things are hard-coded for that.

首先,创建一个类型为UIViewController的UIKit类,以显示共享弹出窗口:

First, create a UIKit class of type `UIViewController to present the share popover:

class ActivityViewController : UIViewController {

    var uiImage:UIImage!

    @objc func shareImage() {
        let vc = UIActivityViewController(activityItems: [uiImage!], applicationActivities: [])
        vc.excludedActivityTypes =  [
            UIActivity.ActivityType.postToWeibo,
            UIActivity.ActivityType.assignToContact,
            UIActivity.ActivityType.addToReadingList,
            UIActivity.ActivityType.postToVimeo,
            UIActivity.ActivityType.postToTencentWeibo
        ]
        present(vc,
                animated: true,
                completion: nil)
        vc.popoverPresentationController?.sourceView = self.view
    }
}

主要是;

  • 您需要一个包装器" UIViewController才能present东西.
  • 您需要var uiImage:UIImage!来设置activityItems.
  • You need a "wrapper" UIViewController to be able to present things.
  • You need var uiImage:UIImage! to set the activityItems.

接下来,将其包装为UIViewControllerRepresentable:

struct SwiftUIActivityViewController : UIViewControllerRepresentable {

    let activityViewController = ActivityViewController()

    func makeUIViewController(context: Context) -> ActivityViewController {
        activityViewController
    }
    func updateUIViewController(_ uiViewController: ActivityViewController, context: Context) {
        //
    }
    func shareImage(uiImage: UIImage) {
        activityViewController.uiImage = uiImage
        activityViewController.shareImage()
    }
}

仅需注意的两件事是

  • 实例化ActivityViewController以将其返回到ContentView
  • 创建shareImage(uiImage:UIImage)来调用它.
  • Instantiating ActivityViewController to return it up to ContentView
  • Creating shareImage(uiImage:UIImage) to call it.

最后,您有ContentView:

struct ContentView : View {
    let activityViewController = SwiftUIActivityViewController()
    @State var uiImage = UIImage(named: "vermont.jpg")
    var body: some View {
        VStack {
            Button(action: {
                self.activityViewController.shareImage(uiImage: self.uiImage!)
            }) {
                ZStack {
                    Image(systemName:"square.and.arrow.up").renderingMode(.original).font(Font.title.weight(.regular))
                    activityViewController
                }
        }.frame(width: 60, height: 60).border(Color.black, width: 2, cornerRadius: 2)
            Divider()
            Image(uiImage: uiImage!)
        }
    }
}

请注意,有一些uiImage的硬编码和(ugh)强制解包,以及@State的不必要使用.这些是存在的,因为我计划在旁边使用`UIImagePickerController将所有这些联系在一起.

Note that there's some hard-coding and (ugh) force-unwrapping of uiImage, along with an unnecessary use of @State. These are there because I plan to use `UIImagePickerController next to tie this all together.

这里的注意事项:

  • 实例化SwiftUIActivityViewController,并将shareImage用作按钮动作.
  • 使用它来是按钮显示.别忘了,即使UIViewControllerRepresentable实际上也只是一个SwiftUI View
  • Instantiating SwiftUIActivityViewController, and using shareImage as the Button action.
  • Using it to also be button display. Don't forget, even a UIViewControllerRepresentable is really just considered a SwiftUI View!

将图像的名称更改为您在项目中拥有的图像,这应该可以工作.您将获得一个居中的60x60按钮,其下方带有图片.

Change the name of the image to one you have in your project, and this should work. You'll get a centered 60x60 button with the image below it.

这篇关于SwiftUI导出或共享文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆