幾乎共享所有代碼

使用 SwiftUI 可共享大部分的代碼。我在編寫 Nomad Drive App 時候使用了此方案,借這次的開發過程,我總結了這篇文章來記錄一下我使用該方案遇到的問題。

歡迎下載體驗我寫的 Nomad Drive 體驗。

https://qoli.notion.site/Nomad-Drive-16f781c9681a487696bceeb7dd2bffbe

index-1.png

文件結構

index-1.png

以我最近開發的 Nomad 為例子

我為此項目建立如下的文件結構

統一的 App 入口設定

//
//  AppView.swift
//  Pikpak macOS
//
//  Created by 黃佁媛 on 2021/12/2.
//

import AVKit
import SwiftUI

struct AppView: View {
    let persistenceController = PersistenceController.shared

    #if !os(iOS)
        @StateObject private var appViewModal = AppViewModal.shared
    #endif

    init() {
        #if os(iOS)
            let audioSession = AVAudioSession.sharedInstance()
            do {
                try audioSession.setCategory(.playback, mode: .moviePlayback)
            } catch {
                print("Setting category to AVAudioSessionCategoryPlayback failed.")
            }
        #endif
    }

    var body: some View {
        #if !os(iOS)
            let messageView = MessageView()
                .environmentObject(appViewModal)
                .transition(AnyTransition.asymmetric(insertion: .move(edge: .leading), removal: .opacity))
                .opacity(appViewModal.show ? 1 : 0)
                .animation(.easeInOut, value: appViewModal.show)
        #endif

        let sidebar = Sidebar()
            .navigationTitle(Bundle.main.appName)

        #if os(tvOS)
            ZStack(alignment: .topLeading) {
                NavigationView {
                    sidebar
                }.navigationViewStyle(.stack)

                messageView
            }
            .environment(\\.managedObjectContext, persistenceController.container.viewContext)
            .sheet(isPresented: $appViewModal.showSheet, onDismiss: nil) {
                appViewModal.showView
            }
        #endif

        #if os(macOS)
            ZStack(alignment: .top) {
                NavigationView {
                    Sidebar()
                        .navigationTitle(Bundle.main.appName)

                    Text("No Sidebar Selection")
                }

                messageView
            }
            .environment(\\.managedObjectContext, persistenceController.container.viewContext)
            .sheet(isPresented: $appViewModal.showSheet, onDismiss: nil) {
                VStack {
                    HStack {
                        Text(appViewModal.sheetTitle)
                            .foregroundColor(.secondary)
                        Spacer()
                        Button {
                            appViewModal.showSheet = false
                        } label: {
                            Image(systemName: "xmark.circle.fill")
                        }.buttonStyle(.plain)
                    }

                    appViewModal.showView
                        .padding([.top, .leading, .trailing])
                }
                .padding()
                .frame(minWidth: 360)
            }
        #endif

        #if os(iOS)
            NavigationView {
                sidebar

                if UIDevice.current.userInterfaceIdiom == .pad {
                    Text("No Sidebar Selection")
                    EmptyView()
                }
            }
            .navigationViewStyle(.stack)
            .environment(\\.managedObjectContext, persistenceController.container.viewContext)
        #endif
    }
}

我在 Shared、App 下建立一個統一的 AppView 入口。

然後,必須把每一個平台的 Targets 都重新指向到這個 AppView 上即可。