【文章翻譯】Why nullable types?

【文章內容使用 Gemini 1.5 Pro 自動翻譯產生】

為什麼要使用可空類型?

幾週前,我們宣布了 Dart 空安全測試版,這是一項主要的生產力功能,旨在幫助您避免空錯誤。說到空值,在 /r/dart_lang subreddit 中,一位使用者最近問道

但是為什麼我們仍然擁有/想要空值?為什麼不完全擺脫它呢?我目前也在玩 Rust,它根本沒有空值。所以似乎沒有它也能活下去。

我喜歡這個問題。為什麼完全擺脫空值?本文是我在該討論串中回答內容的擴展版本。

簡短的答案是,是的,完全有可能在沒有空值的情況下生存,像 Rust 這樣的語言就是這樣做的。但是程式設計師確實會使用空值,所以在我們可以將其移除之前,我們需要了解為什麼要使用它。當我們在確實擁有它的語言中使用它時,空值通常什麼?

事實證明,空值通常用於表示值的缺失,這非常有用。有些人沒有中間名。有些郵寄地址沒有公寓號碼。有些怪物在你殺死它們時不會掉落任何寶藏。

在這種情況下,我們想要一種表達方式:「這個變數可以具有 X 類型的值,或者它可能根本沒有值。」那麼問題是如何建模呢?

一種選擇是說一個變數可以包含預期類型的值,或者它可以包含魔術值 null。如果我們在值為 null 時嘗試使用它,就會出現執行時錯誤。這就是 Dart 在空安全之前所做的,SQL 所做的,Java 對非基本類型所做的,以及 C# 對類類型所做的。

但是執行時失敗很糟糕。這意味著我們的使用者會遇到這個錯誤。我們程式設計師寧願在他們遇到之前就發現這些錯誤。事實上,如果我們能夠在我們執行程式之前就發現錯誤,我們會很高興。那麼我們如何以類型系統理解的方式對值的缺失進行建模呢?換句話說,我們如何給「可能缺失」的值和「肯定存在」的值不同的靜態類型?

主要有兩種解決方案:

  1. 使用選項或 maybe 類型
  2. 使用可空類型

解決方案 1:選項類型

這就是 ML 和大多數源自 ML 的函數式語言(包括 Rust、Scala 和 Swift)所做的。當我們知道我們肯定會有一個值時,我們只使用底層類型。如果我們寫 int,則表示「這裡肯定有一個整數」。

為了表示一個可能缺失的值,我們將底層類型包裝在一個 選項類型 中。所以 Option<int> 表示一個值,它可能是一個整數,也可能什麼都不是。它就像一個可以包含零個或一個項目的集合類型。

從類型系統的角度來看,intOption<int> 之間沒有直接關係。將它們視為不同的類型意味著我們不能意外地將可能缺失的 Option<int> 傳遞給預期接收真實 int 的東西。我們也不能意外地嘗試使用 Option<int> 好像它是一個整數一樣,因為它不支援任何這些操作。我們不能對 Option<int> 執行算術運算,就像我們不能對 List<int> 執行算術運算一樣。

要從底層類型的現有值(例如 3)建立選項類型的值,您可以像 Some(3) 一樣構造選項。要在值缺失時建立選項類型,您可以寫類似 None() 的內容。

為了使用儲存在 Option<int> 中的可能缺失的整數,我們必須首先檢查並查看值是否存在。如果存在,我們可以從選項中提取整數並使用它,就像從集合中讀取值一樣。具有選項類型的語言通常也具有良好的 模式匹配 語法,這為我們提供了一種優雅的方式來檢查值是否存在,如果存在則使用它。

解決方案 2:可空類型

另一種選擇 (heh) 是 Kotlin、TypeScript 和現在的 Dart 所做的。可空類型聯集類型 的一種特殊情況。

(題外話:這裡的命名非常令人困惑。選項類型——ML 和它的朋友們上面所做的——是 代數資料類型 的一種特殊情況。代數資料類型的另一個名稱是「區分聯集」。但是,儘管名稱中有「聯集」,但「區分聯集」與「聯集類型」卻大不相同。正如 Phil Karlton 所說,電腦科學中只有兩個難題:快取失效和命名。)

與選項類型方法類似,我們使用底層類型來表示一個肯定存在的值。所以 int 仍然表示我們絕對有一個整數。如果我們想要一個可能缺失的整數,我們可以使用 int? 可空類型。這個小小的問號是 int | Null 之類的聯集類型的語法糖。

就像選項類型一樣,可空類型不支援與底層類型相同的操作。類型系統不允許我們嘗試對可空 int 執行算術運算,因為這是不安全的。同樣,我們不能將可空整數傳遞給需要實際整數的東西。

然而,類型系統比選項類型更靈活一些。類型系統理解聯集類型是其分支的超類型。換句話說,intint? 的子類型。這意味著我們可以將肯定存在的整數傳遞給預期接收可能存在的整數的東西,因為這樣做是安全的。這是一個向上轉換,就像我們可以將 String 傳遞給接收 Object 的函數一樣。Dart 只禁止我們反過來——從可空到不可空——因為那將是一個向下轉換,而這些可能會失敗。

當我們有一個可空類型的值,並且我們想要查看是否存在實際值或 null 時,我們會像在 C 或 Java 中自然地那樣以命令式方式檢查該值:

1
2
3
4
5
foo(int? i) {
if (i != null) {
print(i + 1);
}
}

然後,語言使用 流程分析 來確定程式的哪些部分受到這些檢查的保護。分析確定只有在變數不為 null 時才能到達程式碼,因此在這些區域內,類型系統會將變數的類型收緊為不可空。因此,在這裡,它將 i 視為在 if 語句內具有 int 類型。

語言應該採取哪種解決方案?

因此,當我們 Dart 團隊決定讓語言以更安全的方式處理 null 時,我們應該如何選擇解決方案 1 或 2?我們可以從觀察我們的使用者開始。他們想要如何編寫檢查缺失值的程式碼?在函數式語言中,模式匹配是主要的控制流程結構之一,那裡的使用者對它非常熟悉。使用選項類型和模式匹配在這種風格中是很自然的。

在源自 C 的命令式語言中,像我之前的範例這樣的程式碼是檢查 null 的慣用方法。使用流程分析和可空類型使熟悉的程式碼能夠正確安全地工作。事實上,在 Dart 中,我們發現大多數現有程式碼在新類型系統下已經是靜態空安全的,因為新的流程分析可以正確地分析已經編寫的程式碼。

(這在某種程度上並不令人驚訝。大多數程式碼在處理 null 方面已經是動態正確的。如果沒有,它會一直崩潰。大部分工作只是使類型系統足夠聰明,以便看到該程式碼已經正確,從而使用者的注意力集中在少數不正確的部分。)

因此,如果我們的目標是最大限度地提高熟悉度和使用者舒適度(這語言設計中的重要標準),我們應該遵循我們語言的控制流程結構為我們設定的路徑。

表示缺失和存在

有一種更深層次的方法來處理這個問題,基於選項類型和可空類型的表示方式之間的差異。這種表示方式的差異迫使我們做出一些關鍵的取捨,而這些取捨可能會使我們傾向於某個方向。

在第一種方法中,選項類型的值具有與底層值不同的執行時表示。假設我們在 Dart 中選擇了選項類型,您建立了一個選項類型,然後將其向上轉換為 Object

1
2
3
var optionalInt = Some(3);
Object obj = optionalInt;
print(obj is int); // false

請注意最後一行。Option<int> 值,即使存在,也不像底層類型的值。Some(3)3 是不同的、可區分的

【文章翻譯】Announcing Dart null safety beta

【文章內容使用 Gemini 1.5 Pro 自動產生】

開始將套件遷移到更健全、更安全的狀態

此文章同時發布於 Dart 部落格 上。

今天,我們宣佈 Dart 和 Flutter 的健全空安全功能已進入 Beta 階段。空安全是我們最新的主要生產力功能,旨在 幫助您避免空錯誤,這是一種通常難以發現的錯誤。如果您想快速了解為什麼我們對空安全感到兴奋,請查看這部新影片:

隨著空安全功能升級到 Beta 階段, 是時候開始對數千個在 pub.dev 上提供的套件進行社群遷移了。我們已經遷移了 Dart 核心函式庫、Flutter 框架以及 超過 40 個 Dart 和 Flutter 套件。我們希望看到社群透過遷移他們的套件來擁抱空安全性。

Timeline of Dart sound null safety support, from Technical Preview 1 to Stable in early 2021

隨著 Beta 版本的发布,我們也開始了在發佈穩定版空安全功能之前的最後衝刺。我們希望您能使用此功能,並告訴我們哪些部分可以改進,哪些 UI 訊息可以變得更容易理解,或者哪些文件可以變得更清晰。我們 **非常期待 您的回饋**。

選擇加入空安全功能

在我們討論空安全功能的遷移之前,重要的是要重申(如我们在空安全原则 中所述),您可以控制何时开始采用空安全功能。應用程式和套件只有在它们的最小 Dart SDK 约束 至少为 Dart 2.12 预览版本时才会使用空安全功能:

1
2
environment:
sdk: ">=2.12.0-0 <3.0.0"

要体验这一点,请尝试创建一个小的空安全版 hello 应用程序(例如,使用 dart create),其中包含如下所示的代码。然后,您可以尝试在更改SDK约束之前和之后运行该应用程序,以及运行 dart pub get,并体验程序行为的變化。(请确保使用在 dart –version 中报告 2.12 的 SDK。)

