iOS通用Framework编译提示无bundle问题

解决iOS模拟器bundle拷贝问题
本文介绍了解决iOS模拟器环境下bundle文件拷贝失败的方法。通过在编译脚本中添加特定条件判断和资源文件复制逻辑,避免了模拟器环境中bundle文件路径错误导致的问题。

在编译一个通用的Framework A, 但A依赖的Framework B有个bundle, 这个bundle在真机上编译运行没问题, 但是在模拟器编译通过不了, 提示错误如下:

A/DerivedData/A/Build/Products/Debug-iphonesimulator/B/B.bundle" not found. Run 'pod install' to update the copy resources script

 

主要原因是模拟器下拷贝bundle文件失败,到build目录发现其实是bundle路径有问提, 但是这些都是pod install自动生成的, 我们可以在编译simulator时不去执行拷贝资源的脚本,有两种方案, 一种是直接修改'[CP] Copy Pods Resources', 一种是在这之前添加一个 run script, 我选择第二种, 脚本如下:

set -x
set -e

echo "executecheck-simulator.txt"


if [ "${EFFECTIVE_PLATFORM_NAME}" == "-iphonesimulator" ];
then
    FILENAME="${SRCROOT}"/check-simulator.txt

    cp -f "${SRCROOT}/Pods/Target SupportFiles/Pods-xxx/Pods-xxx-resources.sh""${SRCROOT}/Pods-xxx-resources.sh.tmp"
    sed -i "" "3 r ${FILENAME}""${SRCROOT}/Pods-xxx-resources.sh.tmp"
    cp -f "${SRCROOT}/Pods-xxx-resources.sh.tmp""${SRCROOT}/Pods/Target SupportFiles/Pods-xxx/Pods-xxx-resources.sh"
    rm -f "${SRCROOT}/Pods-xxx-resources.sh.tmp"
fi

 

使用时根据自己情况将xxx替换为Framework名称

 

其中,有几个需要注意的点:

  • 检测xcodebuild当前执行的设备, 可以通过EFFECTIVE_PLATFORM_NAME, 也可以通过PLATFORM_NAME, 其中PLATFORM_NAME表示当前Platform名称, 和Effective_platform_name一样, 但是没有-前缀
  • 如何插入内容到shell script, 使用sed命令, 注意mac下需要加""

 

 重新编译运行通过

 

