WWDC Quick Look 💓 By SwiftGGTeam
Evolve your document launch experience

Evolve your document launch experience

元の動画を見る

ハイライト

iOS 18 はドキュメント系 app に新しい起動画面を提供。DocumentGroupLaunchScene で背景、装飾 view、テンプレート作成ボタンをカスタマイズ可能——iOS 18 SDK で再コンパイルするだけでゼロコードで新デザインを取得。

主要内容

ドキュメント系 app には長年、起動時の尷尬がありました:ユーザーが見るのはシステム標準のドキュメントブラウザ——ブランド感のない冷たいファイル一覧。あなたの app が執筆ツール、キャンバス、コードエディタであっても、開いた瞬間はすべてのドキュメント app と同じに見えます。

iOS 18 が答えを出しました。iOS 18 SDK で再コンパイルするだけで、SwiftUI の DocumentGroup と UIKit の UIDocumentViewController が自動的に新起動画面を表示——中央の app 名、目立つ作成ボタン、内蔵ドキュメントブラウザ、すべてシステム提供で新コード不要。

これは起点に過ぎません。Apple は同時に DocumentGroupLaunchScene API を公開し、背景画像の差し替え、装飾 view の追加、ボタン文言のカスタマイズ、テンプレートからのドキュメント作成まで可能に。Swift Playgrounds は既にこの API で Byte キャラクターを起動画面に配置——初回起動から app の個性を伝えられます。

詳細

SwiftUI:ゼロコードアップグレード + 段階的カスタマイズ

最も基本的な SwiftUI ドキュメント app 構造(02:38):

@main
struct WritingApp: App {
    var body: some Scene {
        DocumentGroup(newDocument: { StoryDocument() }) { file in
            StoryView(document: $file.document)
        }
    }
}

キーポイント:

  • DocumentGroup はドキュメントタイプと編集 view を同時に宣言
  • iOS 18 SDK でコンパイル後、コード変更なしで app 起動時に新 launch 画面を自動表示

起動画面をカスタマイズするには App body に DocumentGroupLaunchScene を追加(04:38):

DocumentGroup(
    newDocument: { StoryDocument() }
) { file in
    StoryView(document: $file.document)
}

DocumentGroupLaunchScene {
    NewDocumentButton("Start Writing")
} background: {
    Image(.pinkJungle)
        .resizable()
        .aspectRatio(contentMode: .fill)
}

キーポイント:

  • DocumentGroupLaunchSceneDocumentGroup と並列宣言
  • NewDocumentButton("Start Writing") でデフォルト “Create Document” ボタン文言を置換
  • background クロージャは任意の SwiftUI View を受け付け、ここでは画像で充填

装飾 view:geometry で配置

装飾要素追加時は overlayAccessoryView クロージャでレイアウト情報を取得(05:53):

DocumentGroupLaunchScene {
    NewDocumentButton("Start Writing")
} background: {
    Image(.pinkJungle)
        .resizable()
        .aspectRatio(contentMode: .fill)
} overlayAccessoryView: { geometry in
    ZStack {
        Image(.robot)
            .position(
                x: geometry.titleViewFrame.minX,
                y: geometry.titleViewFrame.minY
            )
        Image(.plant)
            .position(
                x: geometry.titleViewFrame.maxX,
                y: geometry.titleViewFrame.maxY
            )
    }
}

