动态

详情 返回 返回

蘋果今明兩年或將採購2.3萬台AI服務器 | Swift 週報 issue 40 - 动态 详情

前言

本期是 Swift 編輯組整理週報的第四十期,每個模塊已初步成型。各位讀者如果有好的提議,歡迎在文末留言。

Swift 週報在 GitHub 開源,歡迎提交 issue,投稿或推薦內容。目前計劃每兩週週一發佈,歡迎志同道合的朋友一起加入週報整理。

世間萬般兵刃,唯有過往傷人最深。Swift社區邀你走出低谷,邁向山巔!👊👊👊

週報精選

新聞和社區:53.5億美元!傳蘋果今明兩年或將採購2.3萬台AI服務器!

提案:隔離的默認值表達式

Swift 論壇:討論為什麼 CaseIterable 比 Set 更快

推薦博文:掌握 swift 中 Preview macro 的用法

話題討論:

在諸多物流行業,你最看好哪一家?

上期話題結果

投票結果顯示大多數人更傾向於保持薪資不變或者期望薪資增加,而只有少數人願意接受較小幅度的薪資降低。小編認為公司在決定遠程辦公政策時需要綜合考慮員工的期望和需求。

新聞和社區

53.5億美元!傳蘋果今明兩年或將採購 2.3 萬台 AI 服務器!

10 月 25 日消息,根據最新的研究顯示,蘋果公司計劃在 2023 年採購約 2000 - 3000 台 AI 服務器,2024 年或將增長至 1.8 萬 - 2 萬台,採購的主要目標是滿足蘋果對AI算力的需求,尤其是在訓練和推理生成式 AI 方面。

報告稱,蘋果主要採購的是英偉達的 HGX H100 8-GPU 系統,由 8 個 H100 SXM5 模塊加上 4 個 NVSwitch Chip 在同一個 System board 上。這款 AI 服務器以其強大的性能和穩定的表現成為業界熱門選擇,單台價格高達 25 萬美元(約合人民幣 183 萬元)。

據天風國際分析師郭明錤預測,在 2023 年和 2024 年期間,蘋果將分別採購約 6.2 億美元(約合人民幣 45.38 億元)和 47.5 億美元(約合人民幣 347.7 億元)的 AI 服務器,總投額資達 53.3 億美元。雖然投資額巨大,但考慮到蘋果的品牌影響力和技術需求,這一投入無疑是值得的。

目前各行各業對 AI 技術應用持續滲透,對於 AI 算力的需求暴增,全球 AI 服務器市場將迎來更大規模的增長。郭明錤也指出,在未來幾年中,全球 AI 服務器市場將繼續保持強勁增長,併為相關企業帶來更多機會。因此,對於那些想要在這個領域取得成功的企業來説,關注並積極參與 AI 服務器市場的擴張至關重要。(來源:芯智訊)

TestFlight 讓管理測試員變得更加簡單

2023 年 10 月 24 日

藉助 TestFlight,你可輕鬆獲取有關 App Beta 版的反饋,以便放心地在 App Store 上進行發佈。現在,使用 App Store Connect 中經改進的控件,你可更有效地評估測試員的參與度並管理參與情況,以充分利用 Beta 測試。你可按狀態和參與度指標 (例如會話、崩潰和反饋) 對測試員進行排序,並刪除參與度較低的非活躍測試員。你還可以按設備和操作系統進行篩選,甚至選擇相關測試員,以將其添加到新的羣組中。

推送通知控制面板現已推出新交付指標

2023 年 10 月 19 日

推送通知控制面板現在包含在生產環境中通過 Apple 推送通知服務 (APNs) 發送的通知的指標。藉助控制面板的直觀界面,你可以查看交付狀態的聚合視圖,深入瞭解通知的各種統計數據 (包括基於推送類型和優先級的詳細細分)。

我們在 WWDC23 (簡體中文字幕) 公佈的推送通知控制面板,將能幫助你輕鬆地通過 APNs 向 Apple 設備發送測試通知。

Apple Vision Pro 開發者實驗室現已擴展到紐約市和悉尼

2023 年 10 月 17 日

我們非常興奮能看到世界各地的開發者對 Apple Vision Pro 開發者實驗室的期待和熱情。很高興能在此宣佈,我們已在紐約市和悉尼設立新的實驗室。歡迎參加我們的開發者實驗室活動,直接在設備上進行測試,與 Apple 專家溝通交流以獲得幫助,一起探索如何讓你的 visionOS、iPadOS 和 iOS App 在這個激動人心的新平台上更進一步。我們還分別在庫比蒂諾、倫敦、慕尼黑、上海、新加坡和東京設立了實驗室。

提案

正在審查的提案

SE-0410 Low-Level Atomic Operations 提案正在審查。