1
2
3
4
5
6
7
8
9
**bin/hello.dart:**
...
void main() {
var hello = 'Hello Dart developers';
if (someCondition) {
hello = null;
}
print(hello);
}
1
2
**在更改 SDK 约束之前:**
$ dart run
1
null
1
2
**在更改 SDK 约束之后(并运行 dart pub get):**
$ dart run
1
2
3
bin/hello.dart:6:13: Error: Null can't be assigned to a variable of type 'String' because 'String' is not nullable.
hello = null;
^

遷移到空安全功能

要將套件(或簡單的應用程式)遷移到空安全功能,請遵循以下五个步骤,这些步骤在 dart.dev 上的 遷移指南 中有完整的說明。

第 1 步:檢查您的相依性是否已準備好

我們強烈建議您按照順序遷移程式碼,先遷移相依性圖的葉子节点。例如,如果 C 相依於 B,而 B 相依於 A,請先將 A 遷移到空安全功能,然后是 B,最后是 C。此顺序适用于 A、B 和 C 是函式庫、套件还是应用程序。

Illustration of dependency order vs. migration order

為什麼順序很重要?雖然您可以在相依性遷移之前取得一些遷移程式碼的進展,但如果您在相依性遷移期間更改其 API,您可能會冒著需要進行第二次遷移的風險。如果您的幾個相依性不是空安全的,請考慮使用在 pub.dev 上列出的每個套件的聯絡資訊來聯繫套件發佈者。

驗證相依性是否已準備好

若要驗證您的應用程式或套件是否已準備好開始遷移,您可以在空安全模式下使用 dart pub outdated。以下範例顯示,如果此應用程式將其相依性升級到如 可解析 欄位中列出的路徑、進程和 pedantic 的預覽版本,則它已準備好進行遷移。

Screenshot of `dart pub outdated` output

如果空安全支援在次要新版本中可用,您將在 可升級 欄位中看到它們。通常,空安全支援將在主要新版本中可用;在这种情况下,您将看到在 outdated 输出的 可解析 下列出的版本。若要升級到這些版本,請編輯您的 pubspec.yaml 檔案以允許這些主要版本。例如,您可能會將 process: ^3.0.13 更改為 process: ^4.0.0-nullsafety。

您還可以在 pub.dev 上使用套件頁面上的新 空安全 標籤(例如 collection 1.15)和新的 進階搜尋 空安全搜尋選項 來查找具有空安全支援的套件。

Screenshot of pub.dev search

第 2 步:使用遷移工具進行遷移

如果您的相依性已準備好,您可以繼續使用遷移工具 dart migrate 來遷移您的應用程式或套件。

遷移工具是互動式的,因此您可以審查工具推斷出的可空性屬性。如果您不同意工具的任何結論,您可以加入可空性提示以更改推斷。加入幾個遷移提示可能會對遷移品質產生重大影響。

Screenshot of the migration tool UI

少數 Dart 套件作者已經使用空安全功能的早期預覽版本測試了遷移,他們的回饋令人鼓舞。遷移指南中提供有關如何使用遷移工具的額外提示。

第 3 步:靜態分析您的遷移程式碼

在您的 IDE 或命令列中使用 pub get 更新您的套件。然後使用您的 IDE 或命令列對您的 Dart 程式碼執行靜態分析:

1
2
$ dart pub get
$ dart analyze

或在您的 Flutter 程式碼上:

1
2
$ flutter pub get
$ flutter analyze

第 4 步:確保測試通過

運行您的測試,并确保它们通过。您可能需要更新預期為空值的測試,以防您更改了套件程式碼,使其不再允許為空。

第 5 步:發佈您的空安全套件

遷移完成且測試通過後,您可以將套件作為預覽版本發佈。以下是最佳實務的簡要摘要:

  • 將您的版本號碼增量到下一個主要版本(例如,從 2.3.x 到 3.0.0)。此最佳實務可確保您的套件使用者不會在他們準備好使用空安全功能本身之前升級到它,並且它讓您能夠自由地重構 API 以最佳地利用空安全功能。
  • 將套件的版本設定為 pub.dev 上的預覽版本。(例如,使用 3.0.0-nullsafety.0,而不是 3.0.0。)

有關遷移和版本控制的完整詳細資訊,請參閱 遷移指南

健全空安全的優點

我們之前關於空安全功能技術預覽的部落格文章 在 Dart 中在 Flutter 中 已經透過許多範例討論了空安全的優點。現在,空安全功能即將完成,我們看到了這種好处的几个实际例子。

更安全的程式碼

就在最近,我們 發現了 Flutter 主頻道中的一个錯誤,其中各種 flutter 工具命令在某些機器設定上會因空錯誤而崩潰:方法 ‘>=’ 被調用於 null 上。潜在问题是最近的一个添加了对检测 Android Studio 4.1 的支持的拉取请求。该 PR 添加了类似于以下内容的代码:

