← 所有文章

iOS 27 iPad 尺寸調整:暫解方案的代價

Apple 在 iOS 27 版本說明中,替無法連續調整尺寸的 iPad App 給了一行暫解方案:在 Info.plist 裡宣告支援全部四種介面方向。1這段說明沒提的是,系統會把這份全 App 層級的宣告,與各個 view controller 所支援的方向取交集。2換句話說,全 App 的集合一放寬,處處都跟著放寬,iPhone 也不例外——除非每一個受限的 view controller 都覆寫了 supportedInterfaceOrientations

而這項變更被廣為傳播的說法,同樣誤解了現況。Apple 的意圖是讓宣告的方向不再成為連續尺寸調整的門檻。但記載這項意圖的版本說明被歸在「已知問題」底下,因為在 Beta 4 中,方向依然是門檻。1

兩邊都重要。這個行為是一個 bug,走在一項刻意變更的路上;而這個 bug 的暫解方案,帶著一個沒人寫在同一處的副作用。

摘要

在 iOS 與 iPadOS 27 Beta 4 中,凡是以 iOS 27 SDK 建置、且 UISupportedInterfaceOrientations 未列出全部四種方向的 iPad App,都會被視為不可連續調整尺寸。Apple 把這一點列為已知問題,同時聲明介面方向「不應再是連續尺寸調整的條件」。1文件中的暫解方案是宣告全部四種。這麼做會在全 App 層級放寬方向集合,而系統判定是否旋轉的依據,正是拿全 App 的方向與各個 view controller 的方向相比對。2另有四項已知問題與 UIRequiresFullScreen 有關:本該以離散的 UIScreen 變更送達的更新,卻以連續尺寸調整的形式傳遞。1UIRequiresFullScreenUISupportedInterfaceOrientations 兩者都未被標為棄用。34

版本說明實際寫了什麼

iOS 與 iPadOS 27 Beta 4 版本說明的 UIKit 段落中,共有六則條目與此相關,其中五則尚未解決。1

門檻本身,歸在「已知問題」:

「在 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 會隨尺寸調整而改變的問題,如今已列入「已解決問題」。1它在前一個 beta 中還是尚未解決的已知問題。若您手邊的筆記是幾週前記下的,重述之前請先確認這一則。

連續尺寸調整換來什麼

在權衡代價之前,值得先把被門檻擋住的東西講清楚,因為「可連續調整尺寸」這個說法承載了很具體的意義。

iPad 視窗改變大小有兩種方式。一種是在離散狀態之間跳動,也就是相容模式下的 App 所得到的待遇:用 Apple 的話說,系統「為您的 App 維持一致的 scene 尺寸,但不會將 App 的 scene 以全螢幕呈現」。3另一種則是跟著拖曳走,在使用者移動尺寸調整控制項的過程中,持續收到一連串中間尺寸。

差別會直接落在使用者的手上。可連續調整尺寸的 App 會在視窗移動的同時重排版面;不可連續調整的則會固定住版面、在最後一刻猛然對齊——擺在不會這樣的系統 App 旁邊,看起來就是遲鈍。

多年來,Apple 一直在限縮相容模式這條路。UIRequiresFullScreen 於 iOS 9 登場,讓 App 得以完全退出 iPad 多工與動態尺寸調整。3iPadOS 16 的幕前調度與 iPadOS 26 的視窗化 App 模式,各自擴張了一個視窗能做的事;而如今的文件在描述相容模式時,講的是它扣掉了什麼,而不是它給了什麼。

所以暫解方案真正回答的問題是:您的 iPad App 要參與現代視窗化,還是要待在一個 Apple 持續縮小的模式裡。為此改動 Info.plist 是值得的;但不設防地改動則不值得——這正是下一節的重點。

暫解方案的代價

Apple 的暫解方案只有一句話:在 Info.plist 裡宣告全部四種介面方向。1而它的後果,寫在另一頁上。

UIViewController.supportedInterfaceOrientations 記載了系統如何決定要不要旋轉:2

「為了判定是否旋轉,系統會將 view controller 所支援的方向,與 App 所支援的方向(由 Info.plist 檔案或 app delegate 的〔方法〕決定)以及裝置所支援的方向相互比較。」

三個集合,取交集。Info.plist 的宣告是一道上限,而非一道指令。有些 App 只在 Info.plist 裡列出一種方向,view controller 層級從未覆寫過任何東西,直向就是這樣撐住的;這類 App 在套用暫解方案的那一刻,就失去了唯一的約束。

