能登 要

札幌在住のiOSアプリ開発者。SwiftUI により分割されたデバイス間を縦横にやりとりできる考え方に転換しています。

iOSアプリ開発者。2009年のiPhoneアプリ開発開始時期から活動。開発言語のアップデートの中でSwiftUIおよび周辺技術に着目中。

初手で迷わないCoreData有効 Life Cycle SwiftUI App テンプレート(Xcode12.2 later) - iOS Application Develop

端的に云うと

CoreData有効のテンプレートは初手コード修正(Xcode12.2対応版)。SiwftUIベースのアプリを作ろうとしたところ白画面が出てきた場合はCoreData有効チェックを疑ってみる。

1) CoreData

CoreDataはローカルストア機能とオブジェクト関係マッピングツールのフレームワークで、iPhone,iPad 上での構造化データの保存や、検索に関して十分な性能を持つ。

2) CloudKit (iOS8〜)

CloudKitはiCloud基盤としたバックエンド機能(mBaaS)をアプリ開発者側からアクセスするためのフレームワークで、CloudKitを使うといった場合、データストアを想像する開発者は多い(実際にはデータのストアやロードでプッシュ通知を発行する、BLOBデータ格納。データ共有リンク生成機能なども提供している)。

3) CloudKitの強化 WWDC2019-2020 (iOS13〜)

WWDC2019でCoreDataを通してCloudKitのデータストア機能にアクセス可能となった。WWDC2020ではCloudKitのデータストアをローカルに一時蓄積しCoreDataによる検索を利用できる様になっている。

関連動画

4) 2020年のCoreDataの立ち位置

CoreDataを学ぶ動機は増えている。CoreDataを習得すればローカルはもとよりクラウドベースのストレージを扱うためのハードルが下がる。

クラウドにストレージしていても検索高速化の需要が出てきた場合でも、ローカルにデータを蓄積し検索といった性能向上が期待できる。

CoreDataはSwiftUIに先んじてmultiplatformをうたうframeworkで、SwiftUIでもデータストアの役割を当然の様に担っている。

5) 残念なXcodeのテンプレート(Xcode12.2)

SwiftUIでCoreDataをサポートしているにもかかわらず、SiwftUI AppベースでCoreDataを有効にしたテンプレートは利用者を荒野に何も持たせず叩き出す出来となっている。

Xcode12.2 で新規アプリを以下の条件で作成する(アプリ名は任意)。

  • iOS Appを選択、ウィザード画面に移動。
  • Interface にSwiftUI を選択
  • Life Cycle にSwiftUI Appを選択
  • LanguageにSwiftを選択
  • Use Core Dataにチェック(副項目はチェックなし)
  • Include Testsは未チェク(今回は関係ないため)

作成し、ビルド(⌘+B)を実行するろ白い画面が出てくるだけでないも操作できない。

SwiftUIからアプリ開発を始めようとした初心者がLifeCycleでSwiftUI Appを選択したついでにCoreDataのチェックをつけるだけで動いているのかも分からない画面が出てくることを想像するとAppleは新参開発者の注目集める気はないのかと思ってしまう。

6) Xcodeのテンプレートプロジェクトを修正する。

テンプレートとして期待した見た目になる様にコードを一部修正する。期待した見た目とは、画面上部にタイトルがあり、操作できるボタン(編集、追加)が表示されている状態を示す。

6-1) App派生Structの修正

[アプリ名]App.swift を修正する。NavigationViewでContentViewを囲い、.navigationTitleモデファイヤーでタイトル名を記述する。

//
//  StoreApp.swift
//  Store
//

import SwiftUI

@main
struct StoreApp: App {
    let persistenceController = PersistenceController.shared

    var body: some Scene {
        WindowGroup {
            NavigationView {
                ContentView()
                    .navigationTitle("List")
            }
                .environment(\.managedObjectContext, persistenceController.container.viewContext)
        }
    }
}

6-2) ContentViewの修正

.toolbarの中をToolbarItemGroupで囲む。placementに.navigationBarTrailingを指定する。

//
//  ContentView.swift
//  Store
//

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>

    var body: some View {
        List {
            ForEach(items) { item in
                Text("Item at \(item.timestamp!, formatter: itemFormatter)")
            }
            .onDelete(perform: deleteItems)
        }
        .toolbar {
            ToolbarItemGroup(placement: .navigationBarTrailing) {
                #if os(iOS)
                EditButton()
                #endif

                Button(action: addItem) {
                    Label("Add Item", systemImage: "plus")
                }
            }
        }
    }

    ・・・
}

修正を加えるとタイトルが表示されるほか、追加ボタンで項目追加、編集ボタンをタップすると編集/通常モードへの切り替え、項目をスワイプ(右から左)すると項目削除が可能となる。

CustomCoreDataWithSwiftUI

7)Toolbarについて

SwiftUI 2nd major releaseで追加されたツールバーアイテム(ToolbarItem)を構築するための.toolbarモデファイヤーは配置先の置き場所がない場合は表示されないので注意が必要。今回題材としたテンプレートのようにNavigationViewが用意されていないと画面上に反映されないというケースも発生する。

.toolbarモデファイヤーについては優れたまとめが投稿されているので紹介する。

[SwiftUI] toolbar の使い方 | SmallDeskSoftware

Apple公式のドキュメントは.次期SDKが発表されるとbeta差分を確認できるのでこちらも紹介しておく。

8) まとめ

Xcodeで提供されているテンプレートの条件の組み合わせによっていくつかは不親切なものになっている。SwiftUIのテンプレートに関して言えばSwiftUIの知識次第で少しの修正でテンプレートを動かすことができる。

修正すべき箇所が理解できるかどうかでSwiftUIに対する習得度を測るには良いが多分それはテンプレートの役目ではないし、新参の開発者向けとは言えないソースコードが出力されている。

参考

CloudKit - iCloud - Apple Developer https://developer.apple.com/icloud/cloudkit/