我将以实现您预期结果的方式回答这个问题,但这可能不是最好的方法,非常欢迎改进!我是在 Cocoa Touch Framework 子项目上完成的,但如果它还不能工作,它应该很容易适应 Cocoa Touch Static Library。老实说,这更像是一个教程而不是一个答案,但无论如何......
首先要做的事情。我的解决方案的快速概述:您将在同一个工作区上拥有两个项目。一个是框架,另一个是应用程序本身。您将在框架上创建 xib/storyboard,并在框架或应用程序上使用它(尽管后者对我来说没有多大意义)。
框架项目将包含一个构建运行脚本,它将其所有资源(图像、xib、故事板)复制到一个包中,该包将成为应用程序项目的一部分。此外,框架项目将成为您的应用项目的依赖项。这样,每当您编译您的应用程序时,构建运行脚本应该会自动运行并在打包您的应用程序之前更新资源包。
设置起来肯定不是一件快速简单的事情,但这就是我回答您的问题的原因。这样我就可以自己回到这里,记住我是如何实现同样的目标的。你永远不知道老年痴呆症什么时候会袭击你:)
不管怎样,让我们开始工作吧。
-
创建/打开您应用的项目。我将把它称为 AppProject。
-
创建一个框架/库项目并将其作为子项目添加到 AppProject,或者只是将您当前的框架项目拖到 AppProject。这里重要的是框架项目是 AppProject 的子项目。我将把框架项目称为 MyFramework。
-
为您的特定项目配置您需要的任何东西。我想至少使用链接器标志-ObjC 和-all_load 是一件标准的事情。这对于这个迷你教程的目的并不是很有用,但该项目至少应该正在编译。您的工作区应该是这样的:
-
打开 AppProject 文件夹并创建一个名为 MyBundle.bundle 的新目录。
-
将 MyBundle.bundle 拖到 AppProject(这很重要:您不应该将它拖到库项目中!) .您可能希望取消选中 Copy items if needed 并选择/检查在编译您的应用程序时该捆绑包将被复制到的目标。
-
暂时别管 MyBundle.bundle。
-
转到 MyFramework 的Build Settings 并添加一个新的Run script phase。
-
这一步可能是可选的,但它对我来说就像这样,所以我将它包括在内。将刚刚创建的Run script 拖动到Compile sources 阶段的正上方。
-
编辑Run script 阶段,将其shell 更改为/bin/sh(如果还没有的话)。将脚本设置为以下(cmets 应解释脚本):
运行脚本
#!/bin/bash
echo "Building assets bundle."
# Bundle name (without the ".bundle" part). I separated this because I have different app targets, each one with a different bundle.
BUNDLE_NAME='MyBundle'
CURRENT_PATH=`pwd`
# This should generate the full path to your bundle. Might need to be adapted if the bundle
# directory you created was in another directory.
BUNDLE_PATH="$CURRENT_PATH/$BUNDLE_NAME.bundle"
# Check if the bundle exists, and removes it completely if it does.
if [ -d "$BUNDLE_PATH" ]; then
rm -rf "$BUNDLE_PATH"
fi
# Re-creates the same bundle (I know this is weird. But at least I am SURE the bundle will
# be clean for the next steps)
mkdir "$BUNDLE_PATH"
# Copy all .jpg files to the bundle
find ./ -name *.jpg -type f -print0 | xargs -0 -J% cp % "$BUNDLE_PATH"
# Copy all .png files to the bundle
find ./ -name *.png -type f -print0 | xargs -0 -J% cp % "$BUNDLE_PATH"
# Copy all .xib files to the bundle.
find ./ -name *.xib -type f -print0 | xargs -0 -J% cp % "$BUNDLE_PATH"
# Copy all .storyboard files to the bundle.
find ./ -name *.storyboard -type f -print0 | xargs -0 -J% cp % "$BUNDLE_PATH"
# This is the golden thing. iOS code will not load .xib or storyboard files, you need to compile
# them for that. That's what these loop do: they get each .xib / .storyboard file and compiles them using Xcode's
# ibtool CLI.
for f in "$BUNDLE_PATH/"*.xib ;
do
# $f now holds the complete path and filename a .xib file
XIB_NAME="$f";
# Replace the ".xib" at the end of $f by ".nib"
NIB_NAME="${f%.xib}.nib";
# Execute the ibtool to compile the xib file
ibtool --compile "$NIB_NAME" "$XIB_NAME"
# Since the xib file is now useless for us, remove it.
rm -f "$f"
done
for f in "$BUNDLE_PATH/"*.storyboard ;
do
# $f now holds the complete path and filename a .storyboard file
STORYBOARD_NAME="$f";
# Replace the ".storyboard" at the end of $f by ".storyboardc" (could've just added the final "c", but I like
# to keep both loops equal)
COMPILED_NAME="${f%.storyboard}.storyboardc";
# Execute the ibtool to compile the storyboard file
ibtool --compile "$COMPILED_NAME" "$STORYBOARD_NAME"
# Since the .storyboard file is now useless for us, remove it.
rm -f "$f"
done
- 您的工作区/设置现在应该是这样的:
- 转到 AppProject
Build phases,并将您的框架添加到 Link Binary with Libraries 部分。还将框架添加为 Target dependencies 部分。
- 似乎一切都设置好了。在框架项目上创建一个 xib 或故事板文件,并按照您通常的方式创建视图(或视图控制器)。这里没什么特别的。您甚至可以为您的组件和所有内容设置自定义类(只要自定义类在框架项目中,而不是在应用程序项目中)。
编译应用项目之前
编译应用项目后
- 在您的代码中,无论您需要在何处加载您的 NIB/Xib,请使用以下代码之一。如果你能做到这一点,我什至不需要告诉你,你需要将这些代码调整为你想用 xib/Storyboard 做的任何事情,所以......享受吧:)
为 UITableView 注册单元格 xib:
NSString* bundlePath = [[NSBundle mainBundle] pathForResource:@"MyBundle" ofType:@"bundle"];
NSBundle* bundle = [NSBundle bundleWithPath:bundlePath];
UINib* nib = [UINib nibWithNibName:@"TestView" bundle:bundle];
[tableView registerNib:nib forCellReuseIdentifier:@"my_cell"];
将 UIViewController 推送到导航控制器:
NSString* bundlePath = [[NSBundle mainBundle] pathForResource:@"MyBundle" ofType:@"bundle"];
NSBundle* bundle = [NSBundle bundleWithPath:bundlePath];
UIViewController* vc = [[UIViewController alloc] initWithNibName:@"BundleViewController" bundle:bundle]; // You can use your own classes instead of the default UIViewController
[navigationController pushViewController:vc animated:YES];
从它的初始 UIViewController 模态呈现一个 UIStoryboard:
NSString* bundlePath = [[NSBundle mainBundle] pathForResource:@"MyBundle" ofType:@"bundle"];
NSBundle* bundle = [NSBundle bundleWithPath:bundlePath];
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"BundleStoryboard" bundle:bundle];
UIViewController* vc = [storyboard instantiateInitialViewController];
vc.modalPresentationStyle = UIModalPresentationFormSheet;
vc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:vc animated:YES completion:^{}];
如果它对您(或访问此问题/答案的人)不起作用,请告诉我,我会尽力提供帮助。