LoginSignup
3

More than 1 year has passed since last update.

【SwiftUI】シェアを実装する際に気を付ける事

Last updated at Posted at 2022-05-11

はじめに

SwiftUIでシェア機能を実装する際はUIActivityViewControllerを使用します。
ここにかなり深い落とし穴があるので落ちないように気をつけましょう。
私は落っこちて原因に気づかず長い間、クラッシュを生み出していました笑
みなさんはそうならない様に気をつけましょう。

結論

iPadで普通にUIActivityViewControllerを使うとクラッシュします

パターン1(おすすめ)

import SwiftUI

struct ContentView: View {
    @State var ShowSharePopover: Bool = false
    var body: some View {
        Button("シェア") {
            Share()
        }
        .popover(isPresented: $ShowSharePopover) {
            ShareView()
        }
    }
    // iPhone: ハーフモーダル
    // iPad: ポップアップ
    func Share() {
        if UIDevice.current.userInterfaceIdiom == .pad {
            ShowSharePopover = true
        } else {
            let link = URL(string: "https://qiita.com/SNQ-2001/items/86646b661ccc4a7a9034")!
            let activityViewController = UIActivityViewController(activityItems: [link], applicationActivities: nil)
            let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene
            let viewController = scene?.keyWindow?.rootViewController
            viewController?.present(activityViewController, animated: true, completion: nil)
        }
    }
}

struct ShareView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let link = URL(string: "https://qiita.com/SNQ-2001/items/86646b661ccc4a7a9034")!
        let activityViewController = UIActivityViewController( activityItems: [link], applicationActivities: nil)
        return activityViewController
    }
    func updateUIViewController(_ vc: UIActivityViewController, context: Context) {
    }
}
iPhone iPad
IMG_0243.PNG IMG_2470.PNG

パターン2

import SwiftUI

struct ContentView: View {
    @State var ShowShareSheet: Bool = false
    var body: some View {
        Button("シェア") {
            share()
        }
        .sheet(isPresented: $ShowShareSheet) {
            ShareView()
        }
    }
    // iPhone: ハーフモーダル
    // iPad: 中央ポップアップ
    func share() {
        if UIDevice.current.userInterfaceIdiom == .pad {
            ShowShareSheet = true
        } else {
            let link = URL(string: "https://qiita.com/SNQ-2001/items/86646b661ccc4a7a9034")!
            let activityViewController = UIActivityViewController(activityItems: [link], applicationActivities: nil)
            let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene
            let viewController = scene?.keyWindow?.rootViewController
            viewController?.present(activityViewController, animated: true, completion: nil)
        }
    }
}

struct ShareView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let link = URL(string: "https://qiita.com/SNQ-2001/items/86646b661ccc4a7a9034")!
        let activityViewController = UIActivityViewController( activityItems: [link], applicationActivities: nil)
        return activityViewController
    }
    func updateUIViewController(_ vc: UIActivityViewController, context: Context) {
    }
}
iPhone iPad
IMG_0244.PNG IMG_2468.PNG

パターン3(使用してはいけない)

import SwiftUI

struct ContentView: View {
    var body: some View {
        Button("シェア") {
            share()
        }
    }
    // iPhone: ハーフモーダル
    // iPad: クラッシュ
    func share() {
        let link = URL(string: "https://qiita.com/SNQ-2001/items/86646b661ccc4a7a9034")!
        let activityViewController = UIActivityViewController(activityItems: [link], applicationActivities: nil)
        let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene
        let viewController = scene?.keyWindow?.rootViewController
        viewController?.present(activityViewController, animated: true, completion: nil)
    }
}
iPhone iPad
IMG_0244.PNG クラッシュ

パターン4

import SwiftUI

struct ContentView: View {
    @State var ShowSharePopover: Bool = false
    var body: some View {
        Button("シェア") {
            Share()
        }
        .popover(isPresented: $ShowSharePopover) {
            ShareView()
        }
    }
    // iPhone: モーダル
    // iPad: ポップアップ
    func Share() {
        ShowSharePopover = true
    }
}

struct ShareView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let link = URL(string: "https://qiita.com/SNQ-2001/items/86646b661ccc4a7a9034")!
        let activityViewController = UIActivityViewController( activityItems: [link], applicationActivities: nil)
        return activityViewController
    }
    func updateUIViewController(_ vc: UIActivityViewController, context: Context) {
    }
}
iPhone iPad
IMG_0245.PNG IMG_2470.PNG

パターン5

import SwiftUI

struct ContentView: View {
    @State var ShowShareSheet: Bool = false
    var body: some View {
        Button("シェア") {
            Share()
        }
        .sheet(isPresented: $ShowShareSheet) {
            ShareView()
        }
    }
    // iPhone: モーダル
    // iPad: 中央ポップアップ
    func Share() {
        ShowShareSheet = true
    }
}

struct ShareView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let link = URL(string: "https://qiita.com/SNQ-2001/items/86646b661ccc4a7a9034")!
        let activityViewController = UIActivityViewController( activityItems: [link], applicationActivities: nil)
        return activityViewController
    }
    func updateUIViewController(_ vc: UIActivityViewController, context: Context) {
    }
}
iPhone iPad
IMG_0245.PNG IMG_2468.PNG

おわり

今回作成したプロジェクトを置いとくので参考にしてください。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3