<think>我们正在讨论iOS自定义框架开发中从特定bundle加载资源的问题。根据用户的问题,我们需要创建一个自定义框架,并在该框架中从指定的bundle(可能是框架自己的bundle或另一个bundle)加载资源。 在iOS中,框架(Framework)是一种将代码和资源打包在一起的方式,可以在多个应用中共享。框架有自己的bundle,我们可以从这个bundle中加载资源。 步骤概述: 1. 创建自定义框架项目。 2. 向框架添加资源(如图片、xib、故事板等)。 3. 在框架的代码中,使用正确的bundle来加载资源。 4. 在应用中使用框架并验证资源加载。 详细步骤: ### 1. 创建自定义框架项目 在Xcode中,选择File -> New -> Project,然后选择iOS -> Framework & Library -> Framework。给框架命名,并设置好语言(如Swift或Objective-C)。 ### 2. 向框架添加资源 将资源文件(如图片、音频、xib文件等)拖到框架项目中。在添加时,确保这些资源被包含在框架的target中。 ### 3. 从框架的bundle中加载资源 在框架的代码中,我们需要使用框架自己的bundle来加载资源,而不是使用主应用的bundle。因为当框架被集成到应用中时,框架的资源位于其自己的bundle中。 #### 获取框架的bundle 我们可以通过获取框架的类所在的bundle来定位资源。 在Swift中: ```swift // 在框架的代码中 let frameworkBundle = Bundle(for: SomeClassInFramework.self) ``` 在Objective-C中: ```objective-c NSBundle *frameworkBundle = [NSBundle bundleForClass:[SomeClassInFramework class]]; ``` #### 加载资源 有了框架的bundle后,我们就可以使用这个bundle来加载资源。 例如,加载图片: ```swift if let image = UIImage(named: "myImage", in: frameworkBundle, compatibleWith: nil) { // 使用图片 } ``` 或者从bundle中加载nib文件: ```swift let nib = UINib(nibName: "MyNib", bundle: frameworkBundle) ``` 或者加载其他资源文件(如plist): ```swift if let plistPath = frameworkBundle.path(forResource: "Config", ofType: "plist") { // 使用路径加载plist } ``` ### 4. 在应用中使用框架 将框架嵌入到应用中: - 将编译好的框架(.framework文件)拖到应用中,或者如果框架项目与应用项目在同一工作区,可以直接添加依赖。 - 在应用的target设置中,确保框架被添加到“Embedded Binaries”中。 然后,在应用代码中导入框架并使用其功能。框架加载资源时,会自动从自己的bundle中获取。 ### 注意事项 - 资源文件在框架中的组织:通常,我们会将资源放在一个单独的目录中,并在框架中通过相对路径访问。但是,当框架被构建后,这些资源会被放在框架bundle的根目录或你指定的目录下。因此,在加载资源时,只需提供文件名和扩展名(或者如果放在子目录中,则需要提供相对路径)。 - 资源文件的命名:为了避免冲突,建议在资源文件名前加上前缀,特别是当框架可能会被多个应用使用时。 - 资源编译:确保在框架的构建阶段(Build Phases)中,资源文件被包含在“Copy Bundle Resources”中。 ### 引用参考 在iOS开发中,通过使用`Bundle(for:)`方法可以获取框架的bundle,从而加载框架内部的资源[^1]。同时,在构建框架时,需要确保资源文件被正确复制到框架bundle中[^2]。 §§相关问题§§ 1. 如何在Swift Package Manager(SPM)管理的框架中加载资源? 2.iOS框架中,如何管理本地化字符串资源? 3. 如何从动态加载的框架(如插件)中加载资源?</think>### iOS 自定义框架开发:从特定 Bundle 加载资源 在 iOS 自定义框架开发中,从特定 Bundle 加载资源需要遵循以下关键步骤: #### 1. **资源文件组织** - 在框架项目中创建资源目录(如 `Resources` 文件夹) - 添加资源文件(图片、xib、音频等)并确保: ```none Build Phases > Copy Bundle Resources 中包含这些文件 ``` #### 2. **获取框架 Bundle** 在框架代码中使用类方法定位自身 Bundle: ```swift // Swift class FrameworkClass {} extension Bundle { static var framework: Bundle { return Bundle(for: FrameworkClass.self) } } // 使用示例 let image = UIImage( named: "logo", in: Bundle.framework, compatibleWith: nil ) ``` ```objective-c // Objective-C @implementation FrameworkResources + (NSBundle *)frameworkBundle { return [NSBundle bundleForClass:[self class]]; } @end // 使用示例 UIImage *image = [UIImage imageNamed:@"logo" inBundle:[FrameworkResources frameworkBundle] compatibleWithTraitCollection:nil]; ``` #### 3. **资源加载方法** 根据文件类型选择加载方式: ```swift // 加载图片 UIImage(named: "icon", in: Bundle.framework, with: nil) // 加载 XIB let view = Bundle.framework.loadNibNamed( "CustomView", owner: nil )?.first as? UIView // 加载数据文件 if let jsonPath = Bundle.framework.path(forResource: "config", ofType: "json") { let data = try? Data(contentsOf: URL(fileURLWithPath: jsonPath)) } ``` #### 4. **关键注意事项** 1. **资源命名规范** - 使用唯一前缀避免冲突(如 `FWK_icon.png`) - 保持文件名大小写一致(iOS 文件系统通常区分大小写) 2. **资源编译验证** - 检查 `.framework` 文件内容: ```sh # 终端命令 lipo -info YourFramework.framework/YourFramework file YourFramework.framework/Resources/* ``` 3. **资源目录结构** - 推荐目录结构: ``` YourFramework.framework ├── Headers ├── Modules ├── Resources │ ├── Images │ ├── XIBs │ └── JSON └── YourFramework ``` 4. **通用应用支持** 使用设备类型后缀自动加载对应资源[^1]: ```swift // 自动选择 @2x/@3x 图片或 ~iphone/~ipad 资源 let image = UIImage(named: "adaptive_bg", in: bundle, compatibleWith: nil) ``` #### 5. **调试技巧** - 打印 Bundle 路径检查资源位置: ```swift print("资源路径: \(Bundle.framework.resourcePath ?? "")") ``` - 使用 `NSBundle` 的 `pathsForResourcesOfType` 验证资源包含性: ```objective-c NSArray *images = [[FrameworkResources frameworkBundle] pathsForResourcesOfType:@"png" inDirectory:nil]; ``` ### 常见问题解决 - **资源未找到**:检查文件是否在 "Copy Bundle Resources" 中,确认物理文件存在于项目目录 - **内存警告**:大文件使用 `Data(contentsOf:)` 替代 `UIImage(contentsOfFile:)` - **国际化资源**:创建 `lproj` 目录并添加本地化文件[^2] > 提示:动态框架(.framework)的资源会直接打包在 bundle 中,而静态库(.a)需要额外创建 resource bundle 进行管理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值