iOS 27 的 iPad 可調整大小:這個變通方案是有代價的
Apple 的 iOS 27 發行說明,為那些無法連續調整大小的 iPad App 給出了一句話的變通方案:在 Info.plist 中宣告支援全部四個介面方向。1 這則說明沒有提到的是,系統會把這個 App 層級的宣告,與每個 view controller 所支援的方向取交集。2 放寬 App 層級的集合,等於在所有地方一併放寬,iPhone 也不例外——除非每一個需要受限的 view controller 都覆寫了 supportedInterfaceOrientations。
更新,8 月 24 日: 這道門檻已經解除。目前的發行說明將問題 166422120 標示為 Fixed——它在 beta 4 版與 beta 6 版之間從 Known Issues 中移出,beta 7 版也印證了這一點:已宣告的方向不再是連續可調整大小的條件,與下文引用的意圖一致。1 如果已經上線了「宣告全部四個方向」的變通方案,在目前的 beta 上它不再是必要的;但在移除之前,請重新檢查那些與它一併加上
supportedInterfaceOrientations覆寫的 view controller,因為這些覆寫本身仍在發揮作用(本文所談的交集行為並未改變)。beta 4 時期與UIRequiresFullScreen相關的調整大小已知問題,同樣在 Resolved Issues 中標示為 Fixed。以下的分析按照當初撰寫的樣子保留,以 Beta 4 為錨點,因為只要變通方案還留在已發行的建置裡,它的副作用機制就依然成立。關於這項改變所處的更大脈絡,請參閱可調整大小的 iPhone 時代。
關於這項改變的那個流傳版本,對目前狀態的描述同樣是錯的。 Apple 的意圖是讓已宣告的方向不再決定連續可調整大小。而記錄這項意圖的發行說明條目之所以被歸入 Known Issues,是因為在 Beta 4 中方向仍然發揮著限制作用。1
兩邊都重要。這個行為是通往一項刻意變更途中的 bug,而這個 bug 的變通方案帶有一個沒人寫在同一處的副作用。
TL;DR
在 iOS 與 iPadOS 27 Beta 4 中,一個以 iOS 27 SDK 建置、且 UISupportedInterfaceOrientations 缺少四個方向中任何一個的 iPad App,會被視為不支援連續調整大小。Apple 把它列為已知問題,同時又表示方向「不應再成為連續可調整大小的條件」。1 文件給出的變通方案是宣告全部四個方向。這麼做會放寬整個 App 的方向集合,而系統正是透過比較 App 層級的方向與每個 view controller 的方向來決定是否旋轉。2 另有四個已知問題牽涉 UIRequiresFullScreen:本應以離散的 UIScreen 變更來傳遞之處,卻收到了連續的調整大小更新。1 UIRequiresFullScreen 與 UISupportedInterfaceOrientations 都沒有被淘汰。34
發行說明究竟寫了什麼
iOS 與 iPadOS 27 Beta 4 說明中,UIKit 一節有六則與此有關,其中五則尚未解決。1
門檻本身,歸入 Known Issues:
「在 iPad 上,如果您的 iPad App 以 iOS 27 SDK 建置,且其
UISupportedInterfaceOrientations未包含全部四個介面方向,該 App 會被視為不支援連續調整大小。從 iOS 27 開始,所支援的介面方向不應再成為連續可調整大小的條件。」
請讀一讀第二句的語氣。「不應再成為條件」描述的是預期行為。這一則之所以以已知問題的形式存在,正是因為出貨的行為還沒有與這個意圖對上。
這個區別會改變您該做什麼。如果方向真的不再決定可調整大小,建議就會是移除變通方案。既然它們仍在發揮作用,建議就是先套上一個,並預期這麼做的理由會消失。
圍繞 UIRequiresFullScreen 的四則已知問題:
一個以 iOS 27 SDK 建置、並設定了 UIRequiresFullScreen 的 iPad App 會收到連續的調整大小更新,而「每一次調整大小本應作為一次離散變更,傳遞給一個 bounds 已更新的新 UIScreen」。同樣的情況也出現在 iPad 上執行的 iPhone 專用 App,以及 iPhone 鏡像輸出之中。1
第四則涵蓋 iPhone 鏡像輸出中的方向處理:以 iOS 27 SDK 建置的 App 會得到一個支援所有方向的 scene,「無論 UISupportedInterfaceOrientations 中宣告了什麼,或 UIViewController.supportedInterfaceOrientations 回傳了什麼」,而這些本應「在使用者開始調整視窗大小之前一直受到尊重」。1
一則已解決: 先前那個在 UIRequiresFullScreen 之下調整大小時 UIScreen.main 的 bounds 會改變的問題,現在已列在 Resolved Issues 中。1 它在前一個 beta 中還是一則有效的已知問題。如果您正依照幾週前記下的筆記在做事,動手之前先核對這一則。
連續可調整大小究竟帶來什麼
在權衡代價之前,值得先把被限制的那個東西講清楚,因為「連續可調整大小」這個說法承擔著具體的意涵。
iPad 視窗改變尺寸有兩種方式。一種是在離散狀態之間跳動,這正是相容模式下的 App 所得到的:用 Apple 的話說,系統「為您的 App 維持一致的 scene 尺寸,但不會以全螢幕方式呈現 App 的 scene」。3 另一種則是跟隨拖曳,在使用者移動調整控制項的過程中接收一連串中間尺寸。
差別會顯現在使用者的手上。連續可調整大小的 App 會在視窗移動時同步重排版面;不支援的那種則會維持原本的版面,最後才一下卡到定位——與不這麼做的系統 App 擺在一起,就顯得遲鈍。
多年來,Apple 一直在收窄相容路徑。UIRequiresFullScreen 於 iOS 9 登場,用來徹底退出 iPad 多工與動態調整大小。3 iPadOS 16 的 Stage Manager 與 iPadOS 26 的 Windowed Apps 模式各自擴展了視窗能做的事,而文件如今描述相容模式的方式,是它扣住了什麼,而不是它給了什麼。
所以變通方案回答的問題是:您的 iPad App 要參與現代的視窗化,還是留在一個 Apple 不斷壓縮的模式裡。這值得改一次 Info.plist,但不值得毫無防護地改——這正是下一節的重點。
變通方案的代價
Apple 的變通方案只有一句話:在 Info.plist 中宣告全部四個介面方向。1 而它的後果寫在另一個頁面上。
UIViewController.supportedInterfaceOrientations 記載了旋轉是如何被決定的:2
「為了判斷是否旋轉,系統會將 view controller 所支援的方向,與 App 所支援的方向(由
Info.plist檔案或 app delegate 的[方法]決定),以及裝置所支援的方向進行比較。」
三個集合取交集。Info.plist 中的宣告是上限,而不是指令。一個只在 Info.plist 裡列出一個方向、因而一直維持直向,並且在 view controller 層級從未覆寫過任何東西的 App,會在套用變通方案的那一刻失去這項限制。
對通用 App 來說,這會同時落在 iPhone 與 iPad 上。而 Apple 自家的指引也反對在 iPhone 上做寬鬆的宣告:關於上下顛倒的方向,「最佳做法是為 iPad 慣用類型啟用它。沒有主畫面按鈕的 iOS 裝置,例如 iPhone 12,並不支援這個方向。對 iPhone 慣用類型,您應該完全停用它。」2 Info.plist 的文件從另一個方向說了同樣的話,指出系統會「在沒有主畫面按鈕的裝置上」忽略上下顛倒。4
所以誠實的說明是兩步,而不是一步:
<!-- Info.plist: the ceiling. Required for continuous resizability on iPad. -->
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
// And the floor, on every controller that must stay constrained.
final class CaptureViewController: UIViewController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
UIDevice.current.userInterfaceIdiom == .pad ? .all : .portrait
}
}
跳過第二步,就等於為了換取 iPad 的視窗行為,去告訴一個通用 App 在 iPhone 上可以上下顛倒地旋轉。這個失敗不是當機,也不是建置錯誤,而是有人正在使用時相機畫面翻了過去。
另外請注意,supportedInterfaceOrientations 的預設值因慣用類型而異,而且只有在 shouldAutorotate 回傳 true 時系統才會查詢它。2 如果覆寫過後者,在斷定自己的限制仍然成立之前,值得把這兩者的互動重讀一遍。
判斷自己是否受影響
這些都不會產生建置錯誤,所以稽核只能靠手動。三項檢查,依省下的時間多寡由高到低排列。
逐個 target 查看 Info.plist 實際宣告了什麼。 方向相關的鍵往往在建立專案時設定一次,此後再也沒人回頭看;而通用 App 可以透過 UISupportedInterfaceOrientations~ipad,為 iPhone 與 iPad 帶著不同的宣告。兩處都要讀。
# Every orientation and fullscreen declaration across the project
rg -l 'UISupportedInterfaceOrientations|UIRequiresFullScreen' --glob '*.plist'
# And what each one says
/usr/libexec/PlistBuddy -c "Print :UISupportedInterfaceOrientations" Info.plist
/usr/libexec/PlistBuddy -c "Print :UIRequiresFullScreen" Info.plist
當某個鍵不存在時,PlistBuddy 會以非零狀態結束——對 UIRequiresFullScreen 而言,這本身就是答案:沒有這個鍵,代表從來就沒進過相容模式。
找出在程式碼中限制方向的 controller。 改動 Info.plist 之後仍然有效的正是它們,而它們的缺席正是這項改動危險的原因。
rg 'supportedInterfaceOrientations|shouldAutorotate' --type swift
結果為空,再加上一份狹窄的 Info.plist 宣告,正是會出問題的那種組合:這個 App 完全靠 property list 才維持直向,一旦放寬,唯一存在過的限制也就沒了。
接著在兩種慣用類型上親眼看看這個 App。 這個失敗是視覺性的,自動化訊號很弱。一個驅動畫面並對其內容做斷言的 UI 測試,在任何方向下都會通過。要找的是一個先前無法旋轉的畫面竟然轉了起來——這表示在改動 Info.plist 之後,要執行 iPhone 建置,並實際轉動裝置或模擬器。
媒體擷取、文件掃描、簽名欄位、遊戲,以及任何具有固定長寬比畫布的介面,是意外旋轉代價最高的地方,也最明顯地屬於該寫 per-controller 覆寫的位置。
UIRequiresFullScreen 正被掏空,而不是被淘汰
五則未解決問題中有四則牽涉 UIRequiresFullScreen。1 這個讓 App 退出 iPad 多工的鍵,如今成了調整大小的傳遞行為不正確的前提條件。
它並沒有被淘汰。UIRequiresFullScreen 的文件顯示其可用於 iOS 9.0 與 iPadOS 9.0,沒有任何淘汰、不可用或 beta 標記。3 UISupportedInterfaceOrientations 同樣如此,自 iOS 3.2 起可用。4
這個組合值得點名。一個在 2026 年設定 UIRequiresFullScreen 的 App,編譯時不會有警告,出貨時不會有移轉通知,最後落在一個 Apple 持續收窄的相容模式裡。這個模式在現代系統上代表什麼,文件早已寫明:在支援 Windowed Apps 模式的 iPad 上的 iPadOS 26 及後續版本,以及在支援 Stage Manager 的 iPad 上的 iPadOS 16 及後續版本,系統「為您的 App 維持一致的 scene 尺寸,但不會以全螢幕方式呈現 App 的 scene」。3
這個鍵已經不再做它名字所說的事。它沒有退場,而您的建置裡沒有任何東西會告訴您這件事。
共同的模式:SDK 連結說了算
上面每一則都共用同一個條件,而這個條件不是作業系統版本。每一則都適用於「以 iOS 27 SDK 建置」的 App。1
同一份原始碼,不同的二進位檔,不同的行為。這一點在這次的版本中反覆出現:選單項目圖片取決於連結的是哪個 SDK,橫跨兩代 SDK 共有三種不同的行為。而 macOS 27 的跨團隊容器拒絕看起來是相反的情形,是一項沒有 SDK 條件的系統層級政策——正因如此,這個區別值得去查證,而不是想當然耳。
對測試而言的實際後果是:針對 iOS 26 SDK 的建置與針對 iOS 27 SDK 的建置,是兩個不同的對象。如果 CI 矩陣裡只有一個 Xcode 版本,那麼測到的只是其中一個。
現在該做什麼
先決定自己是不是真的需要連續可調整大小。 如果 iPad App 已經宣告了全部四個方向,這裡的內容都不適用。變通方案只在您刻意限制過方向時才有關係。
如果要套用變通方案,就搭配 per-controller 的覆寫。 Info.plist 的改動是上限;限制必須移到需要它的那些 controller 的 supportedInterfaceOrientations 上,並依慣用類型分支。
另外單獨稽核 UIRequiresFullScreen。 有四則未解決問題牽涉到它,而建置過程不會給您任何提示。請 grep 所有 Info.plist 檔案,包括那些您並不覺得是 iPad App 的 target,因為其中一則問題涵蓋的正是在 iPad 上執行的 iPhone 專用 App。
預期這道門檻會消失。 Apple 表示方向不應再決定連續可調整大小。當那一天到來,宣告全部四個方向的理由就沒有了,但被放寬的方向集合會一直留在 Info.plist 裡,直到有人把它移除。請留一則註解說明它為什麼在那裡。
動手之前重新核對說明。 這六則之中已經有一則從 Known Issues 移到了 Resolved。本文反映的是 2026 年 8 月 2 日當時的 Beta 4。
重點整理
給 iPad App 開發者:
- 儘管 Apple 表示方向不應再具有限制作用,但在 Beta 4 中已宣告的方向仍然決定連續可調整大小。請把它當成一個有變通方案的 bug,而不是新的行為。
- 變通方案會放寬整個 App 的方向上限。請加上 per-controller 的 supportedInterfaceOrientations 覆寫,否則 iPhone 建置就會開始旋轉。
- 四則未解決問題牽涉 UIRequiresFullScreen 傳遞連續而非離散的調整大小更新。
給維護舊 App 的人:
- UIRequiresFullScreen 沒有被淘汰,也不會產生警告,而它所要求的那種行為卻持續收窄。請明確地稽核它。
- 這裡的每一則問題都以「以 iOS 27 SDK 建置」為條件,而不是以使用者執行的作業系統為條件。
FAQ
已宣告的方向是否已經不再決定連續可調整大小?
在 Beta 4 中還沒有。Apple 表示「從 iOS 27 開始,所支援的介面方向不應再成為連續可調整大小的條件」,同時把這句話歸入 Known Issues,因為目前的行為仍然以方向為條件。1
實際的變通方案是什麼?
在 UISupportedInterfaceOrientations 中宣告全部四個介面方向。1 並且要為那些必須維持受限的 view controller 搭配 supportedInterfaceOrientations 覆寫,因為系統會把 App 層級的集合與每個 controller 的集合取交集。2
這會影響我的 iPhone 建置嗎?
如果您出貨的是通用 App,而且只靠 Info.plist 來限制方向,那麼會。Apple 建議對 iPhone 慣用類型完全停用上下顛倒,並指出在沒有主畫面按鈕的裝置上系統會忽略它。24
UIRequiresFullScreen 被淘汰了嗎?
沒有。它的文件顯示其可用於 iOS 與 iPadOS 9.0,且沒有淘汰標記。3 這裡四則未解決問題都牽涉到它,所以不要把缺少淘汰標記讀成一種背書。
Apple 修好這道門檻之後,我該移除變通方案嗎?
移除不再需要的那一部分,保留保護您的那一部分。當已宣告的方向不再決定連續可調整大小,列出全部四個方向的理由就消失了,可以把 UISupportedInterfaceOrientations 收回到 App 實際支援的範圍。而 per-controller 的 supportedInterfaceOrientations 覆寫無論如何都應該留著:把方向限制表達在限制本該所在的位置,比依賴一個 App 層級的上限更耐久。
要避開的失敗模式恰恰相反:把 Info.plist 收窄回去,卻忘了正是那些覆寫在撐著擷取畫面不被轉過來。
我怎麼知道自己的 App 目前是不是連續可調整大小?
在 iPad 上調整視窗大小,看版面是跟著拖曳走,還是最後才卡到定位。跟著走就是連續可調整大小。如果是卡到定位,請檢查兩件事:是否設定了 UIRequiresFullScreen(它會徹底退出動態調整大小),以及 UISupportedInterfaceOrientations 是否列出了全部四個方向——後者正是這則已知問題所描述的條件。13
針對較舊的 SDK 建置能不能避開這一切?
每一則都以使用 iOS 27 SDK 建置為條件。1 較舊的 SDK 可以避開這些特定問題,但那是延後最終的改變,而不是阻止它。
來源
-
Apple,“iOS & iPadOS 27 Beta 4 Release Notes,” UIKit。Known Issues:radar 166422120(方向決定連續可調整大小,附帶宣告全部四個方向的變通方案)、178560235 與 178562971 與 178558224(
UIRequiresFullScreen收到連續而非離散的調整大小更新,分別發生在 iPad 上、iPad 上的 iPhone 專用 App,以及 iPhone 鏡像輸出中),以及 178555304(iPhone 鏡像輸出的 scene 無論宣告為何都支援所有方向)。Resolved Issues:radar 178559386(在UIRequiresFullScreen之下調整大小時UIScreen.main的 bounds 改變),它在較早的 beta 中曾是一則已知問題。各條目所屬的區塊已於 2026-08-02 對照 Beta 4 的 JSON 重新查證。更新 2026-08-24: 對照 Beta 7 版的 JSON 重新查證——166422120 與UIRequiresFullScreen這一組現在全部出現在 Resolved Issues 中(依封存副本,這次移動發生在 beta 6 版之前),而 UIKit 的 Known Issues 清單已經是空的。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple,“UIViewController.supportedInterfaceOrientations.” 上文完整引用的交集規則出自此處:系統會將 view controller 所支援的方向,與 App 所支援的方向(來自
Info.plist或 app delegate)以及裝置所支援的方向進行比較。它同時也是各慣用類型預設值、shouldAutorotate前提條件,以及「對 iPhone 慣用類型停用上下顛倒」這項指引的出處。 ↩↩↩↩↩↩↩ -
Apple,“UIRequiresFullScreen.” 可用於 iOS 9.0 與 iPadOS 9.0,截至 2026-08-02 沒有淘汰、不可用或 beta 標記。相容模式描述的出處,包括在 iPadOS 26 及後續版本的 Windowed Apps 模式,以及 iPadOS 16 及後續版本的 Stage Manager 之下的行為。 ↩↩↩↩↩↩↩
-
Apple,“UISupportedInterfaceOrientations.” 可用於 iOS 3.2 與 iPadOS 3.2,沒有淘汰標記。四個方向取值的出處,以及「系統在沒有主畫面按鈕的裝置上忽略上下顛倒選項」這項說明的出處。 ↩↩↩↩