對通用 App 來說,這一改動會同時落在 iPhone 與 iPad 上。而 Apple 自家的指引正是反對在 iPhone 上做這樣寬鬆的宣告:關於上下顛倒的方向,「最佳做法是為 iPad idiom 啟用它。沒有主畫面按鈕的 iOS 裝置,例如 iPhone 12,並不支援此方向。您應為 iPhone idiom 完全停用它。」2Info.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 的預設值會因 idiom 而異,而且只有在 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 之所以只支援直向,完全是靠屬性列表撐著,一旦放寬,唯一存在過的約束就沒了。

接著在兩種 idiom 上實際看一遍 App。這種失敗是視覺上的,自動化訊號很弱。一個驅動畫面並針對內容做斷言的 UI 測試,在任何方向下都會通過。您要找的,是某個先前不會旋轉的畫面開始旋轉了——這意味著在改動 Info.plist 之後,得跑 iPhone 版本,然後親手把裝置或模擬器轉一轉。

媒體擷取、文件掃描、簽名欄位、遊戲,以及任何具有固定長寬比畫布的畫面,是意外旋轉代價最高的地方;它們同樣也是最該放上逐 controller 覆寫的地方。

UIRequiresFullScreen 正被掏空,而非棄用

五則未解決的問題中,有四則牽涉 UIRequiresFullScreen1這個讓 App 退出 iPad 多工的鍵,如今成了尺寸調整更新傳遞行為出錯的前提條件。

它並沒有被棄用。UIRequiresFullScreen 的文件顯示可用於 iOS 9.0 與 iPadOS 9.0,沒有任何棄用、不可用或 beta 標記。3UISupportedInterfaceOrientations 同樣沒有,自 iOS 3.2 起可用。4

這個組合值得點名。一個在 2026 年設定 UIRequiresFullScreen 的 App,編譯時不會有警告,出貨時不會有遷移通知,最後落進一個 Apple 持續限縮的相容模式裡。文件已經寫明了這個模式在現代系統上意味著什麼:在 iPadOS 26 及更新版本、支援視窗化 App 模式的 iPad 上,以及在 iPadOS 16 或更新版本、支援幕前調度的 iPad 上,系統「為您的 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 早已宣告全部四種方向,這裡的一切都與您無關。暫解方案只在您刻意約束過方向時才有意義。

若要套用暫解方案,請搭配逐 controller 的覆寫。Info.plist 的改動是一道上限;約束必須移進真正需要它的那些 controller 的 supportedInterfaceOrientations 裡,並以 idiom 作為判斷依據。

另外針對 UIRequiresFullScreen 做一次稽核。有四則未解決的問題牽涉到它,而您的建置流程不會標示它。請 grep 您所有的 Info.plist 檔案,包括那些您不認為是 iPad App 的 target——因為其中一則問題涵蓋的正是在 iPad 上執行的 iPhone 專用 App。

預期這道門檻會消失。Apple 已聲明方向不應再構成連續尺寸調整的條件。等那一天到來,宣告全部四種的理由就沒了,但被放寬的方向集合會一直留在您的 Info.plist 裡,直到有人把它拿掉。請留一則註解,說明它為什麼在那裡。

動手前再確認一次版本說明。這六則條目裡,已經有一則從已知問題移到了已解決。本文反映的是 2026 年 8 月 2 日當下的 Beta 4 狀態。

重點整理

給 iPad App 開發者: - 在 Beta 4 中,宣告的方向仍然是連續尺寸調整的門檻,儘管 Apple 聲明不該如此。請把它當成一個附帶暫解方案的 bug,而不是新的既定行為。 - 暫解方案會放寬全 App 層級的方向上限。請補上逐 controller 的 supportedInterfaceOrientations 覆寫,否則您的 iPhone 版本會開始旋轉。 - 有四則未解決的問題,牽涉 UIRequiresFullScreen 傳遞連續而非離散的尺寸調整更新。

給維護舊 App 的人: - UIRequiresFullScreen 未被棄用,也不會產生警告,但它所要求的行為卻持續被限縮。請專門為它做一次稽核。 - 這裡的每一則問題,條件都是「以 iOS 27 SDK 建置」,而不是使用者正在執行的作業系統版本。

常見問題

宣告的方向是否已經不再是連續尺寸調整的門檻?

在 Beta 4 中還沒有。Apple 聲明「自 iOS 27 起,所支援的介面方向不應再是連續尺寸調整的條件」,並把這段聲明歸在已知問題底下,因為目前的行為仍以方向作為門檻。1

實際的暫解方案是什麼?

UISupportedInterfaceOrientations 中宣告全部四種介面方向。1同時,對那些必須維持受限的 view controller 補上 supportedInterfaceOrientations 覆寫,因為系統會把全 App 的集合與各個 controller 的集合取交集。2

