蘋果在 WWDC 2019 正式公布了UIKit for Mac,在 WWDC 結束後的一兩週,就花了點時間,把以前寫的一個計算台北捷運轉乘的簡單 iOS app,轉換成了可以在 macOS 當中執行。
轉換的過程還算簡單,首先準備好 macOS 10.15 beta 以及 Xcode 11 beta,打開你原本的 Xcode 專案,這時候你可以看到在 Deployment Info 當中,原本在可以 Deploy 的 Device 中,在 iPhone 與 iPad 之外,會多出 Mac 這個選項。勾選之後,Xcode 會問你是否確定要進行轉換,之後經過一段很短的轉換過程,就可以跑起來了。不過因為一陣子時間沒有管這個小 app,所以還是花了點時間調了一下像是 Dark Mode 下的顏色顯示之類的問題。
不過,在想要把一些目前的產品 code 轉換成可以在 macOS 執行的時候,就沒有那麼順利了。這個小 app 可以輕鬆轉換過去,大概是因為本身夠簡單,也沒有用到什麼額外的套件。
轉換時遇到的困難
如果你有一個現成的 iOS app 專案,在增加 Mac target 的時候,你大概會遇到以下的問題:
- 無法連結到相依的 iOS framework:如果你的 app 需要 link 到一些只有 binary 的第三方廠商的 Framework,Xcode 會告訴你這樣的訊息: Building for UIKit for Mac, but the linked framework ‘YourFramwork.framework’ was built for <unknown>. You may need to restrict the platforms for which this framework should be linked in the target,也就是說,Xcode 無法辨識這是可以供 UIKit for Mac 的 Framework。也就是說,你需要第三方廠商用新版的 Xcode 重新編譯這些 Framework,才有辦法連結。
- 如果你的 app 透過 CocoaPods 安裝了第三方的 Pods,也不太容易編譯起來。CocoaPods 與 Xcode 的 New Build System 相處得不是很好,但是你一定得要用 New Build System,才可以編譯 UIKit for Mac 的 app。
Xcode 的 New Build System 在編譯過程中,不會打包最新版本的 framework,所以你在更動了 CocoaPods 所安裝的 Pods 之後,Xcode 還是會繼續打包前一次編譯出來的版本。其實一般 iOS app 開發也會遇到相同的問題,但為了偷懶,大概就直接切換到 Legacy Build System 就解決了,要怎樣在 New Build System 裡頭好好使用 CocoaPods,可以看一下 CocoaPods and the new Xcode build system 這篇。
至於之後 CocoaPods 會不會調整得比較好用嘛,也沒有人知道,但是看來蘋果的立場是以後官方的套件管理會是 Swift Package Manager。 - UIKit for Mac 沒有完整移植所有的 UIKit class,已經 deprecated 就不會移植過來,像是 UIWebView 等。所以,如果你的 app 用到了這些 class,還是得做一定程度的改寫。
至於 Flutter app,由於 Flutter engine 目前也只有 iOS 上的 Binary,於是也無法編譯。
所以,雖然蘋果宣稱可以將 iOS app 輕鬆移植到 macOS 上,不過想像中,在秋天 macOS 10.15 Catalina實際上線的時候,可能還不會有那麼多 app移植過來。
把 UIKit for Mac app 跑起來的感覺
把 app 跑起來之後,首先會看到一大串像這樣的錯誤訊息:
AXRuntime 與 macOS 上的 accessibility 有關,所以就順手看了一下在 UIKitForMac App裡頭使用 VoiceOver 大概是怎樣的感覺。基本上 UIKitForMac App支援 Accessibility,但是有些地方又有點怪,像是如果 app裡頭用了 pop over,VoiceOver 就讀不到在 popover上面的東西。
UIDevice 這個物件在 UIKitForMac上面的行為也有點微妙,如果你從 UIDevice 去詢問目前的作業系統版本,他會告訴你是 macOS,但是如果你去問這個 Device是什麼 Model,你預期會拿到像是 MacBook 或是 Mac Mini之類的 Mac 型號,但是 UIDevice 會告訴你說這是一台 iPad。
整體來看,UIKitForMac 就是在 macOS 上面開一個視窗,然後在裡頭把一個 iPad app 給跑起來。這樣的 app 如果是拿來做一個 Twitter client 或是簡單的音樂播放 app ,可能綽綽有餘,但是如果想要得到充滿生產力的桌面環境體驗,那麼 UIKitForMac 還少了不少真正桌面環境需要的東西。
像是:怎麼做多視窗支援,讓每個不同文件都有各自的編輯視窗(話說 iOS 13 在 iPad上面有這方面的新 API,或許應該試一下),能不能直接拖拉檔案到 app 裡頭開啟,視窗本身的客製化…感覺都還有不少地方是蘋果可以調整的。