68
62

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

たった数行のコードで作成できる iOS 15 の新たな SwiftUI の機能

Last updated at Posted at 2021-08-04
  • タスクを優先順位付きで作成し、タスクを実行し、タスクをキャンセルします。
  • ユーザーが「集中モード」をオンにしたかどうかを把握する
  • 位置情報ボタン
  • (SwiftUI) SwiftUIを利用してリモート画像を読み込む
  • (SwiftUI) Listリストの検索機能
  • (SwiftUI) リストセパレータを隠す
  • (SwiftUI) リストにPull to Refresh(引っ張って更新)機能を追加
  • (SwiftUI) テキストフィールドのフォーカスを外す
  • (SwiftUI) リストセルにスワイプアクションを追加する
  • (SwiftUI) テキストビューでマークダウンを使用する
  • (SwiftUI) 画面が表示されたらタスクを実行します
  • (SwiftUI) タブビューにバッジ(未読メッセージカウンター)を追加

この記事は developer.apple.com 上で公開されている文書に基づいて書かれました。スクリーンショットは後ほどこちらに追加します。

iOS 14の新機能に関して私が書いた別の記事もお読みいただけます。
たった数行のコードで作成できる iOS 14 の新たなフレームワークの機能

タスクを優先順位付きで作成し、タスクを実行し、タスクをキャンセルします。

このコードはタスクを非同期 (asynchronously) で実行します。

let task = Task(priority: .userInitiated) {
    Server.fetchCatNames { catNames in
        print(catNames)
    }
}

ユーザーが「集中モード」をオンにしたかどうかを把握する

フォーカスモードはiOS15の新機能です。
アプリは、ユーザーが邪魔されたくないかどうかを確認することができます。

まず、Communication Notifications権利を登録する必要があります。

次に、ユーザーの「集中モード」にアクセスが必要な理由を説明するNSFocusStatusUsageDescriptionキーの値を登録します。

以下のコードを使ってアクセス権をリクエストします。

// import Intents
let permissionNotDetermined = (INFocusStatusCenter.default.authorizationStatus == .notDetermined)
if permissionNotDetermined {
    INFocusStatusCenter.default.requestAuthorization { status in
        print(status)
    }
}

ユーザーの集中モードの状態を確認するには、次のコードを使います。

let isAccessAuthorized = (INFocusStatusCenter.default.authorizationStatus == .authorized)
if let isFocused = INFocusStatusCenter.default.focusStatus.isFocused,
   isAccessAuthorized {
    print(isFocused)
}

SwiftUIの位置情報ボタン

ユーザーの位置情報をリクエストしたい場合、その旨を示すボタンを表示することができます。

このボタンには、開発者にかわって実際に位置情報の許可をリクエストする機能はありません。
プリセットスタイルが適用された、単なる普通のボタンです。
ユーザーの位置情報をリクエストして取得するためのロジックの実装は、開発者に委ねられています。

// import CoreLocation
// import CoreLocationUI
LocationButton(.currentLocation) {
    print("Location requested.")
}
.cornerRadius(15)
.symbolVariant(.fill)
.foregroundColor(.white)

ボタンに表示するラベルは、さまざまなものから選ぶことができます:

LocationButton(.currentLocation)
LocationButton(.sendCurrentLocation)
LocationButton(.sendMyCurrentLocation)
LocationButton(.shareCurrentLocation)
LocationButton(.shareMyCurrentLocation)

UIKitフレームワークの位置情報要求ボタンCLLocationButtonについてはこちらの記事をご覧ください。
Apple Developer Documentation

SwiftUIを利用してリモート画像を読み込む

リモート画像を非同期で素早く読み込むことができます。

AsyncImage(url: URL(string: "https://via.placeholder.com/350x150")!)

画像UIオブジェクトやエラーメッセージを取得し、画像をダウンロードしている最中にロード画面を表示することもできます。

AsyncImage(url: URL(string: "https://via.placeholder.com/350x150")!, scale: 1.0) { phase in
    if let image = phase.image {
        image
    } else if let error = phase.error {
        Text(error.localizedDescription)
    } else {
        ProgressView()
    }
}

SwiftUIのリストに関する新機能

Listに対して.searchableを使用すれば検索ボックスを表示できます。

struct ContentView: View {
    
    @State var searchTextEntered: String = ""
    var allCatNames = ["ムギ", "ソラ", "リン"]
    
