You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将App主Main Storyboard存入Swift Package并兼容info.plist配置

解决方案

前置修正:完善Package.swift配置

你当前的Package.swift存在两处需要调整的问题:

  1. 测试Target名称和主Target重名,会导致编译报错
  2. 没有显式声明资源文件,正式打包时可能出现资源丢失

修正后的完整代码如下:

// swift-tools-version:5.5
import PackageDescription

let package = Package(
    name: "FooPackage",
    defaultLocalization: "en",
    products: [
        .library(name: "FooPackage", targets: ["FooPackage"]),
    ],
    targets: [
        .target(
            name: "FooPackage",
            dependencies: [],
            // 声明资源目录
            resources: [.process("Resources")]
        ),
        // 修正测试Target名称
        .testTarget(
            name: "FooPackageTests",
            dependencies: ["FooPackage"]),
    ]
)

可行方案(两种可选)

方案1:放弃info.plist的NSMainStoryboardFile配置,手动加载主Storyboard(更推荐,无兼容性问题)

该方案完全避开info.plist只能读取主Bundle资源的限制,是苹果生态推荐的标准处理逻辑:

  1. 首先在Swift Package内暴露公共的Storyboard访问API,添加代码到FooPackage.swift:
import AppKit

public extension NSStoryboard {
    // 对外暴露包内的主Storyboard实例
    static let packageMainMenu = NSStoryboard(name: "Main Menu", bundle: .module)
}

// 也可以直接暴露初始化好的入口控制器,减少宿主侧代码
public func getPackageMainInitialController() -> NSViewController? {
    NSStoryboard.packageMainMenu.instantiateInitialController() as? NSViewController
}
  1. 宿主App侧调整配置和逻辑:
  • 删除info.plist中Main storyboard file base name (macOS)配置项
  • 在AppDelegate中手动初始化窗口,加载包内的Storyboard:
import AppKit
import FooPackage

class AppDelegate: NSObject, NSApplicationDelegate {
    var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        guard let initialController = getPackageMainInitialController() else {
            fatalError("加载包内主Storyboard失败")
        }
        window = NSWindow(contentViewController: initialController)
        window.makeKeyAndOrderFront(nil)
        NSApp.activate(ignoringOtherApps: true)
    }
}

方案2:编译时拷贝Storyboard到宿主App主Bundle(兼容原有info.plist配置)

如果不想修改原有App的启动逻辑,可以通过编译阶段配置把包内的Storyboard拷贝到宿主主Bundle,直接适配原有info.plist的配置:

  • 选中宿主App的Xcode工程,点击对应Target,切换到Build Phases标签
  • 点击左上角+号,选择New Copy Files Phase
  • 目标位置选择Resources,可按需勾选Copy only when installing
  • 点击阶段下方的+号,找到FooPackage下的Base.lproj/Main Menu.storyboard以及所有本地化版本的对应storyboard文件添加到列表中
  • 保留info.plist中的NSMainStoryboardFile配置不变即可正常使用

注意事项

如果是iOS项目,上述逻辑完全通用,只需要把NSStoryboard替换为UIStoryboard,窗口初始化逻辑调整为iOS对应的实现即可。

内容的提问来源于stack exchange,提问作者Alexander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 22:06:00