[SwiftUI] presentationMode は iOS15/macOS12 で deprecated になりました

SwiftUI2021

EnvironmentValue の PresentationMode が iOS15/macOS12 で deprecated になるので、説明します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Monterery beta 5
  • Xcode 13 beta5
  • iOS 15

PresentationMode

EnvironmentValue として用意されていた変数です。

isPresented 等で表示を制御する変数を渡せないケースなどでは、この PresentationMode を使うことで ビューを閉じることができました。

PresentationMode を使った例(@iOS14/macOS11)


//
//  ContentView.swift
//
//  Created by : Tomoaki Yagishita on 2021/09/26
//  © 2021  SmallDeskSoftware
//

import SwiftUI

struct ContentView: View {
    @State private var showSheet = false
    var body: some View {
        Text("Hello, world!")
            .onTapGesture {
                showSheet.toggle()
            }
            .padding()
            // (1)
            .sheet(isPresented: $showSheet) {
                // (2)
                Sheet()
            }
    }
}

struct Sheet: View {
    // (3)
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        Text("Sheet")
            .onTapGesture {
                // (4)
                presentationMode.wrappedValue.dismiss()
            }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
コード解説
  1. showSheet 変数で制御して .sheet modifier を使って、sheet を表示させています
  2. Sheet には、変数を渡していません
  3. Environment 変数の presentationMode を参照します
  4. Environment で wrap されている内部の変数を使って、閉じることができます

Environment は読み出し専用なので、wrappedValue を使って、その内部変数を直接使用するというすこし変則的な使い方ですが、この方法でしか閉じることができないケースがあり、それなりの頻度で使っていました。

iOS15/macOS12 で deprecated に

Apple のドキュメントによると、presentationMode は、iOS15/macOS12 では、deprecated 扱いです。

Apple のドキュメントは、こちら

PresentationMode が deprecated になる代わりに、isPresented と dismiss という Environment 変数が提供されます。

# isPresented と dismiss は、もともとは PresentationMode から提供されていたプロパティ/関数です。

isPresented/dismiss 使用例(iOS15/macOS12 以降)

動作はあまり変わりませんが、せっかくなので、isPresented を使って、表示されるテキストを調整しました(が、表示されているときは常に isPresented は true なので、意味はありません)。

コードは、以下のようになります。


//
//  ContentView.swift
//
//  Created by : Tomoaki Yagishita on 2021/09/26
//  © 2021  SmallDeskSoftware
//

import SwiftUI

struct ContentView: View {
    @State private var showSheet = false
    var body: some View {
        Text("Hello, world!")
            .onTapGesture {
                showSheet.toggle()
            }
            .padding()
            // (1)
            .sheet(isPresented: $showSheet) {
                // (2)
                Sheet()
            }
    }
}

struct Sheet: View {
    // (3)
    @Environment(\.isPresented) var isPresented
    // (4)
    @Environment(\.dismiss) var dismiss
    var body: some View {
        // (5)
        Text(isPresented ? "Presenting" : "No-Presenting")
            .onTapGesture {
                // (6)
                dismiss.callAsFunction() 
                // dismiss() とも書けます
            }
    }
}
コード解説
  1. Sheet の表示制御は、変わりません
  2. Sheet を表示するところも変わりません
  3. 表示されているかを確認するには、presentationMode の代わりに、Environment 変数の isPresented を定義します
  4. 閉じるためには、presentationMode の代わりに、Environment 変数の dismiss を定義します。
  5. isPresented は、表示しているかどうか を表す Bool 変数です
  6. dismiss は、DismissAction という型で、callAsFunction を使うことで、閉じることができます
MEMO
isPresented の説明には、"A Boolean value that indicates whether the view associated with this environment is currently being presented."と書かれています。

dismiss は isPresented が対象としているもの閉じると説明されています。

動きから想像するに、現在のアクティブな View に対して作用し閉じることができると思えるのですが、"the view associated with this environment" の厳密な意味がわかりませんでした・・・・

まとめ:presentationMode は、deprecated になるので、isPresented/dismiss を使う

presentationMode は、deprecated になるので、isPresented/dismiss を使う
  • Environment 変数 presentationMode は、iOS15/macOS12 で deprecated 指定される
  • Environment 変数 presentationMode は、新しく導入される Environment 変数の isPresented/dismiss に置き換えることができる
  • isPresented は、対象のビューが表示されているかを表す Bool 型変数
  • dimiss は、対象のビューを閉じることできる DismissAction 型

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です