前言
本期是 Swift 編輯組自主整理週報的第二十二期,每個模塊已初步成型。各位讀者如果有好的提議,歡迎在文末留言。
Swift 週報在 GitHub 開源,歡迎提交 issue,投稿或推薦內容。目前計劃每兩週週一發佈,歡迎志同道合的朋友一起加入週報整理。
若目標遠大,就要有大動作。若追求卓越,便須有大改變。Swift社區已整裝待發,你要不要一起呢?👊👊👊
週報精選
新聞和社區:Apple Vision Pro 和 visionOS 撼世登場
提案:移除由屬性包裝器引起的 Actor 隔離推斷
Swift 論壇:為什麼只能將結構附加到數組一次
推薦博文:Swift OpenAPI Generator 的介紹
話題討論:
你認為企業實行薪資保密有哪些利弊
上期話題結果
上期話題投票結果表明,在 2023 年工作更難找的情況下,大家面臨着更大的工作壓力,裁員消息的傳出也增加了擔憂。大量的媒體報道可能強調了經濟衰退的跡象,這也會加強大家對經濟危機的看法。
新聞和社區
註冊 WWDC23 實驗室和活動
通過在線實驗室和活動這種絕佳方式,你可以在一整週內與 Apple 工程師、設計師和專家進行交流溝通。
一對一實驗室
從開發的基礎知識到複雜概念,你都可以在這裏獲得個性化指導。瞭解如何運用全新 Apple 技術、探索 UI 設計原則、優化產品在 App Store 上的形象,以及更多主題。
活動
每日都有許多精彩的活動在 Slack 中展開。
在 Q&A 中就工程和設計主題提問。
在大家一起觀看講座視頻期間加入或關注實時對話,並與演講者進行 Q&A。
在社區暖場活動中瞭解其他開發者和 Apple 團隊。
體驗最新的框架,嘗試各種設計理念,並在學習區分享你的創作。
在 6 月 6 日,與業內的佼佼者比試一下專業知識問答。
實驗室和活動對 Apple Developer Program 和 Apple Developer Enterprise Program 的所有成員,以及 2023 Swift Student Challenge 參賽者開放。
Apple Vision Pro 和 visionOS 撼世登場
Apple Vision Pro 是一款革命性的空間計算設備,可實現數字化內容與真實世界的無縫融合,讓用户在沉浸於當下的同時還能與他人溝通交流。在 Apple Vision Pro 中,各種 App 將突破傳統顯示器的束縛限制,擁有一幅無邊的畫布。此外,Apple Vision Pro 還推出了一個全三維用户界面,而控制這個界面,僅需要用户的眼睛、雙手和語音 — 最自然、最直觀的輸入工具。Apple Vision Pro 搭載了全球首個空間操作系統 visionOS,讓用户能夠以一種絕妙的方式與數字化內容互動,如同它們真的存在於現實世界之中。Apple Vision Pro 採用了突破性設計:在顯示方面,採用超高分辨率顯示屏系統,兩塊顯示屏的總像素為 2,300 萬;在性能方面,採用獨特的雙芯片設計並搭載定製的 Apple 芯片,確保每一刻的體驗都真實無比,讓人沉浸當下。
探索豐富實用的資源,助你通過一種全新而又熟悉的方式將空間計算方面的創意變為現實,打造出能夠重新定義溝通、效率和娛樂的 App。
App Store 中新增的隱私功能
在 Apple,我們將隱私視作每個人的基本權利。因此,我們構建了許多功能來幫助用户瞭解開發者在隱私以及數據收集和共享方面的做法,讓用户能夠自主掌控他們的數據。通過 App 跟蹤透明度 (ATT),用户可以選擇 App 是否有權跟蹤用户在其他公司的 App 和網站內的活動,以便投放廣告或者與數據代理商共享。藉助隱私標籤和 App 隱私報告,用户可以查看 App 收集哪些數據以及如何使用這些數據。
許多 App 會利用第三方軟件開發工具包 (SDK),這些工具包可以提供出色的功能,但可能會對 App 處理用户數據的方式產生影響。為了讓開發者可以更輕鬆地打造出色的 App,同時告知用户數據使用情況並尊重他們在這方面做出的選擇,我們推出了兩項新功能。
首先,為了幫助開發者瞭解第三方 SDK 如何使用數據,我們推出了新的隱私清單。隱私清單是一份文件,會以單一標準格式概述 App 中第三方代碼的隱私做法。當開發者準備分發他們的 App 時,Xcode 會將開發者使用的所有第三方 SDK 中的隱私清單合併為一個簡單易用的報告。這個報告內容全面,總結了 App 中的所有第三方 SDK,使開發者能夠更輕鬆地創建更準確的隱私標籤。
此外,為了向用户提供額外的隱私保護,如果 App 引用的 API 可能會被用於指紋識別(在 App Store 中被禁止的一種做法),現在需要選擇合理的原因來解釋為什麼使用此 API 並在隱私清單中聲明已使用此 App。在這個過程中,App 必須準確描述其對於這些 API 的使用情況,並且只能出於隱私清單中所述的原因而使用這些 API。
第二,我們希望幫助開發者改善軟件供應鏈的完整性。使用第三方 SDK 時,開發者可能很難知道他們下載的代碼是不是由期望的開發者編寫的。為了解決這個問題,我們推出了適用於 SDK 的簽名功能,這樣一來,當開發者在 App 中採用新版本的第三方 SDK 時,Xcode 將驗證它是否由同一開發者簽名。這個功能將對開發者和用户都十分有幫助。
我們將在今年晚些時候發佈更多信息,包括:
影響隱私的 SDK 列表 (對用户隱私產生重大影響的第三方 SDK)
“需要指明原因”的 API 列表,使用它們時必須給出合理的原因
開發者反饋表,用於就調用涉及的 API 提出新的原因
其他文檔,詳細介紹簽名和隱私清單、他們的優勢以及何時需要使用它們
提案
正在審查的提案
SE-0400 Init 訪問器 提案正在審查。
該提案的目的是,Init 訪問器將屬性包裝器的離線初始化特性泛化,使得類型中的任何計算屬性都可以選擇參與確定性初始化分析,並且可以替代使用自定義初始化代碼對一組存儲屬性進行初始化。
SE-0401 移除由屬性包裝器引起的 Actor 隔離推斷 提案正在審查。
SE-0316:全局 Actors 引入了像 @MainActor 這樣的註釋,將類型、函數或屬性隔離到特定的全局 Actor。還引入了各種規則,用於推斷全局 Actor 隔離。如下:
@propertyWrapper
struct UIUpdating<Wrapped> {
@MainActor var wrappedValue: Wrapped
}
struct CounterView { // infers @MainActor from use of @UIUpdating
@UIUpdating var intValue: Int = 0
}
該提案主張在使用 Swift 6 語言模式編譯時移除此推斷規則。根據上面的示例,CounterView 在 Swift 6 中將不再推斷 @MainActor 隔離。
Swift論壇
1) 提議SE-0400: Init Accessors
SE-0400:Init Accessors 314 的審查從現在開始,一直持續到 2023 年 6 月 26 日。
2) 提議改進提案模板以獲得更好的功能實踐
介紹
強制性工具鏈和示例項目以及 Experiment It 部分將允許開發人員在提案審查期間更輕鬆地進行實驗並參與討論。
動機
試驗正在審查的功能這是評估提案的重要方式,即使是寫得很好和詳細的提案也可以從讓開發人員試驗它中受益。 提案模板可以改進,使任何人在審查期間更容易試用提議的功能。
建議的解決方案
將以下標題字段添加到提案模板:工具鏈和示例項目以及新的 Experiment It 部分。
工具鏈
該字段應指向一個鏈接,從中可以下載一個 swift 工具鏈,其中該功能是在實驗性標誌下實現的。
目前大多數提案只提到主分支中有一個功能可用,儘管大多數時候該功能都在 Swift.org 上可用的開發快照中 - 下載 Swift 對於新手來説了解這一點並不是那麼微不足道,有時還有一個提案審查期 甚至在沒有工作快照的情況下啓動。
該鏈接應該從第一天起就可用,並在審核期間儘可能更新。
一種可能性是在網站下載頁面上添加一個額外的部分,其中包含專用於正在審查的提案的工具鏈,這可以允許工具鏈可用,即使由於某種原因它不能出現在主快照中也是如此。
3) 提問為什麼只能將結構附加到數組一次?
我的應用程序的目標是提醒用户與他們親近的人互動。 因此,我的應用程序主要使用兩個結構體,稱為 Relation(代表一個人)和 Interaction(代表與人的一次交互)。
我構建了一個名為 “NewInteractionSheet” 的工作表,其目標是向關係的交互數組之一添加一個新的交互。
在添加交互時,此工作表非常有效。 但是,由於某種原因,它只能工作一次。 為什麼要這樣做? 這就是我想要弄清楚的。
這是 “NewInteractionSheet.swift” 代碼的一部分:
import PhotosUI
import CoreLocation
import MapKit
struct NewInteractionSheet: View {
@Binding var isPresentingNewInteractionView: Bool
@Binding var relations: [Relation]
@State private var newInteraction = Interaction.emptyInteraction
@State private var relation: Relation = Relation.emptyRelation
@State private var isPresentingLocationPicker: Bool = false
var body: some View {
NavigationView {
Form {
Section("You interacted with...") {
RelationPicker(relations: $relations, relation: $relation)
}
Section("Interaction details") {
InteractionDatePicker(dateToSet: $newInteraction.date)
TypePicker(typeToSet: $newInteraction.type)
DurationPicker(shouldShow: newInteraction.type.hasDuration,
hoursToSet: $newInteraction.durationHours,
minutesToSet: $newInteraction.durationMinutes)
SummaryTextField(summaryToSet: $newInteraction.summary)
LocationPicker(shouldShow: newInteraction.type.hasLocation,
coordinatesToSet: $newInteraction.location.coordinates,
locationNameToSet: $newInteraction.location.name,
isPresentingLocationPicker: $isPresentingLocationPicker)
InteractionPhotosPicker(images: $newInteraction.pictures)
}
}
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Dismiss") {
isPresentingNewInteractionView = false
}
}
ToolbarItem(placement: .confirmationAction) {
Button("Add") {
if let index = relations.firstIndex(where: { $0.id == relation.id }) {
print("\nBefore appending to relations")
print(relations[index])
print(newInteraction)
relations[index].interactions.append(newInteraction)
print("\nAfter having appended to relations")
print(relations[index])
print(newInteraction)
}
isPresentingNewInteractionView = false
//AJOUTER LA PLANIFICATION D'UNE NOTIFICATION
}
}
}
.navigationTitle("New interaction")
}
}
}
正如在代碼中看到的,我包含了三個“打印”指令來幫助我調試它。 當我嘗試添加兩個交互時,以下是控制枱中打印的內容:
Before appending to relations
Relation(id: EA18AAD4-E576-49A9-90BF-CC58C5000ECE, firstName: "Johanna", lastName: "Duby", photo: nil, interactions: [], contactFrequency: 1814400.0, birthday: Optional(2023-06-15 14:34:40 +0000), notes: "", theme: Relations.Theme.blue, reminders: nil)
Interaction(id: 106CD832-1949-4800-AC75-E21B8890E580, date: 2023-06-15 14:34:43 +0000, type: Relations.InteractionType.audioCall, durationHours: 0, durationMinutes: 0, summary: "", location: Relations.Location(name: "", coordinates: nil), pictures: [])
After having appended to relations
Relation(id: EA18AAD4-E576-49A9-90BF-CC58C5000ECE, firstName: "Johanna", lastName: "Duby", photo: nil, interactions: [Relations.Interaction(id: 106CD832-1949-4800-AC75-E21B8890E580, date: 2023-06-15 14:34:43 +0000, type: Relations.InteractionType.audioCall, durationHours: 0, durationMinutes: 0, summary: "", location: Relations.Location(name: "", coordinates: nil), pictures: [])], contactFrequency: 1814400.0, birthday: Optional(2023-06-15 14:34:40 +0000), notes: "", theme: Relations.Theme.blue, reminders: nil)
Interaction(id: 106CD832-1949-4800-AC75-E21B8890E580, date: 2023-06-15 14:34:43 +0000, type: Relations.InteractionType.audioCall, durationHours: 0, durationMinutes: 0, summary: "", location: Relations.Location(name: "", coordinates: nil), pictures: [])
Before appending to relations
Relation(id: 8D3D2012-D8A2-4092-B1A9-D476F7E05B9A, firstName: "Nastassja", lastName: "Ferrari", photo: nil, interactions: [], contactFrequency: 1209600.0, birthday: nil, notes: "", theme: Relations.Theme.green, reminders: nil)
Interaction(id: 5C4EE2E1-7D2D-4E32-BC00-FCA781EC8C20, date: 2023-06-15 14:34:49 +0000, type: Relations.InteractionType.audioCall, durationHours: 0, durationMinutes: 0, summary: "", location: Relations.Location(name: "", coordinates: nil), pictures: [])
After having appended to relations
Relation(id: 8D3D2012-D8A2-4092-B1A9-D476F7E05B9A, firstName: "Nastassja", lastName: "Ferrari", photo: nil, interactions: [], contactFrequency: 1209600.0, birthday: nil, notes: "", theme: Relations.Theme.green, reminders: nil)
Interaction(id: 5C4EE2E1-7D2D-4E32-BC00-FCA781EC8C20, date: 2023-06-15 14:34:49 +0000, type: Relations.InteractionType.audioCall, durationHours: 0, durationMinutes: 0, summary: "", location: Relations.Location(name: "", coordinates: nil), pictures: [])
4) 提問Swift 5.9 是否支持嵌套/遞歸宏?
5) 提問如何引用不同模塊中的文章?
查看 DocC 代碼鏈接的語法,似乎我們有辦法引用同一模塊中的文章:
<doc:GettingStarted>
但是我們不能使用前導斜槓語法來指定模塊相對路徑,因為它已經被 tutorials 命名空間佔用:
<doc:/tutorials/SlothCreator>
如何引用來自不同模塊的文章?
回答:
庫存 DocC 尚不支持外部 - 或者更具體地説,尚未提供公共解決方案。 早期的 DocC 代碼中有一些關於允許某些過程的外部引用解析器的位,@ronnqvist 一直在研究更新的解決方案(“分層解析器”)——但我只關注了一些 PR(最近的一個 提取了很多舊代碼:通過 d-ronnqvist 添加成功解析的外部引用到參考索引, Pull Request #582)
6) 提問Macros包會嵌入到App中嗎?
例如,當我使用 #stringify Swift 宏在我的應用程序中生成代碼時,它會在編譯期間用新代碼替換我的一些源代碼。 那麼這個宏包會隨我的應用程序一起提供嗎? 或者它只是在編譯期間發生
回答:替換髮生在編譯時。 宏目標不應鏈接到應用該目標中包含的宏的代碼。
7) 提問哪個 Apple Networking Api 用於 UDP 多播和單播?
一般而言,iOS 開發和網絡的新手。 開發一個遊戲節目類型的應用程序,其中“主機”設備需要多播到“參賽者”設備。 參賽者設備也需要能夠響應。 實際上傳遞的信息很少,但速度很重要,因此使用 UDP。
我一直在研究蘋果設備的一些常用網絡 api:network.framework、CocoaAsyncSocket、Multipeer-Connectivity、BSD 套接字等。總的來説,我傾向於只使用高級 network.framework 但缺乏 示例和資源使決策變得困難。 任何意見,將不勝感激。
回答:TN3151: Choosing the right networking API
推薦博文
Swift OpenAPI Generator 的介紹
摘要: Swift OpenAPI Generator是一個 SwiftPM 插件,它可以生成客户端代碼或服務器端代碼,以便處理 HTTP 調用。 OpenAPI 是一種用於記錄HTTP服務的規範,可以使用YAML或JSON編寫,並可被工具讀取,以幫助自動化工作流程,例如生成必要的代碼以發送和接收HTTP請求。Swift OpenAPI Generator 可以幫助我們通過 OpenAPI 文檔描述HTTP請求和響應的結構,包括 HTTP 方法、 URL 路徑和查詢參數、HTTP狀態碼和內容類型,使用 JSON Schema 描述響應體的結構,使得我們能夠在開發應用程序時生成網絡代碼,而不需要手動編寫和維護網絡代碼,專注於核心業務邏輯。要使用 Swift OpenAPI Generator 插件,需要添加 SwiftPM 依賴項以及運行時庫和傳輸實現,然後使用生成的API客户端或服務器端存根。 Swift OpenAPI Generator 支持大多數常用特性,但仍有一些特性需要實現,項目跟蹤進展情況可以使用 GitHub issues
Swift 宏:使用新的表達方式擴展 Swift
摘要: Swift 宏是在 Swift 5.9發佈的一項新功能,它允許你通過自定義編譯時檢查和生成新的代碼,在編譯時將它們寫入到你的文件中,從而消除冗餘的樣板代碼。本文講解了宏的工作原理、如何編寫自定義宏以及如何進行測試,以驗證一個允許在編譯時驗證 URL 並在 URL 有效時返回解包值的宏的例子。本文還討論了宏的不同角色,包括獨立和附加宏,並解釋了為什麼你可能考慮在代碼中使用宏。
在 Swift 服務器端 Vapor 和客户端應用之間共享 Swift 代碼
摘要: 這篇博客討論了在客户端應用和後端服務器之間共享 Swift 代碼的好處以及如何通過 Swift 包和 Vapor 實現這一目標。通過共享模型和端點定義,您可以確保兩個側面都使用相同的層,避免出現意料之外的請求失敗。博客提供了定義軟件包結構、暴露模型、共享端點定義和在後端軟件包中配置端點的代碼示例。此外,它提供了一個通用方法,用於請求端點並在客户端應用中使用它們。作者還提到了優化適用於所有支持的 HTTP 方法的代碼的重要性。
話題討論
薪酬保密作為人力資源管理中一項頗具爭議的舉措,近年來學界對其研究越來越多。有人提出,實行薪酬保密,能讓企業根據員工績效的高低提供差異較大的薪酬,提升薪酬激勵作用,同時也能避免因為收入差距產生內部衝突。也有人提出公開的薪酬制度能使內部溝通更為有效,減少誤傳,增強信任感,作為一種制度,薪酬的等級體系、崗位差距以及操作程序還應以公開為準則。你認為企業實行薪資保密有哪些利弊?
1.保護員工個人隱私。
2.避免員工之間的比較和嫉妒心理,減少內部矛盾。
3.難以查看薪資公正性,更少的保密性意味着更多的平等。
4.易產生員工對公司不信任,讓員工產生長期處於被剝削的感覺。
關於我們
Swift社區是由 Swift 愛好者共同維護的公益組織,我們在國內以微信公眾號的運營為主,我們會分享以 Swift實戰、SwiftUl、Swift基礎為核心的技術內容,也整理收集優秀的學習資料。
特別感謝 Swift社區 編輯部的每一位編輯,感謝大家的辛苦付出,為 Swift社區 提供優質內容,為 Swift 語言的發展貢獻自己的力量。