iPadアプリをうまくMacで動かせるのはiOS17以降なのだ
SwiftUIを使うと、構造的にUIを定義できるので、iPhoneとiPadのアプリをうまい具合に作れるようになりますが、これとは別にiPadアプリがMacで動くようになっています。
しかし、iOS17より前の機能をつかっていると、MacでiPadアプリを開くとメチャクチャ大きいウィンドウで開いてしまいます。そのため、左右に大きな空白を設けてなんとかサイズを維持させるはめになるのですが、iOS17の機能を使うと、Macのウィンドウが内部のコンテンツに合わせて開いてくれるので、サイズや比率がコンテンツに合わせたフィットした形でウィンドウが開いてくれます。
それは、@mainのbody内のWindowGroupのプロパティでWindowResizabilityで.contentsSizeを渡すことで実現します。
var body: some Scene {
WindowGroup {
ContentView()
.modifier(ConditionalFrameModifier(useCustomSize: isMacCatalyst))
}
.windowResizability(.contentSize)
}
これ、iOS17からなのですが、iOS関係あるの?という変な感覚がありますが、まぁ仕方ないですね。
ということで、しかたがないので、iOS17以上をサポート対象としました。
ちなみにiPad上のiPadアプリと、Mac上のiPadアプリを識別しなくてはサイズ指定ができません。これがまた難しくて、以下で判定します。
let isMacCatalyst: Bool = {
#if os(iOS)
if #available(iOS 14.0, *) {
return UIDevice.current.isRunningOnMac
} else {
return false
}
#else
return false
#endif
}()
private extension UIDevice {
@available(iOS 14.0, *)
var isRunningOnMac: Bool {
return ProcessInfo.processInfo.isiOSAppOnMac || ProcessInfo.processInfo.isMacCatalystApp
}
}
これ難しすぎですよねぇ。まぁとりあえず動いているからいいや。
さらに、ContentViewのサイズ指定については、.modifierで使い分けることになります。
struct ConditionalFrameModifier: ViewModifier {
let useCustomSize: Boolfunc body(content: Content) -> some View {
if useCustomSize {
content
.frame(minWidth: 400, idealWidth: 500, maxWidth: 600,
minHeight: 600, idealHeight: 800, maxHeight: 1000)
} else {
content
}
}
}
これもClaude3.5に応用例としてもらいましたが、全然理解できていませんw
まぁ、なんとか動きましたわ。ていうか複雑な方向にもっていかれそうになりますが、なんとかClaude3.5をいなしながら出来上がりました。
Claude3.5様々ですね。