1
2
3
4
5
6
final int major = version?.major;
final int minor = version?.minor;
if (globals.platform.isMacOS) {
/// Android Studio 的插件路径在 4.1 版本之后发生了变化。
if (major >= 4 && minor >= 1) {
...

你能找到错误吗?由于 version 可能会为 null,major 和 minor 也可能会为 null。这个错误在孤立情况下似乎很容易发现,但在实践中,即使是像 Flutter 存储库中使用的严格代码审查流程,也会经常出现类似的代码。使用空安全功能,静态分析 会立即发现这个问题

Screenshot of analysis output in an IDE

这是一个非常简单的错误。在 Google 内部早期使用空安全功能的代码中,我们已经看到更多复杂的错误被发现,然后通过空安全功能解决。以下是几个例子:

  • 一个内部团队发现,他们经常检查代码中的空值,而空安全功能知道这些空值永远不会为 null。这个问题最常出现在使用 protobuf 的代码中,其中可选字段在未设置时返回默认值,而不会返回 null。这导致代码错误地检查默认条件,因为混淆了默认值和 null 值。
  • Google Pay 团队发现他们的 Flutter 代码中的错误,这些错误在尝试在 Widget 上下文之外访问 Flutter State 对象时会导致失败。在空安全功能之前,它们会返回 null 并隐藏错误;使用空安全功能,健全的分析确定这些属性永远不会为空,并抛出一个分析错误。
  • Flutter 团队发现一个错误,如果将 null 传递给 Window.render() 中的 scene 参数,Flutter 引擎可能会崩溃。在空安全功能迁移期间,他们添加了一个提示,以 将 Scene 标记为不可为空,并且能够轻松地防止潜在的应用程序崩溃,如果传递了 null,这些崩溃可能会被触发。

在編譯過程中利用健全的空安全功能

Dart 空安全功能的健全性還有一個令人歡迎的含義:這意味著 Dart 編譯器可以利用可空性資訊。這可能會使您的程式更小、更快。我們還沒有很多實際應用程式完全遷移到健全的空安全功能(因為我們現在才開始進行這些應用程式相依的套件的生態系統遷移),但我們從核心框架中看到了非常令人鼓舞的結果。

我們最近對 hello_world 範例進行了測試重新編譯,以測量空安全功能對應用程式大小的影響。這是一個最簡單的範例,它只會顯示「hello world」。在 比較 編譯後程式碼的總體大小時,未壓縮的(安裝在設備上的)程式碼大小縮小了 3.5%,而沒有做任何其他事情,只是使用健全的空安全功能重新編譯。這有可能實現,儘管這個應用程式只有 10 行程式碼,因為所有包含的函式庫的程式碼大小都縮小了;例如,Flutter 框架本身(套件:flutter)縮小了 3.9%。

至於程式碼速度,強制執行健全的類型系統可能會增加開銷。但是,減少空檢查也可能會使程式碼執行得更快。我們對基准測試的初步分析表明,效能與以前的版本相當,並且新的額外類型資訊為我們在未來進行新的效能改進提供了潛力。我們計劃在未來的部落格文章中更多地介紹我們的效能工作。

在某些情况下,我们已经看到空安全功能带来了性能提升,通常是在迁移到空安全功能时发现了代码逻辑中的缺陷。例如,我们在 Flutter 网页文字布局缓存中发现了一个问题。这个缓存使用了一个可为空的键,然后使用了一些逻辑来在为空时使用 TextAlign.start。这种逻辑导致缓存出现缺陷,即使元素仍然具有默认值,它们看起来也会像改变了一样。因此,经常出现缓存未命中。添加一个不可为空的 textAlign getter 有助于修复缓存缺陷,从而在文字被缓存的情况下,使文字渲染性能 提高了 14 倍

立即開始吧!

包含空安全功能的 Dart 和 Flutter 的 Beta 版本今天已準備就緒。如果您使用 Flutter 開發,您可以使用 flutter channel beta 然後 flutter upgrade 切換到 Beta 版本。否則,您可以從 Dart SDK 檔案 中獲取獨立的 Dart SDK。

如果您開發套件,我們鼓勵您閱讀我們的 遷移指南 並規劃您的遷移。請 告知我們 您遇到的任何問題或建議。

如果您是應用程式開發人員,您可能更希望延遲遷移,直到該功能出现在我們的穩定通道中。我們計劃快速解决 Beta 版本的回饋,修复任何剩余的问题。很难确定空安全功能将在稳定版中发布的确切时间,但我们预计将在明年年初。

感謝您在我們努力使 Dart 變得更加健壯,以及使 Flutter 變得更加强大的過程中提供支持和回饋!


宣佈 Dart 空安全功能 Beta 版本 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章翻譯】Announcing Dart null safety beta

【文章內容使用 Gemini 1.5 Pro 自動翻譯產生】

宣佈 Dart 空安全 Beta 版

此文章交叉發佈於此處和 Flutter 部落格

今天我們宣佈 Dart 和 Flutter 的 Beta 版已提供完善的空安全功能。空安全是我們最新的主要生產力功能,旨在幫助您避免空值錯誤,這是一類通常難以發現的錯誤。如果您正在尋找我們為何對空安全感到興奮的快速摘要,請查看這部新影片:

隨著空安全進入 Beta 版,是時候開始社群遷移 pub.dev 上可用的數千個套件了。我們已經遷移了 Dart 核心程式庫、Flutter 架構,以及超過 40 個 Dart 和 Flutter 套件。有了這些,我們希望看到社群透過遷移他們的套件來擁抱空安全。

Timeline of Dart sound null safety support, from Technical Preview 1 to Stable in early 2021

隨著 Beta 版的推出,我們也開始在發佈空安全功能的穩定版本之前的最後階段。我們希望您能使用此功能,並讓我們知道它的哪些部分可以改進,UI 訊息是否可以更容易理解,或者文件是否可以更清晰。我們**非常期待收到您的回饋**。

選擇加入空安全

在我們討論空安全遷移之前,需要重複的是(如我們的空安全原則中所述),您可以控制何時開始採用空安全。只有當應用程式和套件的最低 Dart SDK 限制 至少是 Dart 2.12 預發佈版時,它們才會以空安全模式執行:

1
2
environment:
sdk: ">=2.12.0-0 <3.0.0"

要體驗這一點,請嘗試建立一個小的空安全 hello 應用程式(例如,使用 dart create),其中包含如下所示的程式碼。然後,您可以嘗試在更改 SDK 限制並執行 dart pub get 之前和之後執行應用程式,並體驗程式行為的變化。(確保使用在 dart --version 中報告 2.12 的 SDK。)

1
2
3
4
5
6
7
8
9
// bin/hello.dart:
...
void main() {
var hello = 'Hello Dart developers';
if (someCondition) {
hello = null;
}
print(hello);
}
1
2
# 更改 SDK 限制之前:
$ dart run
1
null
1
2
# 更改 SDK 限制之後(並執行 dart pub get):
$ dart run
1
2
3
4
bin/hello.dart:6:13: Error: Null can't be assigned to a variable of type 'String' because 'String' is not nullable.

hello = null;
^

遷移至空安全

要將套件(或簡單的應用程式)遷移至空安全,請按照以下五個步驟操作,這些步驟在 dart.dev 的遷移指南中已完整記錄。

步驟 1:檢查您的依賴項是否已準備就緒

我們強烈建議您按順序遷移程式碼,先遷移依賴圖的葉子。例如,如果 C 依賴於 B,而 B 依賴於 A,則先將 A 遷移至空安全,然後是 B,然後是 C。此順序適用於 A、B 和 C 是程式庫、套件還是應用程式。

Illustration of dependency order vs. migration order

為什麼順序很重要?儘管您可以在依賴項遷移之前在遷移程式碼方面取得一些進展,但如果您的依賴項在其遷移期間更改其 API,則您可能會冒險進行第二次遷移。如果您的某些依賴項不是空安全的,請考慮使用 pub.dev 上列出的每個套件的聯絡方式與套件發佈者聯繫。

驗證依賴項是否已準備就緒

要驗證您的應用程式或套件是否已準備好開始遷移,您可以使用空安全模式下的 dart pub outdated。以下範例顯示,如果此應用程式將其依賴項升級到 可解析 欄中列出的 pathprocesspedantic 的預發佈版本,則它已準備好遷移。

Screenshot of `dart pub outdated` output

如果在新的小版本中提供空安全支援,您將在 可升級 欄中看到它們。通常,在新的大版本中會提供空安全支援;在這種情況下,您將在過時輸出的 可解析 下看到列出的版本。要升級到這些版本,請編輯您的 pubspec.yaml 檔案以允許這些主要版本。例如,您可以將 process: ^3.0.13 更改為 process: ^4.0.0-nullsafety

您還可以使用套件頁面上的新 空安全 標籤(例如 collection 1.15)和新的進階搜尋 空安全搜尋選項 在 pub.dev 上找到具有空安全支援的套件。

Screenshot of pub.dev search

步驟 2:使用遷移工具進行遷移

如果您的依賴項已準備就緒,則可以使用遷移工具 dart migrate 繼續遷移您的應用程式或套件。

遷移工具是互動式的,因此您可以查看工具推斷出的可空性屬性。如果您不同意工具的任何結論,您可以加入可空性提示以更改推斷。加入一些遷移提示可以對遷移品質產生巨大影響。

Screenshot of the migration tool UI

我們已經讓少數 Dart 套件作者使用空安全的早期預覽版本測試遷移,他們的回饋令人鼓舞。遷移指南中包含有關如何使用遷移工具的更多提示。

步驟 3:靜態分析您遷移的程式碼

在您的 IDE 或命令列中使用 pub get 更新您的套件。然後使用您的 IDE 或命令列對您的 Dart 程式碼執行靜態分析:

1
2
$ dart pub get
$ dart analyze

或者在您的 Flutter 程式碼上:

1
2
$ flutter pub get
$ flutter analyze

步驟 4:確保測試通過

執行您的測試並確保它們通過。您可能需要更新預期空值的測試,以防您更改了套件程式碼以不再允許空值。

步驟 5:發佈您的空安全套件

當遷移完成且測試通過後,您可以將您的套件作為預發佈版本發佈。以下是最佳實務的簡要摘要:

  • 將您的版本號遞增到下一個主要版本(例如,從 2.3.x 到 3.0.0)。此最佳實務可確保您的套件的使用者在準備好自己使用空安全之前不會升級到它,並且讓您可以自由地重構 API 以最佳地利用空安全。
  • 在 pub.dev 上將您的套件作為預發佈版本進行版本控制和發佈。(例如,使用 3.0.0-nullsafety.0,而不是 3.0.0。)

有關遷移和版本控制的完整詳細資訊,請參閱遷移指南

完善空安全的好處

我們之前關於 Dart 和 Flutter 中空安全的技術預覽的部落格文章透過許多範例討論了空安全的好處。現在,隨著空安全即將完成,我們看到了此好處的一些真實範例。

更安全的程式碼

就在最近,我們在 Flutter master channel 中發現了一個錯誤,其中各種 flutter tool 命令會在某些機器配置上因空值錯誤而崩潰:在空值上呼叫了方法 '>='。根本原因是最近的一個拉取請求,用於加入對偵測 Android Studio 4.1 的支援。該 PR 加入了如下程式碼:

1
2
3
4
5
6
final int major = version?.major;
final int minor = version?.minor;
if (globals.platform.isMacOS) {
/// Android Studio 4.1 版之後的 Plugin 路徑已更改。
if (major >= 4 && minor >= 1) {
...

您能發現錯誤嗎?因為 version 可能為空,majorminor 也可能為空。這個錯誤在這裡單獨看來似乎很容易發現,但在實務中,這樣的程式碼總是會溜走,即使是像 Flutter 儲存庫中使用的嚴格程式碼審查流程也是如此。使用空安全,靜態分析立即捕獲此問題

Screenshot of analysis output in an IDE

那是一個相當簡單的錯誤。在我們在 Google 內部程式碼中早期使用空安全的過程中,我們已經看到更多複雜的錯誤被捕獲,然後透過空安全解決。以下是一些範例:

  • 一個內部團隊發現,他們經常在空安全知道永遠不會為空的程式碼中檢查空值。此問題最常見於使用 protobuf 的程式碼中,其中可選欄位在未設定時返回預設值,而不是空值。這會導致程式碼透過混淆預設值和空值來錯誤地檢查預設條件。
  • Google Pay 團隊在他們的 Flutter 程式碼中發現了錯誤,在嘗試在 Widget 上下文之外存取 Flutter State 物件時,它們會失敗。在空安全之前,這些會返回空值並掩蓋錯誤;使用空安全,完善的分析確定這些屬性永遠不會為空,並拋出分析錯誤。
  • Flutter 團隊發現了一個錯誤,如果將空值傳遞給 Window.render() 中的 scene 參數,Flutter 引擎可能會崩潰。在空安全遷移期間,他們加入了一個提示以將 Scene 標記為不可為空,然後能夠輕鬆地防止如果傳遞空值會觸發的潛在應用程式崩潰。

在編譯期間利用完善的空安全

Dart 空安全的完善性還有另一個令人歡迎的含義:這意味著 Dart 編譯器可以利用可空性資訊。這可能會使您的程式更小、更快。我們還沒有很多真實世界的應用程式完全遷移到完善的空安全(因為我們現在才剛剛開始這些應用程式所依賴的套件的生態系統遷移以實現完善性),但我們從核心架構中看到了非常令人鼓舞的結果。

我們最近對 hello_world 範例進行了測試重新編譯,以測量空安全對應用程式大小的影響。這是一個最小化的範例,只顯示「hello world」。在比較編譯程式碼的總大小時,未壓縮的(安裝在設備上的)程式碼大小縮小了 3.5%,除了使用完善的空安全重新編譯之外沒有做任何事情。儘管這個應用程式只有 10 行程式碼,但這也是可能的,因為所有包含的程式庫的程式碼大小都縮小了;例如 Flutter 架構本身(package:flutter)縮小了 3.9%。

至於程式碼速度,必須強制執行完善的型別系統可能會增加開銷。但是,進行更少的空值檢查也可能會使程式碼更快。我們對基準測試的初步分析顯示,效能與以前的版本相當,並且新的額外型別資訊為我們未來進行新型別的效能改進創造了潛力。我們計畫在未來的部落格文章中詳細介紹我們的效能工作。

在某些情況下,我們已經看到空安全會帶來效能提升,通常是在遷移至空安全時發現了程式碼邏輯中的缺陷。例如,我們在 Flutter 網頁文字佈局快取中發現了一個問題。此快取使用的鍵是可為空的,然後是一些在為空時使用 TextAlign.start 的邏輯。此邏輯導致快取中的缺陷,即使元素仍然具有預設值,它們看起來也像已更改。因此,經常發生快取未命中。加入一個不可為空的 textAlign getter 有助於修復快取缺陷,從而在文字被快取的情況下使文字渲染效能提高 14 倍

立即開始!

包含空安全的 Dart 和 Flutter 的 Beta 版本今天已經準備好了。如果您使用 Flutter 進行開發,您可以使用 flutter channel beta 切換到 Beta,然後使用 flutter upgrade。否則,您可以從 Dart SDK 存檔 中獲取獨立的 Dart SDK。

如果您開發套件,我們鼓勵您閱讀我們的遷移指南並規劃您的遷移。如果您有任何問題或建議,請告知我們

如果您是應用程式開發人員,您可能希望延遲遷移,直到該功能進入我們的穩定頻道。我們計畫快速處理 Beta 版的回饋,修復任何剩餘的問題。很難說明空安全何時會在穩定版本中發佈的具體時間表,但我們認為是明年年初。

感謝您的支援和回饋,我們正在努力使 Dart 成為更強大的語言,使 Flutter 成為更強大的架構!


宣佈 Dart 空安全 Beta 版 最初發佈在 Dart 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章翻譯】Deprecation Lifetime in Flutter

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter 中的棄用生命週期

新的一年即將到來,Flutter 團隊正在為 2021 年的全新開始做好準備。

為此,我們將從 Flutter 架構中移除一些已棄用的 API。

在 Flutter 架構中移除棄用並非新鮮事。我過去也曾經 自己處理過快速搜尋 結果顯示,過去移除棄用沒有定義的時間軸或排程,因為我們的 棄用策略 並沒有規定何時移除它們。由於我們希望為使用者提供一致且可靠的體驗,因此我們決定為棄用建立標準生命週期。

本文將討論我們目前針對重大變更和棄用的策略,以及這些策略如何付諸實行,以及如何發展以為使用者提供更好的體驗。

Flutter 中的重大變更

Photo by CHUTTERSNAP on Unsplash

在 Flutter 中棄用程式碼的流程始於我們的 重大變更策略。棄用被視為重大變更,這意味著它們必須遵循 公開設計文件 指南,該指南要求一段時間用於討論。(此提案的設計文件為 實作棄用生命週期。) 除了提供設計文件外,我們還會在 Flutter 貢獻者 Discord 和受歡迎的社群,例如 flutter-announceflutter-dev 上發佈訊息,所有這些都在進行任何變更之前。這是我作為工程師最喜歡的流程之一:我能夠聽到您的意見。我們很棒的社群在這個流程中非常活躍,這也讓我們變得更好。在多次場合中,我看到一個功能的設計在透過這些管道發佈後有了很大的改進,這全都是因為社群的回饋。

重大變更的作者會遷移受重大變更影響的客戶程式碼。在我們重大變更策略的最後一次更新中,我們 邀請 您將測試提交到我們的 客戶測試儲存庫。這些測試是我們標誌著變更會造成中斷的訊號,我們承諾會在進行變更之前與測試作者合作遷移他們的程式碼。

我們還為我們的重大變更提供 遷移指南。這些指南旨在幫助使用者在更新到最新版本的 Flutter 後遷移他們的程式碼。如果您看過我們的 發行公告 之一,我們也會在特定版本中指出中斷,並引導使用者到有用的資源,幫助他們更新應用程式。

過去的調查 中,我們詢問使用者他們對重大變更的偏好。我們了解到使用者認為重大變更使程式碼更乾淨,對他們很有價值,這就是為什麼我們通常更喜歡重大變更而不是棄用的原因。根據研究:

總體而言,78% 的人表示他們更喜歡導致最乾淨的 API 的重大變更;這也使 API 更易於學習和使用。

我們的重大變更策略基於此研究。與所有規則一樣,總是會有例外。我最近 棄用了一些非常受歡迎的方法,改用新的 Widget。如果我們知道特定變更會造成重大中斷,影響許多使用者,我們就會棄用。棄用允許遷移緩衝期,同時仍然提供重大變更策略所產生所有工具。

日漸老舊的棄用

Photo by Dilyara Garifullina on Unsplash

遷移緩衝期從棄用在 穩定頻道 上發佈時開始。緩衝期結束的時間軸為 1 個日曆年或 4 個穩定版本,取較長者。為了制定出我們認為舒適的時間軸,我們查看了我們的成長率和採用率,並評估了一些已公開發佈的 Flutter 應用程式和套件。

我們希望使用者能夠預期這個排程,而不是擔心下一個版本是否會因為棄用消失而帶來意外的升級障礙。我們還希望確保我們提前通知這些變更,並且我們承諾在開始移除棄用之前,會宣布棄用即將結束生命週期。本著這種精神,我想要與您分享 第一批即將結束生命週期的棄用,現在 Flutter 1.22 已推出。

由於這是我們第一次實施這項策略,因此有很多棄用,其中有些甚至早於 Flutter 1.0!其中一些棄用也早於我們的重大變更策略。我們將會為所有這些棄用努力建立遷移工具和指南。預計在我們下一個穩定版本推出之前,這些棄用將從 Flutter 架構中移除,並會在移除時透過我們通常的管道發布公告。

在我們開始實施這些變更的同時,我們希望聽到您的意見!我們始終歡迎您將測試提交到我們的客戶測試儲存庫,我們會在進行中斷之前與您合作遷移您的程式碼。若要進一步了解測試儲存庫以及如何提交測試,請查看 Flutter 測試 README。在進行這些變更時,我們將透過 Flutter 貢獻者 Discordflutter-announceflutter-dev 頻道通知您並徵求您的回饋。因此,如果您尚未加入其中一個社群,請務必加入!我們期待收到您的訊息,並與您合作。


Flutter 中的棄用生命週期 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

http://creativecommons.org/licenses/by/4.0/

【文章翻譯】New ad formats for Flutter

【文章內容使用 Gemini 1.5 Pro 自動產生】

為 Flutter 行動廣告 Plugin 開放嵌入式橫幅和原生廣告的 Beta 程式

有許多方法可以讓行動應用程式開發人員獲得工作的報酬。透過廣告變現應用程式是許多行動開發人員(包括使用 Flutter 的開發人員)的熱門選擇之一。

原生廣告格式支援,特別是 Flutter 的前五名熱門功能請求之一。Flutter 團隊先前提供的 Google 廣告 Plugin(也稱為 firebase_admob Plugin)支援覆蓋橫幅、插頁式和獎勵影片,但無法渲染嵌入式橫幅或原生廣告等格式。

嵌入式橫幅和原生廣告

顧名思義,嵌入式橫幅廣告讓您將廣告單元整合為 Flutter 視圖的一部分,而不是將橫幅覆蓋在 UI 上。同樣地,原生廣告允許您設計一種感覺像是您應用程式內容自然一部分的廣告體驗。一些開發人員告訴我們,缺少嵌入式橫幅和原生廣告會阻礙他們建立美麗自然的廣告體驗的能力,而另一些開發人員則表示,沒有這些功能可能會阻止他們將 Flutter 採用到他們的應用程式中。

為了響應您的請求,我們一直在開發對這些格式的支援。一年前,我們開始與 Google Ads 密切合作,為 Flutter 實作健全且值得信賴的嵌入式廣告解決方案。我們還完全重構了 Plugin 程式碼,以提高效能和穩定性。今天,在完成實作和一系列 Alpha 測試後,我們很高兴地宣布,此更新的 Plugin 的 beta 版本將提供僅限邀請的存取權。

藉由這個 beta 測試,我們在現有 Plugin 上進行了建置,並為 AdMob 和 Ad Manager 新增了對新格式的支援。與所有 beta 版本一樣,仍然存在一些需要解決的問題,而且功能支援可能會在未經通知的情況下發生變化。如果被選為參與 beta 測試,我們強烈建議您在將應用程式發佈給使用者之前,在您的應用程式中徹底測試整合。

立即申請

若要申請參與我們的 beta 測試,請填寫 我們的申請表。我們特別尋找已有應用程式上架且願意與我們團隊合作,在他們的生產應用程式中使用我們的 beta 版本的客戶。如果您被選為參與 beta 測試,您將收到一封包含更多說明的電子郵件。

根據此 beta 測試的結果,我們預計在 2021 年初向更廣泛的受眾開放使用。

我們希望嵌入式橫幅和原生廣告能幫助您為您的 Flutter 應用程式解鎖更多收入增長。

祝您程式設計和廣告愉快!


Flutter 的新廣告格式 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

http://creativecommons.org/licenses/by/4.0/

【文章翻譯】Accessible expression with Material Icons and Flutter

【文章內容使用 Gemini 1.5 Pro 自動產生】

使用 Material Icons 和 Flutter 打造可存取的表達力

Material Design 和 Flutter 都能幫助開發人員打造出靈活、可存取且富於表現力的體驗,同時提供出色的效能和效率。現在,我們很高興為您提供更多方法來使用改進的 Material Icons 支援在 Flutter 中建立獨特的 UI。

Material Icons 是為常見動作和項目精心設計的圖示,包括從用於導航的簡單箭頭和指示器,到代表可存取性、錯誤回報,甚至洗手等概念的圖示。

Flutter 現在支援所有四種圖示樣式——填滿、描邊、銳利和圓形——幫助您讓您的應用程式或網站對使用者來說熟悉且易於存取,同時讓您以獨特的方式傳達您的品牌。而且,透過對樹狀搖動的支援,Flutter 會優化您的應用程式建構,只包含您正在使用的圖示,從而使載入時間和記憶體使用更加有效率。

以下是一些展示您在 Material 目錄中找到的選項範圍的圖示。您可以在 Material.io 上瀏覽完整的圖示集並下載位圖或向量版本以供在您喜愛的設計工具中使用,或在 Icons API 頁面上查看 Flutter 版本。

Sample of 4 icons: shopping_cart, chat, masks, wash shown in the 4 supported styles: filled, outlined, rounded, sharp.
Sample of 4 icons: shopping_cart, chat, masks, wash. Displayed in the 4 supported styles: filled, outlined, rounded, sharp.

入門

若要開始使用 Icon 類別,請確保在您專案的 pubspec.yaml 檔案中設定 uses-material-design: true。這會告訴 Flutter 將圖示資產包含在您的應用程式中。

Flutter 中的圖示透過圖示字體以向量形式提供,因此您可以無限調整大小和顏色,而無需擔心影像品質下降。在 GitHub 上查看用於生成上述圖示集的程式碼。

不要跳過語義標籤!

為了讓使用螢幕閱讀器等輔助科技的使用者能夠有效地導航您的應用程式或網站,提供有意義且上下文適當的語義標籤非常重要。

預設情況下,螢幕閱讀器會朗讀螢幕上顯示的任何文字。為了將圖示等視覺元素準確地轉換為基於文字的 UI,您需要仔細標記這些元素。

例如,當圖示與動作元素(如按鈕)結合使用時,您應該始終將語義標籤設定為描述使用者點擊該圖示時會發生什麼的字串。

Material.io 提供指南 來指示透過動作來表示 UI 元素。常見的錯誤是將語義標籤預設為圖示的名稱,而不是選擇該圖示時執行的動作。

an example of what to do: a Pencil icon with the label “edit” and what not to do: a Pencil icon with the label “Pencil”

若要進一步了解建立可存取的數位體驗的重要性,請參閱 flutter.dev 上的 可存取性

只發佈您使用的內容!

當您為發佈建構應用程式時,Flutter 編譯器會執行「樹狀搖動」,移除未使用的程式碼和資產(包括圖示),以優化應用程式的佔用空間,並幫助最大限度地減少下載和載入時間。可以使用您想要的任何圖示!在編譯期間,會生成一個自訂圖示字體,其中只包含專案中使用的圖示子集。這可以大幅減少二進制檔案的大小——所有人都能受益!

除了樹狀搖動之外,這裡還有一篇關於 縮減 Flutter 應用程式大小的最佳實務 的很棒社群文章。

向我們展示您的傑作!

全世界的開發人員都在使用 Material Icons 來確保在大型和小尺寸條件下都能保持可讀性和清晰度;這些圖示已針對在所有 Flutter 支援的平台和顯示解析度上美麗顯示而進行優化。

在 @MaterialDesign 和 @@FlutterDev 上關注我們,並展示您如何使用 Material Design 和 Flutter 打造出美麗、可存取的數位體驗!


使用 Material Icons 和 Flutter 打造可存取的表達力 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

Android app 上架流程

本篇文章主要介紹在2020年 Goolge 改版後的 Play Store Console 如何上架 Android App

首先到 Play Store Console 右邊點擊新增應用程式

填寫以下應用程式詳細資訊

  • 應用程式名稱:會顯示在商店的App名稱
  • 預設語言:預設App使用的語言,作為商店一開始提供的預設語言
  • 應用程式類型:分類只有遊戲與應用程式,目的是要把遊戲區分出來,日後可更改
  • 是否收費:設定App是否下載時需要費用,勾選收費後,需要至 付費應用程式 修改設定

最後同意 開發人員計畫政策美國出口法律 後,即可完成初始設定

接著進入到 資訊主頁

第一次設定時會出現 初始設定 提示,可依序點擊設定,該步驟都是必須完成的步驟,否則無法完成審查上架

應用程式存取權

設定 App 是否開放給全部使用者

或是部分功能有使用限制,需設定:

  • 名稱
  • 使用者名稱/電話號碼
  • 密碼
  • 任何操作說明

透過此可限制使用者下載應用程式

廣告

設定App中是否有廣告,若有勾選廣告則會在Play商店上顯示 含廣告內容 的標籤

內容分級

根據國際年齡分級聯盟(英語:International Age Rating Coalition,縮寫IARC)設計的簡化各國分級的內容分級問卷,降低產品評比的過程,參考資料

填寫內容分級問卷,讓使用者了解App的分類,及是否會有不宜兒童的內容

首先填寫電子郵件,問卷完成會寄送一份結果至該信箱

選擇 App 的類別,以 文藻校務通 為例,選擇 參考資訊、新聞或教育內容

根據選擇的類型,需填寫相關內容是否有未成年暴力色情訊息

完成後會顯示基本的報表,點擊右下角提交完成問卷

完成後,若日後想在修改問卷內容,需至右上角 點擊 Start new questionaire 重新提交問卷

目標對象

填寫詳細的App發布目標對象

首先點選 目標年齡層,主要是確認目標對象是不是兒童,若對象未滿13歲則需要新增隱私權政策

勾選 是否會引起兒童興趣,若上者點擊13歲以下,可勾選 宣稱適合兒童

最後點擊 儲存 完成目標對象和內容

接著就完成一半了~~

應用程式類別及詳細資料

應用程式分類,區分應用程式或遊戲的類別,在Play 商店中,也會有類別排名

接著設定商店的聯絡詳細資訊,分別為

  • 電子郵件地址 (必填)
  • 電話號碼
  • 網站

以上訊息皆會在Play商店上顯示

並勾選是否要在Play商店外行銷,讓外部網站可搜尋到你的App

完成後就只剩下最後一個步驟

商店資訊

首先會根據一開始設定的主要語言,設定 App 在 Play 商店的資訊,可根據不同語言,設定不同的商店資訊,可點擊 管理其他語言版本的翻譯內容 管理其他語言的內容

應用程式詳細資料

首先可設定

  • 應用程式名稱:App名稱,作為可供搜尋的關鍵字,上限50字
  • 簡短說明:可在App頁面首要看到簡短說明,上限80字
  • 完整說明:在點擊關於這個應用程式後顯示的完整說明

可參照 Play 商店對應位置

接著設定 應用程式圖示 會顯示在 Play 商店的圖示,限定尺寸為 512*512 的解析度,上傳後都會以橢圓裁剪顯示

主要圖片顯示於商店資訊的最頂端,可用於宣傳應用程式,大小限制 1024*500 解析度的圖片

螢幕截圖主要分為

  • 手機
  • 七吋平板電腦
  • 十吋平板電腦

基本上,對應類型的裝置截圖都適用,也可自行製作符合規定的尺寸的圖片,皆為使用 JPEG 或 24 位元 PNG 圖片,長寬比建議16:9

加入影片也會顯示於商店上

商店資訊設定完成後,若未來要修改都可直接修改,但修改後都需要等商店部署時間,通常都會為半天左右時間

上傳App至商店

發佈 的目錄下,選擇App目前要發布的方式,有分成

  • 正式版:會發布給商店中所有設置的地區
  • 公開測試:任何使用者可至 Play 商店點擊測試計畫,即可使用此版本
  • 封閉測試:由開發人員建立電子郵件清單,或是可透過連結加入測試計畫 https://play.google.com/apps/testing/{app id}
  • 內部測試:由開發人員建立電子郵件清單,或是可透過內部邀請測試連結:https://play.google.com/apps/internaltest/{test group id} 加入
  • 搶先註冊:若還沒發佈正式版時,可利用此功能,在Play商店中顯示搶先體驗的字樣,並提供測試人員特殊獎勵

不管利用哪種測試方式,接下來上傳App的方式都會相同,例如選擇 正式版 發布,並點擊右上方的 建立新版本

接著第一次上架時需點擊 同意使用 Google Play 應用程式簽署,Google 會管理你簽署所使用的金鑰,並且該金鑰只能提供給該 App 使用

若今天金鑰遺失,可請帳戶擁有者聯絡支援小組重新上傳金鑰

將利用 Android Studio 等等的 Android 編譯工具,將原生Android 的 Apk 或是 App Bundle 上傳至此頁面

每次新上傳的 版本號碼(version code) 皆需大於先前上傳的

關於金鑰使用詳細 可參考

版本詳細資訊

版本名稱會根據上傳的 ApkApp Bundle 命名

版本資訊會根據商店可提供的語言,以 XML 格式撰寫,將這次更新內容寫至 語言碼(language code)

完成後點擊儲存,並點擊檢查版本

接著會發現沒有設定提供地區

返回至上一頁的最上方,選擇 國家與地區 編輯針對正式版的發布國家/地區

若沒勾選,Play商店就不會發佈至此國家/地區

接著回到剛剛編輯的版本資訊,點擊 開始發布(正式版)

最後會跳回正式版的頁面,並顯示審查中

自 2019 年開始,Play 商店在第一次審查時,最久大約會至七天,爾後提交大約都是一下子就完成審查,並都是半天會完全部署至商店(所有使用者都可以看到更新)

iOS app 上架流程

本篇文章主要介紹在2020年 Apple 改版後的 App Store Connect 如何上架 iOS App

新增 App

App Store Connect 點擊 我的App

點擊 App 旁邊邊的 + 選擇 新的 App

註冊Identifier

憑證、識別碼及描述檔 註冊App的 Identifier

選擇 App IDs

選擇 App

Discription 填寫可以識別的名稱

App ID Prefix 選擇 Explicit 並填上與 Xcode 中的 Bundle Indentifier 相同的 ID

App ID Prefix 的 Bundle ID 上架後就不可修改

最後點擊 Continue 然後 Register 完成註冊

或是

懶人方法

使用 XcodeTarget 中的 Runner 選擇 Signing & Capabilities

選擇想要上架的Apple開發者帳號

並點擊 + Capability 隨意新增一個 Capability

此動作 Xcode 會自動註冊 Indentifier 至 App Store Connect

完成後再將其取消

沒取消的話審查時會納入審查範圍 要特別注意

接著填寫App基本資訊

  • 平台:選擇你的App會在哪些平台提供,若沒勾選可事後新增
  • 名稱:在Apple Store的名稱,無法跟已上架App相同,命名上需要先搶先贏,除非對方把App刪除或修改名稱,也是使用者搜尋時能找到你的App的首要途徑
  • 主要語言:首先可在商店提供的語言,若有發佈不同國家語系,可事後新增
  • 套件識別碼:選擇剛才新增的 Indentifier,選擇後就不能修改,對應到原生的 Bundle Indentifier
  • SKU:App ID 為獨一無二,可任意命名,填寫後不能修改,但不會公開顯示

App 資訊

新增 App 後,可先來 一般資訊 -> App 資訊,填寫 App 基本資訊,這邊會分兩個區塊,一個是可本地化資訊及一般資訊

可本地化資訊

  • 名稱:必填,為一開始輸入的 App 名稱
  • 副標題:必填,商店中會位於 App 名稱下方,建議使用簡短語句說明 App
  • 隱私權政策:必填,聲明你的 App 隱私權政策的網址,不限制格式

一般資訊

  • Apple ID:由 Apple 產生,作為網頁上的編號,可至 https://apps.apple.com/tw/app/id`${你的 Apple ID}`,找到你的App
  • 內容版權:聲明你的 App 是否有第三方內容,像是以校務通來說,資料來源於學校,就可以視為第三方內容
  • 年齡分級:必填,根據填寫 年齡分級問卷 的結果
  • 許可協議:必填,預設使用 《Apple 標準終端使用者許可協議》(EULA),可點擊自訂許可協議
  • 類別:必填,在商店的分類,可選擇兩個,也作為與同類型App排名的分類

定價與供應狀況

  • 價格排程:選擇你的App定價方式,最低免費到最高 32900元,使用者付費購買後90天內都可以反悔
  • 預定:第一次上架前會顯示,自訂日期在App成功發布後,會通知預定的使用者
  • 供應狀況:需先填寫供應國家與地區,若選擇停止供應,會從商店下架,直到重新供應為止
  • Mac 上的 iOS App:如果你的iOS App有使用到 Mac Catalyst (Flutter 目前不支援),會將你的iOS App發佈至 Mac App Store,若有發佈macOS App,則優先發布 macOS App
  • App發布方式:根據你的開發者帳號,若個人開發者帳號只能選擇公開在Apple Store,若是企業開發者帳號,則可以發布到私人的商店發布

App版本資訊

進入 App 版本資訊

首先設定 App預覽與截圖 可參考以下規格 每個至少三張

12.9 吋 iPad Pro 第三代 及 第二代 尺寸是可以相容的 故截圖第三代 可直接上傳到第二代

建議使用模擬器截圖 上傳完可用滑鼠拖曳改變顯示順序

螢幕尺寸說明 平台 截圖尺寸
iPhone 6.5 吋 iPhone 11 Pro Max、iPhone 11、iPhone X S Max、iPhone XR 1242 x 2688 像素(直向) 2688 x 1242 像素(橫向)
iPhone 5.5 吋 iPhone 8 Plus、iPhone 7 Plus、iPhone 6s Plus 1242 x 2208 像素(直向) 2208 x 1242 像素(橫向)
12.9 吋 iPad Pro(第三代) iPad Pro 2018、iPad Pro 2020 2048 x 2732 像素(直向) 2732 x 2048 像素(橫向)
12.9 吋 iPad Pro(第二代) iPad Pro 2017 2048 x 2732 像素(直向) 2732 x 2048 像素(橫向)

更多詳細資訊 可參考

接著填寫

  • 行銷宣傳文字:作為 App 行銷宣傳標語,建議簡短的文字,也要符合App的性質
  • 關鍵字:在商店搜尋時,透過關鍵字加強找到App,並使用逗點隔開
  • 描述:詳細介紹App的功能與特色
  • 支援URL:對應商店開發者網頁
  • 行銷URL:待補充
  • 版本:可參考 語意化版本,不限定兩碼或三碼,不能與先前定義的相同
  • 版權:宣告App版權的註解
  • 年齡分級:根據填寫 年齡分級問卷 的結果(需點擊編輯填寫)

對應在商店的位置可參考

年齡分級問卷

針對App的內容填寫是否有兒童不宜的

App審查資訊

蘋果在審查時都是採用 人工審查,審查過程都須填寫完整的資料

  • 登入資訊:若你的App有設計登入功能,需提供測試帳號給審查人員
  • 聯絡人資訊:當審查有問題時的聯絡人資訊,電話號碼需要加入國際冠碼
  • 備註:資訊則提供其他資訊供審查人員了解你的App,像是之前就被問過這幾個問題,爾後我都在新的App加入這些回答
    • Who is the target audience?
    • How do users obtain an account?
    • Is this app meant for internal distribution in your own company, in the company of one target client, or in multiple target clients’ companies?
    • In which countries will this app primarily be distributed?
    • If this app is meant for internal distribution, will the app be accessible by both internal and external partners? Or will it be exclusive to in-house employees?
      • 附件:可附上App操作影片,若你的App無法提供帳號測試,或是有些功能需要提供範例影片操作(ex.何時會使用到讀取wifi連線資訊的功能),都需要附上影片

建制版本

接著選擇要送至審查的App版本,需先透過Xcode Archive 後上傳至App Store Connect,點擊藍色按鈕

選擇對應想提交的版本,通常上傳完會需要一段時間處理,當完成處理都會email通知

屆時才會出現在這邊

接著選擇這次提交的出口合規資訊,點擊是否有使用加密功能,若點擊是的話,需要另外填寫出口法律資訊

廣告識別碼

最後是填寫是否有使用到 廣告識別碼,像是 Firebase Analytics 或是 Ad Mod 等第三方的廣告或分析工具,就需要聲明有使用到,若審查後發現錯誤,則需要重新上傳新的App版本

最後回到最上方點擊完成,並點擊審查,結著就會進入正在等待審查

通常審查時間已台灣都是晚上開始到半夜,對應到美國的白天時間,第一次審查都會比較久,大約2~3天,要耐心等待

但有時候會審查失敗,也會寄送 email 通知,可至連結查詢問題,並回覆審查人員

iOS Resolve Center : https://appstoreconnect.apple.com/apps/{apple id}/appstore/platform/ios/resolutioncenter?m=

macOS Resolve Center : https://appstoreconnect.apple.com/apps/{apple id}/appstore/platform/osx/resolutioncenter?m=

若審查成功,則會通知 Ready for Sale,完成這次版本審查

【文章翻譯】Dart sound null safety: technical preview 2

【文章內容使用 Gemini 1.5 Pro 自動產生】

宣布 Flutter 架構的空安全支援

Dart 在 Flutter 中扮演著特殊的角色,為開發人員功能(如熱重載)提供動力,並透過 Dart 的靈活編譯器技術,為行動、桌面和網頁實現跨平台應用程式。我們致力於使 Dart 語言成為 Flutter 應用程式開發人員最具生產力的語言;例如,我們加入了 UI-as-code 語言結構,以優化 Dart 語法,用於編寫 Flutter Widget 樹。

在 6 月份,我們提供了 Dart 空安全的首個技術預覽。今天是另一個重要的里程碑,我們已經 期待已久:我們宣布 健全的空安全 的第二個技術預覽,包括對 Flutter 架構的支援。

空安全是一個主要的生產力功能,可以幫助您避免空引用錯誤,這種類型的錯誤通常很難發現。作為額外的優點,此功能還可以實現一系列效能改進。我們非常期待您的回饋。

為什麼要使用空安全?

Dart 是一種類型安全的語言。這表示當您獲得某種類型的變數時,編譯器可以保證它屬於該類型。但是,類型安全本身不能保證變數不是空引用。

空引用錯誤非常普遍。在 GitHub 上搜尋會發現由於 Dart 程式碼中出現意外的空引用而導致的數千個問題,以及數千個嘗試解決這些問題的提交。試著看看您是否能在下面的 Flutter 應用程式中發現可空性問題,想像 Config 和 WeatherService 是應用程式使用的後端服務:

如果 getAppName() 返回空引用,這個應用程式肯定會失敗;在這種情況下,我們將傳遞空引用給 AppBar 標題中使用的 Text Widget。

但是,還有更多微妙的情況需要考慮:getTemperatures() 也可能返回空引用。在這種情況下,for 迴圈會失敗。或者 getTemperatures() 可以像預期一樣返回一個列表,但該列表可能包含空值,在這種情況下,我們將呼叫 round() 到空引用上,應用程式將會失敗。

空安全功能透過 驗證您的程式碼 來解決這些問題,就像您在輸入時一樣:

Screenshot of the preceding code with null errors.
利用空安全,Dart 會在您的程式碼中找到潛在的空引用錯誤。

利用空安全,您可以更有信心地推論您的程式碼。部署的應用程式中不再有惱人的運行時空引用解除引用錯誤。相反,您在編寫程式碼時會出現靜態錯誤。

空安全原則

Dart 空安全支援基於以下三個核心設計原則:

  1. 預設不可空引用。除非您明確告訴 Dart 變數可以為空引用,否則它將被視為不可空引用。我們選擇這一點作為預設值,因為我們發現不可空引用是 API 中最常見的選擇。
  2. 可遞增採用。有很多 Dart 程式碼。您可以選擇在您想要的時候遞增地逐漸遷移到空安全,然後逐部分地進行遷移。可以在同一個專案中使用空安全的程式碼和非空安全的程式碼。我們還將提供工具來幫助您進行遷移。
  3. 完全健全。Dart 的空安全是 健全 的。這表示我們可以信任類型系統:如果它確定某個東西不是空引用,那麼它 永遠 不會是空引用。這可以實現編譯器最佳化. 當您將整個專案和相依項目遷移到空安全後,您將完全享受到健全性帶來的優勢 - 不僅是更少的錯誤,而且還包括更小的二進位檔案和更快的執行速度。

讓我們更詳細地回顧一下這些設計原則。

1. 預設不可空引用

核心語法非常簡單。以下是一些以不同方式宣告的不可空引用變數。請記住,不可空引用是預設值,所以這些宣告看起來與今天一樣,但它們的含義發生了變化。

Dart 會確保您永遠不會將空引用指派給上述任何變數。如果您嘗試執行 widget = null,幾千行程式碼之後,您將得到一個靜態分析錯誤和紅色的波浪線,您的程式將拒絕編譯。

可空引用變數

如果您想要您的變數可以為空引用,您可以使用 ?,比如這樣:

您可以在函數參數和返回值中使用 ? 語法,也是如此:

但是,再次強調,夢想是您很少需要使用 ?。您的絕大多數類型將是不可空引用。

使用空安全提高生產力

空安全不僅僅是關於安全。我們還希望您在使用此功能時能夠提高生產力,這表示此功能必須易於使用。例如,請看以下程式碼,它使用 if 來檢查空引用值:

請注意,Dart 工具如何檢測到當我們通過該 if 語句時,loudness 變數不可能為空引用。因此,Dart 讓我們可以呼叫 clamp() 方法,而無需跳躍障礙。這種便利性是由一種稱為流程分析的功能實現的:Dart 分析器會像執行程式一樣遍歷您的程式碼,自動找出有關程式碼的更多資訊。

以下是一個示例,它顯示了一個情況,即 Dart 可以確定變數為不可空引用,因為我們始終將不可空引用值指派給它:

如果您移除上述任何指派(例如,透過刪除 statusText = 'Update failed'; 這行程式碼),Dart 無法保證 statusText 為不可空引用:您將得到一個靜態錯誤,您的程式碼將無法編譯。您可以 在 DartPad 中嘗試一下

2. 可遞增採用

由於空安全對我們的類型系統來說是一個如此基礎性的改變,如果我們堅持強制採用,這將是極其破壞性的。我們希望讓您自行決定何時是適當的時間,因此空安全是一個選擇性功能:您將能夠使用最新的 Dart 和 Flutter 版本,而無需在您準備好之前強制您啟用空安全。您甚至可以從尚未啟用空安全的應用程式或套件中相依於已經啟用空安全的套件。

一旦您選擇採用,我們強烈建議您按照順序遷移程式碼,相依關係圖的葉節點優先遷移。例如,如果 C 相依於 B,而 B 相依於 A,則先將 A 遷移到空安全,然後是 B,最後是 C。此順序適用於 A、B 和 C 是函式庫、套件還是應用程式。

為什麼順序很重要?儘管您可以在相依項目遷移之前進行一些程式碼遷移,但如果相依項目在遷移期間更改了它們的 API,您可能會冒著需要進行第二次遷移的風險。當我們到達 beta 版本時,我們將提供工具來幫助您找出哪些相依項目已經遷移。如果您是套件作者,為了避免 API 斷裂的風險,請在發佈空安全的版本之前,等待所有相依項目都完成遷移。

當您的相依項目準備就緒時,您可以使用我們的遷移工具。該工具透過分析您所有現有的程式碼來工作。遷移工具是互動式的,因此您可以審查工具推斷出的可空性屬性。如果您不同意工具的任何結論,您可以添加可空性提示來更改推斷。添加幾個遷移提示會對遷移品質產生巨大的影响。

Screenshot of the migration tool
遷移工具有助於您以互動方式將程式碼遷移到空安全。

3. 完全健全

一旦您完全完成遷移,Dart 的空安全就是 健全 的。這表示 Dart 100% 確定在上面的示例中,返回值、列表和元素不可能為空引用。當 Dart 分析您的程式碼並確定變數為不可空引用時,該變數 始終 為不可空引用:如果您在偵錯工具中檢查正在執行的程式碼,您將看到不可空引用性在運行時被保留。相反,其他一些實作是非健全的,在許多情況下仍然需要執行運行時空引用檢查。Dart 與 Swift 共享 健全的空安全,但其他程式語言卻很少。

Dart 空安全的健全性還有另一個令人欣慰的含義:這表示您的程式可以更小更快。由於 Dart 非常確定不可空引用變數永遠不會為空引用,因此 Dart 可以進行最佳化。例如,Dart 的提前編譯 (AOT) 編譯器可以生成更小更快 Native 程式碼,因為它不需要在知道變數不是空引用時添加空引用檢查。

請注意,要獲得健全的空安全,您需要將整個專案和所有相依項目遷移到空安全。如果您的應用程式或相依項目的一部分尚未遷移,您將獲得部分空安全,它保留了大部分檢查,但沒有完全最佳化,也無法保證應用程式完全安全。

空安全路線圖

空安全何時才能準備好投入生產使用?以下是目前的時間表:

  1. Flutter 進行 技術預覽 2 嘗試:這就是今天。由於我們已成功將核心 Flutter 架構遷移到空安全,因此您可以嘗試使用空安全來學習新的語言功能併嘗試 一個小型 Flutter 樣本。如果您是套件作者,您也可以嘗試遷移,如果您有一個小型相依項目集已經被我們遷移了。您需要傳遞一個 實驗標誌,不應該在生產環境中使用它,也不應該發佈任何遷移的套件。
  2. 使用 beta 版本進行早期套件遷移:今年晚些時候,我們將完成效能調整,並擁有足夠的測試覆蓋率,讓我們有信心相信此功能按預期工作,並且向後相容性穩定。在那時,我們將發佈該功能的 beta 版本,您將不再需要傳遞實驗標誌。我們希望看到套件擁有者開始將他們的套件遷移到空安全,這將為我們提供最後一輪驗證,證明該功能已準備好發佈穩定版本。
  3. 使用 stable 版本投入生產:接下來,我們將解決 beta 版本中收到的回饋,修復任何剩餘的問題,然後發佈到 stable channel。很難為此設定一個具體的時間表,但我們認為是明年年初。一旦該功能穩定,我們希望看到空安全被廣泛採用,會有空安全的應用程式發佈到商店,以及許多空安全的套件在 stable channel 上發佈到 pub.dev。

立即嘗試

您今天就可以開始嘗試使用空安全!若要快速上手,請查看 附帶空安全的 DartPad 特殊版本

如果您想在 VS Code、Android Studio 或終端機中嘗試使用空安全,請查看 Flutter 空安全樣本應用程式。這個應用程式包含執行說明和一個小型氣象應用程式的兩個版本:一個不使用空安全,其中包含一些零散的空引用錯誤,另一個使用空安全來確保這些問題得到處理。如果您更願意嘗試使用一個新的 Flutter 應用程式,您可以運行 flutter create,然後按照 實驗說明 來啟用空安全。請注意,您將需要一個 dev channel 的 Flutter SDK(版本 1.24.0–3.0.pre 或更高版本),因為目前的穩定版本和 beta 版本的 Flutter 不支援空安全。

若要進一步了解功能設計,請閱讀我們最新的 了解空安全 文件。如果您更喜歡觀看簡短的影片,請查看幾個月前 Flutter Day 活動 中的 空安全影片

我們很高興將健全的空安全帶到 Dart。健全的空安全是 Dart 的一個特色功能,可以幫助您編寫更不易出錯的程式碼,並獲得更好的效能。我們希望您會 嘗試 在技術預覽中使用此功能,並透過我們的議題追蹤器 提供回饋。祝您編碼愉快!


Dart 健全的空安全:技術預覽 2 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

http://creativecommons.org/licenses/by/4.0/

【文章翻譯】Flutter on the web, slivers, and platform-specific issues: user survey results from Q3 2020

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter 網頁、Sliver 和平台特定問題:來自 2020 年第三季度的使用者調查結果

撰寫者:Flutter UXR 團隊(JaYoung LeeYouyang HouJack KimTao Dong

2020 年 8 月,Flutter 團隊發布了其第 10 個季度使用者調查。在 10 天的時間裡,全球有 7,668 名使用者回覆了調查。每位使用者平均花費 7.4 分鐘完成調查,相當於 39.4 天的開發者時間。我們非常感謝大家花時間提供意見回饋,我們也希望與大家分享這些結果。

如同往常,我們詢問了您對 Flutter 各個部分的滿意度。本季度,我們也專注於收集有關其他主題的意見回饋,例如 Flutter 網頁、Sliver(用於實現豐富捲動效果的 Widget)和除錯平台特定問題。我們將在本文中更詳細地探討每個主題。如果您有興趣,請繼續閱讀!

摘要

  • 94% 的受訪者對 Flutter 的整體滿意度很高(PSAT),58% 的受訪者非常滿意(VSAT)。雖然 PSAT 保持穩定,但 VSAT 不斷增加。
  • 在企業工作的使用者比例從 26% 增加到 31%。高級使用者的比例也在增加。
  • 在過去 3 個月使用 Flutter 網頁的使用者中,59% 的使用者對其效能感到滿意。71% 的使用者對 Flutter 建立在網頁上感覺自然的 UI 的能力感到滿意。
  • 想要使用 Sliver 實作豐富捲動效果的使用者中,有 79% 的使用者嘗試過使用它們。最大的問題(36%)是難以找到符合他們需求的 Widget。
  • 71% 的使用者有除錯平台特定問題的經驗。常見的問題包括工具(32%)、視覺差異(28%)和相依性管理問題(28%)。

滿意度和使用者群的變化

本季度,對 Flutter 非常滿意 的使用者比例創下新高,達到 58%。總體而言,Flutter 使用者對產品仍然感到滿意(94%),即使社群以指數級增長。以下圖表顯示了 Flutter 滿意度水平隨時間的推移。

58% 的使用者在回答「總體而言,您對 Flutter 的滿意度如何?」的問題時選擇了「非常滿意」。

我們的使用者群有一些顯著的變化。首先,在企業工作的使用者比例顯著增加,從第一季和第二季的 26% 增加到 31%,而在此期間,在創業公司工作的使用者比例穩定在 35% 左右。

雖然大多數 Flutter 使用者都在創業公司工作,但企業開發者比例從 26% 顯著增加到 31%。

另一個顯著的變化是對 Flutter 經驗水平的感知。如以下圖表所示,新手使用者的比例隨時間推移而下降,而高級使用者的比例隨時間推移而增加。這意味著我們社群中有更多有經驗的使用者可以幫助分享他們的知識給新手使用者。如果您有興趣獲得或分享知識,您可以與其他 Flutter 開發者在線交流。請訪問 flutter.dev 上的 社群標籤

高級使用者的比例持續增加。

Flutter 網頁

除了在 stable channel 支援行動裝置外,Flutter 也在 beta 版中支援網頁開發。在此調查中,我們詢問了早期採用者在效能、網頁體驗、工作流程和文件方面遇到的特定問題,以便我們可以優先處理重要問題。

受訪者積極使用 Flutter 建立網頁應用程式。約 33% 的受訪者表示他們已評估 Flutter 網頁以供潛在生產使用(15%)、建構了 demo(11%)或發布了生產應用程式(7%),如以下圖表第三行所示。

33% 的使用者(4,449 人中的 1,468 人)表示他們已評估 Flutter 網頁以供生產(15%)、建構了 demo(11%)或發布了生產應用程式(7%)。

更具體地說,在過去 3 個月擁有行動裝置和網頁開發經驗的使用者中,有 29.5% 的使用者更認真地使用 Flutter 網頁(供潛在生產使用)。這個百分比因開發者先前對平台的經驗而異。看起來,具有網頁開發背景的受訪者正在嘗試 Flutter 作為一種替代網頁框架(22% 的受訪者嘗試使用 Flutter 網頁以供潛在生產使用),而具有行動裝置開發背景的受訪者正在積極嘗試使用 Flutter 網頁作為通往網頁開發的途徑(16% 的受訪者嘗試使用 Flutter 網頁)。

在過去 3 個月嘗試使用 Flutter 網頁以供生產的使用者比例因他們先前對行動裝置和網頁平台的經驗而異。

Flutter 網頁團隊也收集了有關建立網頁體驗的各個問題的意見回饋。首先,我們了解到受訪者認為瀏覽器導航和路由歷史(55%)、複製/貼上選取文字(34%)、捲軸物理學(33%)和選取文字(32%)在建立網頁體驗中至關重要。受訪者也要求提供有關路由和調整行動版佈局以適應網頁的更好文件。

使用者將「瀏覽器導航和路由歷史」選為使用 Flutter 建立網頁體驗中最關鍵的功能。

Flutter 團隊正在根據我們收到的意見回饋積極進行改進。為了解決圍繞導航和路由的頂級使用者問題,團隊最近發布了 Navigator 2。我們還加入了對 複製/貼上可選文字 的支援,並計劃改進 可選文字 功能(特別是針對富文字)。我們將根據社群回報的問題,繼續努力改進捲軸物理學和效能。

最後,團隊收到了有關工作流程、效能和第三方 API 的意見回饋。在基本工作流程中,受訪者認為除錯最困難。頁面載入速度和捲軸是受訪者遇到的最常見的效能問題。受訪者希望 Flutter 網頁更好地支援本地儲存(例如 SQLite)、Firebase 儲存和 Google 地圖。當團隊在 Flutter 網頁方面取得進展時,這些領域將會成形。

Sliver

Sliver Widget(以「Sliver」開頭的 Widget,例如 SliverAppBar 和 SliverList)用於建立豐富的捲軸效果。雖然可以使用 ListView、GridView、PageView 或 AnimatedList 等 Widget 實現許多捲軸效果,但 Sliver Widget 有助於自訂捲軸檢視,並實現更美觀的 UI。

您可以使用 Sliver Widget 實現像這樣的豐富捲軸效果。

Flutter 團隊聽到了有關使用者對 Sliver 體驗的不同故事。有些人表示他們沒有在應用程式中使用 Sliver,而有些人表示他們需要更多 Sliver 來實現各種效果。因此,團隊決定在本季度的調查中加入一些問題,以更好地了解 Flutter 使用者如何使用 Sliver。

我們首先了解到,更多使用者使用簡單的捲軸效果(49%)設計他們的 UI,而不是使用豐富的捲軸效果(39%)。(調查中呈現了簡單捲軸效果和豐富捲軸效果的範例。)對於那些需要豐富捲軸效果的人來說,78% 的人表示他們需要 Sliver 來實現他們想要的效果。

更多使用者使用簡單的捲軸效果(49%)設計他們的 UI,而不是使用豐富的捲軸效果(39%)。

在那些需要 Sliver 的使用者中,20% 的使用者表示他們沒有嘗試過使用 Sliver。對我們來說更有趣的是,35% 的使用者表示他們嘗試過使用 Sliver 但遇到了問題。當我們詢問他們遇到的最大問題時,如以下圖表所示,發現問題最大(36%),其次是學習問題(30%),然後是可用性問題(19%)。

發現問題是 Sliver 使用者遇到的最大問題,其次是學習問題和可用性問題。

因為我們不希望您因這些問題而降低 UI 品質,所以我們計劃更新 flutter.dev,以便更容易找到 Sliver Widget 和有關 Sliver 的相關資訊,並且更容易學習。如果您正在尋找 Flutter 框架中沒有的新 Sliver,請考慮使用社群套件,例如 sliver_toolssticky_headers。Flutter 社群也歡迎您為此領域做出貢獻。

同時,如果您是 Sliver 的新手並且想了解更多,請參閱以下資源:

除錯平台特定問題

先前的調查 中,我們發現 除錯平台特定問題跨平台測試應用程式 是 Flutter 開發者最困難的任務。雖然我們看到了一些與平台特定問題相關的錯誤,但我們並不知道這些問題的相對優先順序,以及它們是否被捆綁在主題中或分散開來。為了找到除錯和測試難以執行的原因,我們加入了一些問題以詢問使用者遇到了什麼特定問題。

首先,我們詢問使用者除錯了哪些平台特定問題。我們發現最 常見 的平台特定問題是工具問題(32%)、不同平台的視覺差異(28%)、相依性管理問題(28%)、不同平台的行為差異(27%)、不同平台的 Plugin 行為差異(26%)和缺少原生功能(25%)。

最常見的平台特定問題是工具問題、視覺差異和相依性管理問題。

受訪者也評估了他們除錯的每個問題的重要性