キーポイント:

  • geometry.titleViewFrame でタイトル view の正確な frame(minX/minY/maxX/maxY
  • 装飾 view はタイトル view の前後に配置し层次感を形成
  • position() または offset() で配置——システムは自動レイアウトしない

テンプレートからドキュメント作成

2 つ目の NewDocumentButton でテンプレート作成をサポート(07:56):

@State private var creationContinuation: CheckedContinuation<StoryDocument?, any Error>?
@State private var isTemplatePickerPresented = false

DocumentGroupLaunchScene {
    NewDocumentButton("Start Writing")
    NewDocumentButton("Choose a Template", for: StoryDocument.self) {
        try await withCheckedThrowingContinuation { continuation in
            self.creationContinuation = continuation
            self.isTemplatePickerPresented = true
        }
    }
    .sheet(isPresented: $isTemplatePickerPresented) {
        TemplatePicker(continuation: $creationContinuation)
    }
}

テンプレートピッカーでユーザーが選択後、continuation でドキュメントを返却(08:07):

struct TemplatePicker: View {
    @Binding var creationContinuation: CheckedContinuation<StoryDocument?, any Error>?

    var body: some View {
        Button("Three Act Structure") {
            creationContinuation?.resume(returning: StoryDocument.threeActStructure())
            creationContinuation = nil
        }
    }
}

キーポイント:

  • NewDocumentButton の async クロージャはドキュメントインスタンスを返す必要あり——SwiftUI が自動保存
  • CheckedContinuation でクロージャをサスペンドし、ユーザーがテンプレート選択完了まで待機
  • 使用後 continuation を nil に——二重 resume を防止

UIKit:launchOptions でカスタマイズ

UIKit app は UIDocumentViewControllerlaunchOptions でカスタマイズ(06:11):

class DocumentViewController: UIDocumentViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // Update the background
        launchOptions.background.image = UIImage(resource: .pinkJungle)

        // Add foreground accessories
        launchOptions.foregroundAccessoryView = ForegroundAccessoryView()
    }
}

UIKit テンプレート作成は UIDocument.CreationIntent08:29):

extension UIDocument.CreationIntent {
    static let template = UIDocument.CreationIntent("template")
}

launchOptions.secondaryAction = LaunchOptions.createDocumentAction(with: .template)
launchOptions.browserViewController.delegate = self

// In delegate method:
func documentBrowser(
    _ browser: UIDocumentBrowserViewController,
    didRequestDocumentCreationWithHandler importHandler: @escaping (URL?, ImportMode) -> Void
) {
    switch browser.activeDocumentCreationIntent {
    case .template:
        presentTemplatePicker(with: importHandler)
    default:
        let newDocumentURL = // ...
        importHandler(newDocumentURL, .copy)
    }
}

キーポイント:

  • UIKit app が新画面を得る前提は UIDocumentViewController が window の rootViewController であること
  • 旧アーキテクチャの UIDocumentBrowserViewController を root にするパターンは調整が必要
  • activeDocumentCreationIntent で異なる作成意図を区別し、テンプレート選択ロジックにルーティング

重要ポイント

  • 何をするか:ドキュメント系 app にブランド化起動画面を追加。なぜ価値があるか:初回起動からプロダクトのトーンを感じさせ、汎用システム UI ではなく。始め方:既存 SwiftUI DocumentGroup プロジェクトを iOS 18 SDK でコンパイルしてゼロコードで新画面取得、背景と装飾を段階的に追加。

  • 何をするか:3〜5 個の厳選ドキュメントテンプレートを提供。なぜ価値があるか:新規ユーザーのドキュメント作成ハードルを下げ、テンプレートに構造とスタイルが含まれ空白ページから始めなくてよい。始め方DocumentGroupLaunchSceneNewDocumentButton("Choose a Template", for:) を追加、CheckedContinuation でテンプレート選択フローを実装。

  • 何をするか:装飾 view で app のストーリーを伝える。なぜ価値があるか:装飾要素が起動画面を機能 UI からブランド接点へ——Swift Playgrounds の Byte キャラクターが成功例。始め方overlayAccessoryViewgeometry.titleViewFrame を使いブランドキャラクターやアイコンを配置、1〜2 要素で十分——過度な装飾は注意散漫に。

  • 何をするか:UIKit ドキュメント app の rootViewController を移行。なぜ価値があるかUIDocumentViewController を root に設定した場合のみ新起動画面を取得——UIDocumentBrowserViewController を root にする旧パターンは不要。始め方UIDocumentBrowserViewController 階層を削除、UIDocumentViewController を root に設定、viewDidLoadlaunchOptions を設定。

関連セッション

コメント

GitHub Issues · utterances