使用 SwiftUI 可共享大部分的代碼。我在編寫 Nomad Drive App 時候使用了此方案,借這次的開發過程,我總結了這篇文章來記錄一下我使用該方案遇到的問題。
歡迎下載體驗我寫的 Nomad Drive 體驗。
https://qoli.notion.site/Nomad-Drive-16f781c9681a487696bceeb7dd2bffbe


以我最近開發的 Nomad 為例子
我為此項目建立如下的文件結構
//
// 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 上即可。