版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2021.01.07 星期四 |
前言
今天翻閱蘋果的API文檔量蕊,發(fā)現(xiàn)多了一個(gè)框架SwiftUI,這里我們就一起來看一下這個(gè)框架哨查。感興趣的看下面幾篇文章。
1. SwiftUI框架詳細(xì)解析 (一) —— 基本概覽(一)
2. SwiftUI框架詳細(xì)解析 (二) —— 基于SwiftUI的閃屏頁(yè)的創(chuàng)建(一)
3. SwiftUI框架詳細(xì)解析 (三) —— 基于SwiftUI的閃屏頁(yè)的創(chuàng)建(二)
4. SwiftUI框架詳細(xì)解析 (四) —— 使用SwiftUI進(jìn)行蘋果登錄(一)
5. SwiftUI框架詳細(xì)解析 (五) —— 使用SwiftUI進(jìn)行蘋果登錄(二)
6. SwiftUI框架詳細(xì)解析 (六) —— 基于SwiftUI的導(dǎo)航的實(shí)現(xiàn)(一)
7. SwiftUI框架詳細(xì)解析 (七) —— 基于SwiftUI的導(dǎo)航的實(shí)現(xiàn)(二)
8. SwiftUI框架詳細(xì)解析 (八) —— 基于SwiftUI的動(dòng)畫的實(shí)現(xiàn)(一)
9. SwiftUI框架詳細(xì)解析 (九) —— 基于SwiftUI的動(dòng)畫的實(shí)現(xiàn)(二)
10. SwiftUI框架詳細(xì)解析 (十) —— 基于SwiftUI構(gòu)建各種自定義圖表(一)
11. SwiftUI框架詳細(xì)解析 (十一) —— 基于SwiftUI構(gòu)建各種自定義圖表(二)
12. SwiftUI框架詳細(xì)解析 (十二) —— 基于SwiftUI創(chuàng)建Mind-Map UI(一)
13. SwiftUI框架詳細(xì)解析 (十三) —— 基于SwiftUI創(chuàng)建Mind-Map UI(二)
14. SwiftUI框架詳細(xì)解析 (十四) —— 基于Firebase Cloud Firestore的SwiftUI iOS程序的持久性添加(一)
15. SwiftUI框架詳細(xì)解析 (十五) —— 基于Firebase Cloud Firestore的SwiftUI iOS程序的持久性添加(二)
16. SwiftUI框架詳細(xì)解析 (十六) —— 基于SwiftUI簡(jiǎn)單App的Dependency Injection應(yīng)用(一)
17. SwiftUI框架詳細(xì)解析 (十七) —— 基于SwiftUI簡(jiǎn)單App的Dependency Injection應(yīng)用(二)
18. SwiftUI框架詳細(xì)解析 (十八) —— Firebase Remote Config教程(一)
19. SwiftUI框架詳細(xì)解析 (十九) —— Firebase Remote Config教程(二)
開始
首先看下主要內(nèi)容:
SwiftUI使創(chuàng)建與iOS文檔交互系統(tǒng)一起使用的基于文檔的應(yīng)用程序比以往更加容易。 在本教程中麦牺,您將學(xué)習(xí)如何創(chuàng)建基于SwiftUI文檔的
meme-maker
應(yīng)用。內(nèi)容來自翻譯鞭缭。
接著看下寫作環(huán)境:
Swift 5, iOS 14, Xcode 12
下面就是正文啦
Documents
是計(jì)算的中心剖膳,基于SwiftUI
文檔的應(yīng)用程序比以往更容易使用iOS文檔交互系統(tǒng)。iOS文檔交互系統(tǒng)基于將您的應(yīng)用程序與Files
應(yīng)用程序的所有出色功能集成在一起岭辣,
在本教程中吱晒,您將使用MemeMaker,該應(yīng)用程序可讓您創(chuàng)建自己的memes
并將其保留為自己的meme
文檔類型易结。
您將了解以下主題:
- 什么是
Uniform Type Identifiers (UTI)
枕荞? - 哪些組件包含
SwiftUI
基于文檔的應(yīng)用程序柜候? - 您如何定義自己的具有唯一擴(kuò)展名的文檔?
- 如何在
iOS / iPadOS
和macOS
上運(yùn)行基于SwiftUI
文檔的應(yīng)用程序躏精?
事不宜遲渣刷,該一起看下了。
打開已有的初始項(xiàng)目矗烛。
構(gòu)建并運(yùn)行辅柴。 這是該應(yīng)用程序的外觀:
點(diǎn)擊右上角的+
按鈕以創(chuàng)建一個(gè)新文檔。 文本編輯器將打開“ Hello瞭吃,world碌嘀!”
。 如圖所示歪架。 將文本更改為SwiftUI rocks!
然后點(diǎn)擊左上角的back button
按鈕關(guān)閉文檔股冗。
注意:在撰寫本文時(shí),存在一些與
SwiftUI
基于文檔的應(yīng)用程序有關(guān)的bug
和蚪。 有時(shí)您會(huì)在導(dǎo)航欄中看不到后退按鈕或添加項(xiàng)目按鈕之類的按鈕止状,因?yàn)樗鼈兡J(rèn)為白色。
切換到Browse
選項(xiàng)卡以查找剛剛創(chuàng)建的文檔攒霹。 該選項(xiàng)卡如下所示:
通過點(diǎn)擊打開新文件怯疤。文本編輯器打開,您可以閱讀輸入的文本催束。
這是創(chuàng)建memes
編輯器的良好起點(diǎn)集峦。您將修改此應(yīng)用程序,以便它與memes
文檔類型一起使用抠刺,而不是處理原始文本塔淤。這是UTI
的作用。
Defining Exported Type Identifiers
用Apple的話Apple’s words來說矫付,Unique Type Identifier or UTI
是“特定文件類型凯沪,數(shù)據(jù)類型,目錄或bundle type
的唯一標(biāo)識(shí)符”买优。例如妨马,JPEG
圖像是一種特殊的文件類型,由UTI
字符串public.jpeg
唯一標(biāo)識(shí)杀赢。同樣烘跺,UTI net.daringfireball.markdown
可以唯一標(biāo)識(shí)以流行的Markdown markup language編寫的文本文件。
UTI
的值是什么脂崔?由于UTI
是唯一的標(biāo)識(shí)符滤淳,因此它們?yōu)槟膽?yīng)用程序提供了一種明確的方式來告知操作系統(tǒng)它可以打開和創(chuàng)建哪種類型的文檔。由于iOS并未附帶對(duì)“meme”
文檔的內(nèi)置支持砌左,因此您需要在應(yīng)用中為Meme
文件添加新的UTI
脖咐。這在Xcode中很簡(jiǎn)單铺敌。
在深入研究代碼之前,您需要對(duì)項(xiàng)目設(shè)置進(jìn)行一些更改屁擅。
在項(xiàng)目設(shè)置中選擇MemeMaker(iOS)target
偿凭,選擇Info
選項(xiàng)卡,然后展開Exported Type Identifiers
部分派歌。
在這里定義文檔的類型和元數(shù)據(jù)弯囊。當(dāng)前,這仍然是為文本文檔設(shè)置的胶果。
進(jìn)行以下更改:
- 將
Description
更改為A meme created with MemeMaker
匾嘱。您可以查看說明,例如在Finder
的信息窗口中早抠。 - 將
Identifier
更改為com.raywenderlich.MemeMaker.meme
霎烙。其他應(yīng)用程序可以使用此標(biāo)識(shí)符來導(dǎo)入您的文檔。 - 將
Conforms
更改為“public.data贝或,public.content”
吼过。這些是UTI
,它們描述了您的UTI
使用的數(shù)據(jù)類型咪奖。用編程的話來說,您可以將它們視為您的UTI
遵循的協(xié)議酱床。您可以使用許多類型羊赵,例如public.data
或public.image
。您可以在Apple’s documentation或Wikipedia中找到所有可用的UTI
的列表扇谣。 - 將
Extension
更改為meme
昧捷。這是.meme
文件擴(kuò)展名,改擴(kuò)展名已添加到使用MemeMaker
創(chuàng)建的文檔中罐寨。
很好靡挥! 現(xiàn)在,您可以使用新擴(kuò)展名.meme
創(chuàng)建文檔了鸯绿。
Using a DocumentGroup
DocumentGroup
是展示用于處理文檔的系統(tǒng)UI的場(chǎng)景跋破。 您可以在上面的屏幕截圖中看到它的外觀。 SwiftUI
使使用文檔瀏覽器變得超級(jí)容易瓶蝴。 只需遵循MemeMakerApp.swift
中的代碼即可:
DocumentGroup(newDocument: MemeMakerDocument()) { file in
ContentView(document: file.$document)
}
DocumentGroup
在處理文檔時(shí)有兩個(gè)初始化程序:init(newDocument:editor :)
和init(viewing:viewer :)
毒返。 第一個(gè)允許您創(chuàng)建新文檔和編輯現(xiàn)有文檔,而第二個(gè)則只能查看文件舷手。 因?yàn)槟獎(jiǎng)?chuàng)建和編輯memes
拧簸,所以入門項(xiàng)目將使用第一個(gè)初始化程序。
初始化程序收到它應(yīng)該顯示的文檔男窟。 在這種情況下盆赤,您將初始化一個(gè)新的空MemeMakerDocument
贾富,將在以后使用。 初始化程序還會(huì)收到一個(gè)用于構(gòu)建文件編輯視圖的閉包牺六。
Working With a File Document
FileDocument
是應(yīng)用可以讀取和寫入設(shè)備的文檔的基本協(xié)議祷安。該協(xié)議包含兩個(gè)靜態(tài)屬性:readContentTypes
和writableContentTypes
。兩者都是UTType
數(shù)組兔乞,分別定義了文檔可以讀取和寫入的類型汇鞭。僅要求readyContentTypes
,因?yàn)?code>writableContentTypes也默認(rèn)為readContentContentTypes
庸追。
FileDocument
還需要帶有FileDocumentReadConfiguration
的初始化程序霍骄。此配置將UTType
形式的文檔類型與包含其內(nèi)容的FileWrapper
捆綁在一起。
最后淡溯,任何符合FileDocument
的類或結(jié)構(gòu)體都需要實(shí)現(xiàn)fileWrapper(configuration :)
读整。寫入文檔時(shí)會(huì)調(diào)用它,它以FileDocumentWriteConfiguration
作為參數(shù)咱娶,類似于讀取配置米间,但用于寫入。
聽起來可能需要做很多工作膘侮,但請(qǐng)放心屈糊。在本教程的這一部分中,您將了解如何使用這兩種配置琼了。
1. Defining Exported UTTypes
打開MemeMakerDocument.swift
逻锐。在文件頂部,您會(huì)在UTType
上找到擴(kuò)展名雕薪,該擴(kuò)展名定義了入門項(xiàng)目正在使用的類型昧诱。
用以下代碼替換此擴(kuò)展名:
extension UTType {
static let memeDocument = UTType(
exportedAs: "com.raywenderlich.MemeMaker.meme")
}
在上面的代碼中,您將memeDocument
定義為新的UTType
所袁,以便可以在下一步中使用它盏档。
仍在MemeMakerDocument.swift
中,找到readableContentTypes
燥爷。 如前所述蜈亩,這定義了應(yīng)用可以讀取和寫入的UTType
列表。 用以下新代碼替換屬性:
static var readableContentTypes: [UTType] { [.memeDocument] }
這會(huì)將您之前創(chuàng)建的新類型設(shè)置為MemeMakerDocument
文檔可以讀取的類型局劲。 由于writableContentTypes
默認(rèn)為readContentContentTypes
勺拣,因此您無需添加它。
2. Creating the Data Model
在繼續(xù)使用MemeMakerDocument
之前鱼填,您需要定義其適用的meme
药有。 在Shared
組中創(chuàng)建一個(gè)名為Meme.swift
的新Swift文件,并選中Targets
中的兩個(gè)復(fù)選框,以便將其同時(shí)包含在iOS
和macOS target
中愤惰。
添加以下代碼:
struct Meme: Codable {
var imageData: Data?
var topText: String
var bottomText: String
}
MemeMaker
會(huì)將Meme
保存到磁盤苇经。 它符合Codable
,因此您可以使用JSONEncoder
和JSONDecoder
將其轉(zhuǎn)換為Data
并返回宦言。 它還包裝了表示一個(gè)Meme
所需的所有信息:兩個(gè)字符串和一個(gè)圖像數(shù)據(jù)扇单。
再次打開MemeMakerDocument.swift
并在類的開頭找到以下代碼:
var text: String
init(text: String = "Hello, world!") {
self.text = text
}
MemeMakerDocument
現(xiàn)在可以保存實(shí)際的Meme
而不是文本。 因此奠旺,將這些行替換為以下代碼:
// 1
var meme: Meme
// 2
init(
imageData: Data? = nil,
topText: String = "Top Text",
bottomText: String = "Bottom Text"
) {
// 3
meme = Meme(
imageData: imageData,
topText: topText,
bottomText: bottomText)
}
上面的代碼就是這樣:
- 1) 這是由
MemeMakerDocument
實(shí)例表示的meme
蜘澜。 - 2) 您為
MemeMakerDocument
定義了一個(gè)初始化程序。 初始化程序接收?qǐng)D像的數(shù)據(jù)以及頂部和底部的文本响疚。 - 3) 最后鄙信,根據(jù)這些參數(shù)初始化一個(gè)新的
Meme
。
此時(shí)忿晕,您將看到代碼中的錯(cuò)誤装诡。 不用擔(dān)心-在保存和加載文件時(shí),還需要進(jìn)行一些其他更改以對(duì)文檔進(jìn)行編碼和解碼践盼。
3. Encoding and Decoding the Document
首先鸦采,對(duì)fileWrapper(configuration :)
進(jìn)行更改。 用以下幾行替換方法主體:
let data = try JSONEncoder().encode(meme)
return .init(regularFileWithContents: data)
這會(huì)將meme
轉(zhuǎn)換為數(shù)據(jù)咕幻,并創(chuàng)建一個(gè)WriteConfiguration
渔伯,系統(tǒng)將其用于將該文檔寫入磁盤。
接下來谅河,將init(configuration :)
的主體替換為以下代碼:
guard let data = configuration.file.regularFileContents else {
throw CocoaError(.fileReadCorruptFile)
}
meme = try JSONDecoder().decode(Meme.self, from: data)
打開現(xiàn)有文檔時(shí)咱旱,應(yīng)用程序?qū)⒄{(diào)用此初始化程序。 您嘗試從給定的ReadConfiguration
中獲取數(shù)據(jù)绷耍,并將其轉(zhuǎn)換為Meme
的實(shí)例。 如果該過程失敗鲜侥,則初始化程序?qū)⒁l(fā)系統(tǒng)要處理的錯(cuò)誤褂始。
現(xiàn)在,您已經(jīng)添加了對(duì)自定義meme
文檔進(jìn)行讀寫的支持描函。 但是崎苗,由于您沒有顯示Meme
編輯器,因此用戶仍然看不到其中任何一個(gè)舀寓。 您將在下一部分中解決該問題胆数。
Providing a Custom Editor
目前,該應(yīng)用程序使用TextEditor
互墓。 基于SwiftUI
文檔的多平臺(tái)應(yīng)用程序的模板從此視圖開始必尼。 用于顯示可編輯和可滾動(dòng)的文本。
TextEditor
不適合創(chuàng)建和編輯模因,因此您將創(chuàng)建自己的視圖來編輯MemeMakerDocument
判莉。
在開始創(chuàng)建新的編輯器視圖之前豆挽,您將刪除舊的視圖。 打開ContentView.swift
并將主體替換為空視圖:
Spacer()
這樣可以確保在構(gòu)建新編輯器時(shí)不會(huì)出現(xiàn)編譯器錯(cuò)誤券盅。
1. Creating the Image Layer
編輯器將包含兩個(gè)子視圖帮哈。 您將在創(chuàng)建實(shí)際的編輯器之前創(chuàng)建它們。
第一個(gè)是ImageLayer
锰镀,它代表圖像娘侍。 在Shared
中創(chuàng)建一個(gè)名為ImageLayer.swift
的新SwiftUI View
文件,并在Targets
中選中MemeMaker(iOS)
和MemeMaker(macOS)
的復(fù)選框泳炉。 用以下內(nèi)容替換文件中的兩個(gè)結(jié)構(gòu):
struct ImageLayer: View {
// 1
@Binding var imageData: Data?
// 2
var body: some View {
NSUIImage.image(fromData: imageData ?? Data())
.resizable()
.aspectRatio(contentMode: .fit)
}
}
// 3
struct ImageLayer_Previews: PreviewProvider {
static let imageData = NSUIImage(named: "AppIcon")!.data
static var previews: some View {
ImageLayer(imageData: .constant(imageData))
.previewLayout(.fixed(width: 100, height: 100))
}
}
上面的代碼正在執(zhí)行以下操作:
- 1)
ImageLayer
具有SwiftUI
綁定到meme
圖像的數(shù)據(jù)憾筏。 在后續(xù)步驟中,MemeEditor
將數(shù)據(jù)傳遞到此視圖胡桃。 - 2) 它的
body
由NSUIImage
組成踩叭,NSUIImage
是您使用圖像數(shù)據(jù)初始化的視圖。 您可能想知道這種view
是什么翠胰。 這是iOS上的UIImage
和macOS
上的NSImage
的類型別名容贝,以及擴(kuò)展名。 它允許使用一種常見的圖像類型之景,在兩種平臺(tái)上具有相同的方法和屬性斤富。 您可以在iOS組的NSUIImage_iOS.swift
文件和macOS組的NSUIImage_macOS.swift
中找到它。 根據(jù)您運(yùn)行的是MemeMaker(iOS)
還是MemeMaker(macOS)
锻狗,它使用正確的類型满力。 - 3) 最后,添加預(yù)覽以支持Xcode的預(yù)覽功能轻纪。
查看預(yù)覽以確保您的視圖正在顯示圖像:
現(xiàn)在您正在顯示圖像油额,您可以繼續(xù)顯示文本!
2. Creating the Text Layer
TextLayer
是第二個(gè)子視圖刻帚,它將頂部和底部文本放置在圖像上方潦嘶。 同樣,在Shared
中創(chuàng)建一個(gè)新的SwiftUI View
文件崇众,并將其命名為TextLayer.swift
掂僵。 切記將MemeMaker(iOS)
和MemeMaker(macOS)
選中為Targets
。
將此替換為生成的TextLayer
結(jié)構(gòu)體:
struct TextLayer<ImageContent: View>: View {
@Binding var meme: Meme
let imageContent: () -> ImageContent
}
TextLayer
具有兩個(gè)屬性:meme
顷歌,保存顯示的Meme
锰蓬; 和imageContent
。imageContent
是一個(gè)閉包眯漩,用于在TextLayer
的body
中創(chuàng)建另一個(gè)視圖芹扭。 請(qǐng)注意,您已將視圖聲明為通用結(jié)構(gòu),其中圖像內(nèi)容視圖可以是遵循View
的任何內(nèi)容冯勉。
接下來澈蚌,將body
添加到視圖中:
var body: some View {
ZStack(alignment: .bottom) {
ZStack(alignment: .top) {
imageContent()
MemeTextField(text: $meme.topText)
}
MemeTextField(text: $meme.bottomText)
}
}
您可以在body
中使用兩個(gè)ZStack
,以將頂部文本放置在圖像頂部灼狰,將底部文本放置在圖像底部宛瞄。 為了顯示圖像,您調(diào)用傳遞給TextLayer
視圖的閉包交胚。 要顯示文本份汗,請(qǐng)使用MemeTextField
,這是在啟動(dòng)程序項(xiàng)目中設(shè)置的常規(guī)TextField
蝴簇,用于顯示格式化的文本杯活。
最后,用以下內(nèi)容替換預(yù)覽:
struct TextLayer_Previews: PreviewProvider {
@State static var meme = Meme(
imageData: nil,
topText: "Top Text Test",
bottomText: "Bottom Text Test"
)
static var previews: some View {
TextLayer(meme: $meme) {
Text("IMAGE")
.frame(height: 100)
}
}
}
看一下預(yù)覽:
目前熬词,它看起來不算meme
旁钧。 不用擔(dān)心,在下一節(jié)中互拾,您將結(jié)合圖像和文本圖層來創(chuàng)建MemeEditor
歪今。
3. Creating a Meme Editor
您之前創(chuàng)建的所有文件均獨(dú)立于平臺(tái)。 但是MemeEditor
將根據(jù)應(yīng)用程序運(yùn)行在iOS / iPadOS
還是macOS
上颜矿,使用特定于平臺(tái)的不同方法來導(dǎo)入圖像寄猩。
在后續(xù)步驟中,您將創(chuàng)建另一個(gè)MemeEditor
骑疆,以在macOS
上顯示田篇,但現(xiàn)在,從iOS和iPadOS版本開始箍铭。 創(chuàng)建一個(gè)新的SwiftUI
視圖文件MemeEditor_iOS.swift
泊柬。 這次,它不應(yīng)該在Shared
組中诈火,而應(yīng)該在iOS中彬呻。 請(qǐng)記住僅檢查MemeMaker(iOS)target
。
用以下代碼替換文件中的視圖:
struct MemeEditor: View {
@Binding var meme: Meme
@State var showingImagePicker = false
@State private var inputImage: NSUIImage?
}
MemeEditor
具有與其呈現(xiàn)的meme
的綁定以及兩個(gè)屬性柄瑰。 您將使用ShowingImagePicker
來決定何時(shí)顯示可以讓用戶選擇圖像的圖像選擇器。 然后剪况,您將圖像存儲(chǔ)在inputImage
中教沾。
接下來,向該結(jié)構(gòu)體添加一個(gè)新方法來存儲(chǔ)輸入圖像:
func loadImage() {
guard let inputImage = inputImage else { return }
meme.imageData = inputImage.data
}
現(xiàn)在译断,您可以在視圖內(nèi)部添加body
:
var body: some View {
// 1
TextLayer(meme: $meme) {
// 2
Button {
showingImagePicker = true
} label: {
if meme.imageData != nil {
ImageLayer(imageData: $meme.imageData)
} else {
Text("Add Image")
.foregroundColor(.white)
.padding()
.background(Color("rw-green"))
.cornerRadius(30)
.padding(.vertical, 50)
}
}
}
// 3
.sheet(isPresented: $showingImagePicker, onDismiss: loadImage) {
UIImagePicker(image: $inputImage)
}
}
這是body
發(fā)生的事情:
- 1) 首先授翻,創(chuàng)建一個(gè)新的
TextLayer
并傳遞對(duì)meme
的綁定和一個(gè)閉包以創(chuàng)建ImageLayer
。 - 2) 在此閉包中,定義一個(gè)按鈕堪唐,將其在點(diǎn)擊時(shí)將
showingImagePicker
設(shè)置為true
巡语。 使用上面定義的ImageLayer
作為label
,或者如果該meme
尚不包含圖像淮菠,則顯示一個(gè)按鈕男公。 - 3) 每當(dāng)
showingImagePicker
設(shè)置為true
時(shí),使用sheet
顯示UIImagePicker
合陵。UIImagePicker
是UIImagePickerController
的包裝枢赔,以使其可用于SwiftUI
。 它允許用戶從其設(shè)備中選擇圖像拥知,并且每當(dāng)關(guān)閉picker
時(shí)都會(huì)調(diào)用loadImage
踏拜。
接下來,將文件中的預(yù)覽替換為以下內(nèi)容:
struct MemeEditor_Previews: PreviewProvider {
@State static var meme = Meme(
imageData: nil,
topText: "Top Text Test",
bottomText: "Bottom Text Test"
)
static var previews: some View {
MemeEditor(meme: $meme)
}
}
現(xiàn)在低剔,您的預(yù)覽應(yīng)該顯示對(duì)視圖的測(cè)試:
最后速梗,打開ContentView.swift
。 用以下代碼替換body
的內(nèi)容襟齿,該代碼是專用的meme
編輯器姻锁,而不是文本編輯器:
MemeEditor(meme: $document.meme)
在這里,您用新的MemeEditor
替換了TextEditor
蕊唐。 您將文檔的meme
傳遞給MemeEditor
屋摔,從而使用戶能夠操作和處理meme
。
最后替梨,完成所有這些編碼之后钓试,MemeMaker
準(zhǔn)備在iPhone上運(yùn)行! 選擇MemeMaker(iOS)scheme
并構(gòu)建并運(yùn)行副瀑。 創(chuàng)建一個(gè)新文檔弓熏,如下所示:
現(xiàn)在,您可以選擇一個(gè)有趣的圖像糠睡,添加一些文字并提高您的meme
制作技巧挽鞠。 嘗試創(chuàng)建一個(gè)像這樣的有趣的meme
:
干得好!
Using the App on macOS
SwiftUI
的一大優(yōu)勢(shì)是您可以在所有Apple平臺(tái)上使用它狈孔。 但是信认,盡管您使用了NSUIImage
,但仍需要進(jìn)行一些更改才能在macOS
上運(yùn)行MemeMaker
均抽。
1. Implementing a MemeEditor for macOS
由于MemeEditor
使用UIImagePickerController
嫁赏,因此您無法在macOS上使用它。 相反油挥,您將創(chuàng)建另一個(gè)版本的MemeEditor
潦蝇,該版本將在macOS上運(yùn)行該應(yīng)用程序時(shí)使用款熬。 它將使用NSOpenPanel
讓用戶選擇圖片作為meme
的背景。
但是多虧了SwiftUI
攘乒,大多數(shù)視圖可以保持不變贤牛。 您可以重用ImageLayer
和TextLayer
。 唯一的區(qū)別是用戶如何選擇圖像则酝。
在macOS組中創(chuàng)建一個(gè)新的SwiftUI View
文件殉簸,并將其命名為MemeEditor_macOS.swift
。 僅檢查MemeMaker(macOS)target
堤魁。 用以下代碼替換該文件的內(nèi)容:
import SwiftUI
struct MemeEditor: View {
@Binding var meme: Meme
var body: some View {
VStack {
if meme.imageData != nil {
TextLayer(meme: $meme) {
ImageLayer(imageData: $meme.imageData)
}
}
Button(action: selectImage) {
Text("Add Image")
}
.padding()
}
.frame(minWidth: 500, minHeight: 500)
}
func selectImage() {
NSOpenPanel.openImage { result in
guard case let .success(image) = result else { return }
meme.imageData = image.data
}
}
}
在這里喂链,您可以創(chuàng)建與之前為iOS創(chuàng)建的視圖類似的視圖。 不過妥泉,這一次椭微,您添加了一個(gè)單獨(dú)的按鈕來調(diào)用selectImage
。 selectImage
使用NSOpenPanel
讓您的用戶選擇圖像盲链。 如果選擇成功蝇率,則將新的圖像數(shù)據(jù)存儲(chǔ)在模因中。
最后刽沾,在文件底部添加一個(gè)預(yù)覽:
struct MemeEditor_Previews: PreviewProvider {
@State static var meme = Meme(
imageData: nil,
topText: "Top Text",
bottomText: "Bottom Text"
)
static var previews: some View {
MemeEditor(meme: $meme)
}
}
構(gòu)建并運(yùn)行本慕。 (您需要使用macOS 11.0
或更高版本。)應(yīng)用如下所示:
您可以在macOS
上創(chuàng)建相同的meme
:
Mac
應(yīng)用程序無需任何額外的工作侧漓,就可以使用帶有快捷方式的工作菜單锅尘。 例如,您可以使用Command-N
創(chuàng)建一個(gè)新文檔布蔗,并使用Command-S
保存該文檔藤违,或者您可以使用Command-Z
撤消上一次更改。
創(chuàng)建使用文檔并同時(shí)在iOS和macOS上運(yùn)行的應(yīng)用有多么容易纵揍,這是否令人驚訝顿乒?
文檔是許多優(yōu)秀應(yīng)用程序的核心部分。 現(xiàn)在泽谨,借助SwiftUI
璧榄,為iOS,iPadOS和macOS構(gòu)建基于文檔的應(yīng)用程序變得更加容易吧雹。
如果您想更深入地研究基于SwiftUI
文檔的應(yīng)用程序骨杂,請(qǐng)參閱 Build document-based apps in SwiftUI。
有關(guān)SwiftUI的更多信息雄卷,請(qǐng)查看SwiftUI: Getting Started或SwiftUI by Tutorials一書腊脱。
要?jiǎng)?chuàng)建基于文檔的UIKit
應(yīng)用,請(qǐng)?jiān)?a target="_blank">Document-Based Apps Tutorial: Getting Started中找到更多信息龙亲。
后記
本篇主要講述了基于
SwiftUI
的Document-Based App
的創(chuàng)建陕凹,感興趣的給個(gè)贊或者關(guān)注~~~