該提案為標準庫添加了一組有限的低級原子操作,包括 C++ 風格的內存排序的原生拼寫。我們的目標是使編寫系統級代碼的勇敢的圖書館作者和開發人員能夠直接在 Swift 中構建同步結構。

SE-0411 隔離的默認值表達式 提案正在審查。

默認值表達式允許用於默認參數和默認存儲屬性值。當前默認值表達式的 actor 隔離規則存在一些問題:存儲屬性的規則容許數據競爭,默認參數值的規則過於限制,而在不同的默認值表達式使用位置之間的規則相互矛盾,導致 actor 隔離模型更難理解

該提案統一了默認值表達式的 actor 隔離規則,消除了數據競爭,通過安全地允許默認值的隔離來提高表現力。

Swift論壇

1) 討論查找符號是如何導入的?

我有一個使用特定 API 的源文件,但沒有導入定義它的包。據我所知,在該文件的導入中,即使是傳遞性的,也不會導入該包。

然而,該文件在構建時“正確”編譯(儘管 Xcode 15 的實時編譯同意我的觀點,即 API 不應該可見並生成實時錯誤)。

我正在使用 Xcode,該文件是一個測試,如果其中任何一個對答案有任何影響。

有沒有辦法可以調試此 API 的導入方式? 除了 import 之外,是否還有其他機制可以讓 swift API 可供 swift 源文件使用?

回答

從技術上講,只有當你想要使用類型的名稱時,才需要將其導入到該文件中。 你可以使用該類型的實例,無需:

// main.swift
let calendar = myCalendar()
let currentYear = calendar.component(.year, from: now())
print("It's \(currentYear)")

// This all works fine with no errors.
// The type of `calendar` is NSCalendar, but if we had written
//   let calendar: NSCalendar = myCalendar()
// that would be an error.

// file2.swift
import Foundation

func myCalendar() -> NSCalendar {
  return NSCalendar(calendarIdentifier: .gregorian)!
}

func now() -> Date {
  return Date()
}

2) 討論 @backDeployed 作為 override 運行,而不是僅用於不受支持的平台版本

自 Xcode 15 和 iOS 17 發佈以來,我們最近一直面臨很多令人頭痛的問題,因為我們 @backDeployed 的 API 的意外行為。

長話短説,我發現我們 @backDeployed 的任何 API 不僅在平台部署版本“之前”的操作系統上被調用,而且也在平台部署版本“之後”的操作系統上被調用。

這可以通過單元測試或 playground 來重現:

import UIKit

public extension Locale.LanguageCode {
  @backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)
  var debugDescription: String { // <-- introduced in iOS 17
    get {
      if #available(iOS 17, macOS 14.0, *) {
        return "17"
      }
      return self.identifier
    }
  }
}

func test() {
  let locale = Locale(identifier: "en_US")
  let languageCode = locale.language.languageCode!
  
  
  let desc = languageCode.debugDescription
  // ^ This print should yield "en" on iOS 16 & 17
  // but it yields "17" on iOS 17 (proving the @backDeployed API is actually being treated as an override instead thunking to the platform deployed version).
  // You can comment out the @backDeployed `debugDescription` above to see it go back to correct behavior
}

test()

實際上,我們使用 @backDeployed 來 override 任何我們喜歡的 API,而不僅僅是向後部署。

這是否可以在 Swift 的錯誤修復修訂版中解決(最好在退出 beta 之前部署到 Xcode 15.1)?

回答

我認為你誤解了 @backDeployed 屬性的作用以及它的用途。@backDeployed 設計用於實現操作系統附帶的框架。

該屬性的設計目的不是為你提供一種為 SDK 中的任意函數提供你自己的 polyfill 的方法,因此,如果我正確解釋了你想要完成的任務,我認為它不會達到你想要的效果 。

在你的示例中,你已為 Locale.LanguageCode 聲明瞭自己的計算屬性 debugDescription。 你的聲明不會“覆蓋”基金會中的聲明;它只是作為可以調用的不同函數同時存在於你的模塊中。是否在任何給定的調用站點調用你的實現取決於編譯器將 debugDescription 靜態解析為哪個聲明。

如果編譯器解析對你的聲明的調用,而不是來自 SDK 的調用,那麼你的實現上的 @backDeployed 屬性將導致編譯器發出對中間 thunk 的調用,該中間 thunk 調用你的原始函數或函數的副本,它不會完成任何有用的事情,因為它是同一模塊中的函數,並且原始副本和後備副本將始終具有相同的實現。

3) 討論新的 SwiftNIO 異步 API

我很高興與大家分享,我們剛剛發佈了一些軟件包的新版本,其中包括全新的異步 API。

  • swift-nio : 2.60.0
  • swift-nio-transport-services : 1.20.0
  • swift-nio-http2 : 1.29.0