    var body: some View {
        NavigationView {
            Form {
                List {
                    ForEach(allCatNames, id: \.self) { catName in
                        Text(catName)
                    }
                }
                .searchable(text: $searchTextEntered)
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
    
    var searchResults: [String] {
        if searchTextEntered.isEmpty {
            return allCatNames
        } else {
            return allCatNames.filter { catName in
                return catName.contains(searchTextEntered)
            }
        }
    }
    
}

また、次のコードを使用して検索候補を表示することもできます。

.searchable(text: <#T##Binding<String>#>, prompt: <#T##LocalizedStringKey#>, suggestions: <#T##() -> View#>)

.listRowSeparator(.hidden)を使って、リストビューの改行コードを非表示にすることができます。

List {
    ForEach(allCatNames, id: \.self) { catName in
        Text(catName)
            .listRowSeparator(.hidden)
    }
}

リストの更新メカニズムを提供することもできます

SwiftUIリストにPull to Refresh(引っ張って更新)機能を追加できます。
ローディングインジケーターは、ユーザーがプルダウンして更新すると表示され、コードが完了すると非表示になります。

List {
    ForEach(allCatNames, id: \.self) { catName in
        Text(catName)
    }
}
.refreshable {
    Server.fetchCatNames { catNames in
        self.allCatNames = catNames
    }
}

リストセルにスワイプアクションを追加する

ユーザーが行を左または右にスワイプすることで、特定のアクションを行えるようにすることができます。

Form {
    List {
        ForEach(allCats, id: \.self) { cat in
            Text(cat)
                .swipeActions(edge: .leading) {
                    Button {
                        print("pinned")
                    } label: {
                        Image(systemName: "bookmark")
                    }
                    .tint(.blue)
                }
        }
    }
}

SwiftUIのテキストビューでマークダウンを使用する

これでSwiftUIでマークダウンを使用できます

Text("You can **now** type *in* markdown. You can put [links](https://example.com) here, or some `code`.")

テキストフィールドのフォーカスを外す

アクティブなテキストフィールドにあるキーボードは、(TextFieldの)変数FocusStateとプロパティ.focusedを使って閉じることができます

(下の例を参照してください)

テキストフィールドにキーボードツールバーを加えましょう

テキストフィールドの動作中、キーボード上方にツールバーを表示させることができます。

struct ContentView: View {
    
    @State var catNameEntered: String = ""
    @FocusState var isCatNameFieldFocused: Bool
    
    var body: some View {
        Form {
            TextField("Cat name", text: $catNameEntered)
                .focused($isCatNameFieldFocused)
                .toolbar {
                    ToolbarItemGroup(placement: .keyboard) {
                        HStack {
                            Button("Clear textfield") {
                                self.catNameEntered = ""
                            }
                            Spacer()
                            Button("Done") {
                                self.isCatNameFieldFocused = false
                            }
                        }
                    }
                }
        }
    }
    
}

SwiftUI画面が表示されたらタスクを実行します

画面が表示されたらタスクを実行することができます。
これを利用すれば遠隔サーバからデータを取り込めます。

var body: some View {
    Form {
        List(allCatNames, id: \.self) { catName in
            Text(catName)
        }
    }
    .task {
        Server.fetchCatNames { catNames in
            self.allCatNames = catNames
        }
    }
}

ユーザーがキーボードの送信ボタンをクリックしたことを知る

ユーザーがキーボードの送信ボタンをクリックしたことを知るために、.onSubmitFormに使用することができます。

struct ContentView: View {
    
    @State var newCatNameField: String = ""
    @State var newCatColorField: String = ""
    
    var body: some View {
        Form {
            TextField("Cat name", text: $newCatNameField)
            TextField("Cat color", text: $newCatColorField)
        }
        .onSubmit {
            print("onSubmit \(newCatNameField) \(newCatColorField)")
        }
    }
    
}

SwiftUIのタブビューにバッジ(未読メッセージカウンター)を追加

タブビューのタブにバッジを追加することができます(例えば、チャットタブでは、未読メッセージ数のバッジを表示することができます)。

TabView {
    
    Form {
        Text("Tab 1")
    }
    .tabItem({
        Label("Tab 1", systemImage: "book")
    })
    .badge(10)
    
    Form {
        Text("Tab 2")
    }
    .tabItem {
        Label("Tab 2", systemImage: "calendar")
    }
    .badge(1)
    
}

Time-Sensitive(一刻を争う)notifications 通知

通知を緊急のものとしてマークすることができます。その場合、ユーザーがフォーカスモードをオンにしていても、画面上に通知が表示されます。

アプリ資格付与ファイルにCommunication NotificationPush NotificationsTime Sensitive Notifications を追加する必要があります。

これら2つのページをチェックすることができます:

Apple Developer Documentation

Apple Developer Documentation


:sparkles: :sparkles: :sparkles:

:relaxed: Twitter ツイッター @MszPro

私の公開されているQiita記事をカテゴリー別にご覧いただけます。

68
62
0

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
68
62

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?