SwiftUI экспорт или обмен файлами - PullRequest
1 голос
/ 29 июня 2019

Мне интересно, есть ли хороший способ экспортировать или поделиться файлом через SwiftUI.Кажется, нет способа обернуть UIActivityViewController и представить его напрямую.Я использовал UIViewControllerRepresentable, чтобы обернуть UIActivityViewController, и он вылетает, если я, скажем, представляю его в модале SwiftUI.

Я смог создать универсальный UIViewController, а затем вызвать метод, который представляетUIActivityViewController, но это много оберток.

И если мы хотим поделиться с Mac с помощью SwiftUI, есть ли способ обернуть NSSharingServicePicker?

В любом случае, если у кого-нибудь есть пример того, какони делают это, это было бы очень ценно.

1 Ответ

0 голосов
/ 01 июля 2019

EDIT: удален весь код и ссылки на UIButton.

Спасибо @Matteo_Pacini за ответ на на этот вопрос за показ нам эту технику. Как и в случае с его ответом (и комментарием), (1) это грубо по краям и (2) я не уверен, что именно так Apple хочет, чтобы мы использовали UIViewControllerRepresentable, и я очень надеюсь, что они обеспечат лучшее SwiftUI ( «SwiftierUI»?) Замена в будущей бете.

Я вложил много работы в UIKit, потому что хочу, чтобы это выглядело хорошо на iPad, где для всплывающего окна требуется sourceView. Реальный трюк заключается в отображении (SwiftUI) View, который получает UIActivityViewController в иерархии представления и запускает present из UIKit.

Мне нужно было представить одно изображение, чтобы поделиться им, поэтому все нацелено в этом направлении. Допустим, у вас есть изображение, хранящееся как переменная @State - в моем примере это изображение называется vermont.jpg , и да, для этого все жестко закодировано.

Сначала создайте класс UIKit типа `UIViewController для представления поповера общего ресурса:

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.

Далее, заверните это в 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) для его вызова.

Наконец, у вас есть 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 вместе с ненужным использованием @State. Это происходит потому, что я планирую использовать `UIImagePickerController рядом, чтобы связать все это вместе.

Примечания здесь:

  • Создание экземпляра SwiftUIActivityViewController и использование shareImage в качестве действия кнопки.
  • С его помощью можно также отображать кнопки. Не забывайте, что даже UIViewControllerRepresentable действительно считается SwiftUI View!

Измените имя изображения на то, которое у вас есть в вашем проекте, и это должно сработать. Вы получите центрированную кнопку 60x60 с изображением под ней.

...