一段時間以來,我們一直致力於新 API 的開發,讓它們在 AsyncChannel SPI 後面進行烘焙。 在最新版本中,我們將 SPI 升級為穩定的 API。

新異步 API 的目標是讓開發人員能夠輕鬆、安全地在 NIO Channels 和 Swift Concurrency 之間建立橋樑。 新 API 的一個重要部分是它們攜帶有關 ChannelPipeline 的類型信息,同時保持靈活性,這是通過利用泛型的強大功能實現的。

你可以在我們全新的 NIO 和 Swift Concurrency 文章中找到有關新 API 的更多文檔。如果你有興趣閲讀更多有關新 API 背後的想法並查看跨包的 API 添加的概述,請隨時查看 我們的開發者文檔.

我想指出的一件重要的事情是,新的 API 在業務邏輯和網絡之間提供了明確的關注點分離。

網絡協議存在於通道管道中,業務邏輯應直接在通道管道之外的 Swift Concurrency 中實現。 許多現有應用程序都駐留在通道管道內,我們強烈建議將業務邏輯移出。

我們迫不及待地想看看社區使用新 API 構建了什麼,並期待你的反饋!

4) 討論使用 ArgumentParser 創建命令行工具的正確方法是什麼? swift package 或 Xcode 創建 Mac 命令行工具項目?

我相信創建 ArgumentParser 命令行工具的正確方法是:

swift package init --type tool --name MyTool

然後在 Xcode 中打開 Package.swift。 但是我無法添加這個包:https://github.com/dominicegginton/spinner

添加依賴項後,“My Mac” target 消失了。

當我從 Xcode 內部創建 macOS 命令行工具項目時,我可以找到 spinner 包並使用它。 如果我添加 ArgumentParser,運行崩潰。

我應該怎麼辦?

回答

你可以嘗試分叉 Spinner,更新其軟件包清單以使用 Rainbow 4+ ,取決於你的 fork,而不是原始 fork,然後看看有什麼問題......

如果沒有任何問題,你可以將該更改作為 PR 提交到 Spinner 項目。

5) 討論performSelector("retainCount")")

另一個線程提示我一個調用禁止的保留計數的問題——可能對調試目的有用。 我知道一些獲取對象的保留計數的技術(例如,通過駐留在非 ARC obj-c 文件中的 C 幫助程序進行調用,因此能夠調用保留計數,即引用線程中顯示的技術)或閲讀 通過 “withUnsafeBytes” 直接從 Swift 中保留 Swift 對象的原始位。 那麼這個基於 performSelector 的其他方法呢?

let obj = NSObject()
let x = obj.perform("retainCount")!
// p x
// (Unmanaged<AnyObject>) {
//  _value = (object = 0x0000000000000002)
// }
print(x) // crash
let y = x.toOpaque() // crash
print(y)
let z = x.takeUnretainedValue() // crash
print(z)
print(obj)

可以對其進行調整以使其工作嗎? 它似乎工作正常,返回正確的 UnmanagedObject,我可以通過 “print” 命令在調試器中看到它,但如何從應用程序中獲取它? 我是否需要使用一些 unsafeBitCast 來讀取該值?

回答

PerformSelector: 返回一個對象; 它名義上僅用於返回對象的方法,而不是基元。

在 Objective-C 中,你可能可以通過將結果轉換為原始類型來濫用它,但如果它不是指針大小或平台的調用約定使用不同的寄存器來返回指針與整數,你將得到垃圾(或更糟)。

我不確定你是否可以在 Swift 中執行此轉換,因為 Unmanaged 假設它確實包含有效的對象引用,並且會嘗試適當地保留和釋放它。

6) 討論為什麼 CaseIterable 比 Set 更快

// V1
enum VaccineCodeSet: String {
    case covidModerna = "207"
    case covidBioNTech = "208"
    case covidAstraZeneca = "210"
    case covidNovax = "211"
    case covidJohnson = "212"
    case covidValneva = "213"
    case hepatitesB = "45"
    case whoopingCough = "11"
    case measles = "05"
    case mumps = "07"
    case rubella = "06"
    case chickenpox = "21"
    case tbe = "77"
    case hepatitesA = "85"
    case yellowFever = "184"

    static var allCases: Set<String> = [
        Self.covidModerna.rawValue,
        Self.covidBioNTech.rawValue,
        Self.covidAstraZeneca.rawValue,
        Self.covidNovax.rawValue,
        Self.covidJohnson.rawValue,
        Self.covidValneva.rawValue,
        Self.hepatitesB.rawValue,
        Self.whoopingCough.rawValue,
        Self.measles.rawValue,
        Self.mumps.rawValue,
        Self.rubella.rawValue,
        Self.chickenpox.rawValue,
        Self.tbe.rawValue,
        Self.hepatitesA.rawValue,
        Self.yellowFever.rawValue
    ]
}
printTimeElapsedWhenRunningCode(title: "VaccineCodeSet") {
    if VaccineCodeSet.allCases.contains("184") {
        true
    }
}
// Time elapsed to check: 0.006421875 s.