這會影響我的 iPhone 版本嗎?

如果您出貨的是通用 App,而且僅靠 Info.plist 來約束方向,那麼會。Apple 建議為 iPhone idiom 完全停用上下顛倒,並指出系統在沒有主畫面按鈕的裝置上會忽略它。24

UIRequiresFullScreen 被棄用了嗎?

沒有。它的文件顯示可用於 iOS 與 iPadOS 9.0,沒有棄用標記。3這裡的未解決問題中有四則與它有關,所以沒有棄用標記,不該被讀成一種背書。

Apple 修好這道門檻之後,我該移除暫解方案嗎?

移除您不再需要的那一半,保留能保護您的那一半。當宣告的方向不再構成連續尺寸調整的條件,列出全部四種的理由就消失了,屆時可以把 UISupportedInterfaceOrientations 收回到 App 實際支援的範圍。至於逐 controller 的 supportedInterfaceOrientations 覆寫,無論如何都該留著——把方向約束表達在約束真正該待的地方,遠比仰賴一道全 App 層級的上限來得耐用。

要避免的失敗模式是反過來的那一種:把 Info.plist 收窄回去,卻忘了那些覆寫才是唯一撐住擷取畫面不倒的東西。

我怎麼知道我的 App 目前是否可連續調整尺寸?

在 iPad 上調整視窗大小,看看版面是跟著拖曳走,還是在最後一刻才猛然對齊。跟著走,就是可連續調整尺寸。若是猛然對齊,請檢查兩件事:是否設定了 UIRequiresFullScreen,這會完全退出動態尺寸調整;以及 UISupportedInterfaceOrientations 是否列出全部四種方向,這正是本則已知問題所描述的條件。13

改用較舊的 SDK 建置,是不是就能避開這一切?

每一則條目的條件都是以 iOS 27 SDK 建置。1較舊的 SDK 能避開這些特定問題,但那只是把終將到來的變更往後延,並不是免除。

資料來源


  1. Apple, “iOS & iPadOS 27 Beta 4 Release Notes,” UIKit。已知問題:radar 166422120(方向構成連續尺寸調整的門檻,附全部四種方向的暫解方案)、178560235、178562971、178558224(UIRequiresFullScreen 收到連續而非離散的尺寸調整更新,分別發生於 iPad 上、iPad 上的 iPhone 專用 App,以及 iPhone 鏡像輸出中),以及 178555304(iPhone 鏡像輸出的 scene 無視宣告而支援所有方向)。已解決問題:radar 178559386(UIRequiresFullScreen 之下 UIScreen.main bounds 隨尺寸調整而改變),該項在較早的 beta 中屬於已知問題。各條目所屬段落已於 2026 年 8 月 2 日對照 Beta 4 JSON 重新查證。 

  2. Apple, “UIViewController.supportedInterfaceOrientations.” 上文完整引用的交集規則出處:系統會將 view controller 所支援的方向,與 App 的(來自 Info.plist 或 app delegate)以及裝置的方向相互比較。同時也是各 idiom 預設值、shouldAutorotate 前提條件,以及「為 iPhone idiom 停用上下顛倒」這項指引的出處。 

  3. Apple, “UIRequiresFullScreen.” 可用於 iOS 9.0 與 iPadOS 9.0,截至 2026 年 8 月 2 日無棄用、不可用或 beta 標記。相容模式描述的出處,包含 iPadOS 26 及更新版本的視窗化 App 模式,以及 iPadOS 16 及更新版本的幕前調度之下的行為。 

  4. Apple, “UISupportedInterfaceOrientations.” 可用於 iOS 3.2 與 iPadOS 3.2,無棄用標記。四個方向值的出處,以及「系統在沒有主畫面按鈕的裝置上會忽略上下顛倒選項」這段說明的出處。 

相關文章

macOS 27 與 iPadOS 27 的選單項目圖片會消失

macOS 27 與 iPadOS 27 預設隱藏選單項目圖片,而消失的內容取決於您連結的 SDK。三種框架,三種不同的修正方式。

3 分鐘閱讀

macOS 27 不再詢問,直接拒絕跨團隊容器存取

macOS 27 移除了讀取其他團隊 app group 容器時的授權提示。API 依然回傳看似正常的 URL,因此失敗要到讀取當下才浮現。

3 分鐘閱讀

Sign in with Apple 會送出四種通知,不是三種

Apple 的公告只點名三種伺服器對伺服器通知類型,API 的文件卻定義了四種。以下是完整的規格,以及 Apple 沒有寫進文件的部分。

3 分鐘閱讀