From 88e471e015083e6970b81e66e3e6b4719004d5ed Mon Sep 17 00:00:00 2001 From: Zongyuan Li Date: Fri, 26 Dec 2025 18:33:00 +0800 Subject: [PATCH] fix(iOS): fix iOS app startup failure Fixes #7643 This commit address the issue with 3 minor fixes: 1. Initialize ghostty lib before app start, or global allocator will be null. 2. `addSublayer` should be called on CALayer object, which is the property 'layer' of UIView 3. According to apple's [document](https://developer.apple.com/documentation/metal/mtlstoragemode/managed?language=objc), managed storage mode is not supported by iOS. So always use shared mode. FYI, another [fix](https://github.com/mitchellh/libxev/pull/204) in libxev is also required to make iOS app work. --- macos/Sources/App/iOS/iOSApp.swift | 10 +++++++++- src/renderer/Metal.zig | 10 +++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/macos/Sources/App/iOS/iOSApp.swift b/macos/Sources/App/iOS/iOSApp.swift index 4af94491c..a1aafcc7d 100644 --- a/macos/Sources/App/iOS/iOSApp.swift +++ b/macos/Sources/App/iOS/iOSApp.swift @@ -1,8 +1,16 @@ import SwiftUI +import GhosttyKit @main struct Ghostty_iOSApp: App { - @StateObject private var ghostty_app = Ghostty.App() + @StateObject private var ghostty_app: Ghostty.App + + init() { + if ghostty_init(UInt(CommandLine.argc), CommandLine.unsafeArgv) != GHOSTTY_SUCCESS { + preconditionFailure("Initialize ghostty backend failed") + } + _ghostty_app = StateObject(wrappedValue: Ghostty.App()) + } var body: some Scene { WindowGroup { diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 2aac285c6..6c7432d21 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -76,8 +76,11 @@ pub fn init(alloc: Allocator, opts: rendererpkg.Options) !Metal { errdefer queue.release(); // Grab metadata about the device. - const default_storage_mode: mtl.MTLResourceOptions.StorageMode = - if (device.getProperty(bool, "hasUnifiedMemory")) .shared else .managed; + const default_storage_mode: mtl.MTLResourceOptions.StorageMode = switch (comptime builtin.os.tag) { + // manage mode is not supported by iOS + .ios => .shared, + else => if (device.getProperty(bool, "hasUnifiedMemory")) .shared else .managed, + }; const max_texture_size = queryMaxTextureSize(device); log.debug( "device properties default_storage_mode={} max_texture_size={}", @@ -123,7 +126,8 @@ pub fn init(alloc: Allocator, opts: rendererpkg.Options) !Metal { }, .ios => { - info.view.msgSend(void, objc.sel("addSublayer"), .{layer.layer.value}); + const view_layer = objc.Object.fromId(info.view.getProperty(?*anyopaque, "layer")); + view_layer.msgSend(void, objc.sel("addSublayer:"), .{layer.layer.value}); }, else => @compileError("unsupported target for Metal"),