// V2
enum VaccineCodeCaseIterable: String, CaseIterable {
    case covidModerna = "207"
    case covidBioNTech = "208"
    case covidAstraZeneca = "210"
    case covidNovax = "211"
    case covidJohnson = "212"
    case covidValneva = "213"
    case hepatitesB = "45"
    case whoopingCough = "11"
    case measles = "05"
    case mumps = "07"
    case rubella = "06"
    case chickenpox = "21"
    case tbe = "77"
    case hepatitesA = "85"
    case yellowFever = "184"
}
printTimeElapsedWhenRunningCode(title: "Array") {
    if let code = VaccineCodeCaseIterable(rawValue: "184"),
       IllnessCodeCaseIterable.allCases.contains(code) {
       true
    }
}
// Time elapsed to check:: 0.005916875 s.

為什麼 V1 比 V2 慢?

回答

V2 確實還有一項工作要做:從 String 到 enum case。 但這可以優化(在 init(rawValue:) 實現中),因為編譯器知道可能的有效字符串的完整集合,因此它最終比哈希查找更快。

事實上,由於所有字符串都很短,它甚至可以作為整數開關來完成,在檢查長度後將字符串內容視為多字節整數。

推薦博文

掌握 swift 中 Preview macro 的用法

摘要: 本篇博客介紹了 Swift 中的新功能——預覽宏(Preview macro),以及它對開發體驗的改進。預覽宏可以輕鬆地將 SwiftUI 視圖、UIViewController 或 UIView 實例嵌入到預覽中。文章還討論瞭如何創建展示不同視圖狀態的多個預覽,並通過傳遞標題參數來區分它們。此外,它還介紹了預覽宏的 traits 參數,可以在預覽中顯示橫向視圖或指定尺寸。文章最後提到了如何將預覽宏與 widget 結合使用來展示交互式的 widget 時間線。作者建議開發者可以利用預覽宏來改善開發體驗,並指出可以創建專門用於設計系統包的預覽文件或示例用法的文件。

Xcode 中使用 SPM 和 Build Configuration 的一些坑

摘要: 本文介紹了 Swift 中的值和類型參數包,並結合示例進行了詳細解釋。類型參數包和值參數包允許你編寫一個接受任意數量具有不同類型參數的通用函數。在 Swift 5.9 中,由於 SE-393、SE-398 和SE-399 的提案,這一新特性得以實現。採用參數包的最顯著影響之一是在 SwiftUI 中的10個視圖限制已經不存在,這是由於在這些提案之後可實現了可變參數泛型。本文還解釋了參數包的解決方案,它們幫助我們編寫可重用的代碼,避免編寫大量的函數重載。從 Swift 5.9 開始,我們可以使用參數包重寫類似的函數。

Swift 中 User Defaults 的讀取和寫入

摘要: 這篇文章討論了在 Swift 中使用 User Defaults進行讀取和寫入的方法。User Defaults 是 Swift 應用程序中用於存儲在應用程序啓動期間保持不變的偏好設置的首選解決方案。它是一個基於屬性列表(plist)文件的鍵值存儲。文章介紹了一些與 User Defaults 工作時的最佳實踐,並提供了一些特定的解決方案和建議。其中包括使用應用程序組與其他應用程序和擴展共享 User Defaults,以及類型支持和數據轉換的注意事項。此外,文章還介紹了監聽 User Defaults 更改的方法,並探討了一些替代方案,如 Keychain 和 CloudKit。在文章的結尾,作者總結了使用 User Defaults 存儲偏好設置的好處,並提醒讀者在需要跨設備訪問數據或存儲敏感數據時考慮其他解決方案。。

話題討論

10月27日,起家於東南亞的極兔速遞正式登陸港交所。此次IPO,發行價12港元/股,市值約1000億港元,成為港交所2023年迄今開盤市值最高的IPO。在諸多物流行業,你最看好哪一家?

  1. 菜鳥
  2. 順豐
  3. 京東物流
  4. 極兔

歡迎在文末留言參與討論。

關於我們

Swift社區是由 Swift 愛好者共同維護的公益組織,我們在國內以微信公眾號的運營為主,我們會分享以 Swift實戰SwiftUlSwift基礎為核心的技術內容,也整理收集優秀的學習資料。

特別感謝 Swift社區 編輯部的每一位編輯,感謝大家的辛苦付出,為 Swift社區 提供優質內容,為 Swift 語言的發展貢獻自己的力量。

user avatar gaodadepijiu 头像 zhaodaoweb 头像 htdaydayup_5da2d7a6d4888 头像
点赞 3 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.