我已经看过几篇关于iOS的帖子来解决这个问题,但OS X的一两个提到只是说构建一个框架而不是一个静态库。 (我找不到具有良好框架说明的帖子。)
我已经将我的项目创建为静态库,并相应地编写了整个代码。现在,我只是想把我的框架放在一个演示应用程序中,它抱怨丢失的笔尖。作为权宜之计,我已将笔尖复制到父项目中,但我希望将整个项目正确划分。
最好的方法是什么?
修改
对于上下文:我已经创建了一个nib来初始化Mac应用中的NSWindowController
。
答案 0 :(得分:8)
不可能,因为静态库与“bundle”不同。
静态库是一个单独的文件,其中包含由库创建者链接在一起的类,代码和变量。它不“包含”其他文件,它本质上是编译代码的数据库。虽然可以将xibs的数据放在那里,但Xcode无法知道它在那里,因为它将它们视为文件系统上的单个文件。
选项1 :(不好)
使用包含说明的README文件将xib与静态库保持在一起。有点愚蠢的方式,但它很快,而且不是很可怕因为你已经拥有了所有东西。
选项2 :(相当不错)
您可以创建一个“框架”,它本质上是一组代码,资源,设置等,可以被多个项目重用
Apple Doc for Framework: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
OS X框架的随机指南:(它与Xcode的旧版本有关,但它的概念相同) http://www.intridea.com/blog/2010/12/28/a-visual-guide-to-creating-an-embeddable-framework-for-mac-osx
[更新1] 请注意,它不适用于iOS,因为App Store规则不允许应用程序包中的框架。 (无论如何都不是动态加载的代码)。 [感谢@nielsbot,他在评论中提醒我。]
[更新2] 阅读有关iOS 8的更多信息,他们在这方面改变了很多东西。 (由于Apple的NDA,不能谈论这个)
答案 1 :(得分:4)
好的,我花时间整理了一些如何做到这一点的样本。它建立在@ TomSwift的答案之上:http://www.cocoanetics.com/2012/02/xcode-build-rules/
我在这里上传了一个示例项目:https://github.com/nielsbot/StaticLibraryXIB
您可以将XIB文件的自定义规则添加到静态库目标。它在NSNib
上插入一个类方法,只要它被调用就会实例化你的XIB。该方法是您的XIB的名称。因此,如果您有“TestNib.xib”,则可以调用+[NSNib TestNib]
。
更详细:
为XIB文件添加自定义编译器(这实际上只是我们想要为项目中的每个XIB文件运行的一些shell脚本)
a)在静态lib构建规则中,在搜索框中输入“XIB”,然后单击“复制到目标”按钮在项目中创建XIB文件规则。
b)将Process保留为“Interface Builder files”,将Using设置为“Custom script:”这是自定义脚本:
/usr/bin/ibtool --output-format human-readable-text --compile "$TARGET_TEMP_DIR/$INPUT_FILE_BASE.nib" "$INPUT_FILE_DIR/$INPUT_FILE_NAME"
Hexdump=`hexdump -v -e '1 1 "0x%02x, "' "$TARGET_TEMP_DIR/${INPUT_FILE_BASE}.nib"`
Datalength=`stat -f "%z" ${TARGET_TEMP_DIR}/${INPUT_FILE_BASE}.nib`
sed -e "s/HEX_DUMP/$Hexdump/g" -e "s/NIB_NAME/${INPUT_FILE_BASE}/g" -e "s/HEX_LENGTH/$Datalength/g" "${SRCROOT}/NibTest/CompiledNibTemplate.m" > "$DERIVED_FILE_DIR/$INPUT_FILE_BASE.nib.m"
这会将您的XIB文件转换为.m文件,这些文件将自动编译到您的项目中。模板是CompiledNibTemplate.m,如下所示:
#import <Cocoa/Cocoa.h>
@implementation NSNib (NIB_NAME)
+(instancetype)NIB_NAME
{
NSData * data = [ NSData dataWithBytesNoCopy:(void*)(const unsigned char[]){ HEX_DUMP } length:(NSUInteger){ HEX_LENGTH } freeWhenDone:NO ] ;
NSNib * result = [ [ NSNib alloc ] initWithNibData:data bundle:nil ] ;
return result ;
}
@end
根据上面的示例,如果您的XIB被称为“StaticLibraryWindowController.xib”,NSNib
现在将有一个新的类方法StaticLibraryWindowController
。 )调用[ NSNib StaticLibraryWindowController ]
将返回NSNib
个对象。您可以像其他任何笔尖句柄一样调用-instantiateWithOwner:topLevelObjects:
答案 2 :(得分:1)
答案 3 :(得分:1)
正如其他人所指出的那样,将nib文件与静态库捆绑的方式与将nib与框架捆绑的方式相同是不可能的。静态库仅包含已编译的代码。它不是代码和其他资源集合的容器。
那就是说,如果你认真对待这个问题,你就有了一个可以产生同样效果的选择。基本上你将base64编码你的nib到一个字符串,并在运行时重新构建它。这是我的食谱:
1)将.xib编译为二进制.nib格式。使用XCode或ibtool。
2)使用工具将.nib编码为base64文本。在OSX上,您可以使用openssl
从终端执行此操作:
openssl base64 -in myNib.nib -out myNib.txt
3)将base64字符串复制/粘贴到您的一个源文件中。从中构造一个NSString:
NSString* base64 = @"\
TklCQXJjaGl2ZQEAAAAJAAAAHgAAADIAAAA2AAAAjAAAAG4AAADuAwAAEQAAAPwG\
AACHgIaChoGPh4eCjoGJj46CnYGCnoGCn4GBoIKEooaKqIGOqYGCqoGQq4iMs4WC\
uIGEuYePwIaBxoWMy4SCz4GG0IGI0YWM1oGE14aL3YeO5IGE5YeC7IGF7YGKVUlG\
...
ZVN0cmluZwCHgQ0AAABVSUZvbnQAiIBOU0FycmF5AIeATlNGb250AI6AVUlQcm94\
eU9iamVjdACIgQMAAABVSUNvbG9yAIeAVUlWaWV3AA==";
4)编写代码将base64字符串解码为NSData:
NSData* d = [[NSData alloc] initWithBase64EncodedString: base64 options: NSDataBase64DecodingIgnoreUnknownCharacters];
5)从NSData构建一个UINib:
UINib* nib = [UINib nibWithData: d bundle: nil];
6)使用你的笔尖:
NSArray* nibItems = [nib instantiateWithOwner: nil options: 0];
现在,您可能最终需要更改代码中的一些内容。如果您使用init
或initWithNibName:bundle:
从笔尖创建视图控制器,那么这不会“正常工作”。为什么?因为这些机制在一个包(通常是应用程序包)中查找nib,而你的nib将不在那里。但是您可以修复代码中的任何视图控制器,以便从我们刚刚重构的UINib加载。以下是描述此过程的链接:http://www.indelible.org/ink/nib-loading/
除了.nib之外,您可能很快发现除了代码之外还需要其他可用资源。例如。图片。您可以使用相同的方法在静态库中嵌入图像或任何其他资源。
在我看来,保持这个嵌入式笔尖更新所需的工作流程的开发人员成本非常高。如果是我,我只是创建一个框架并分发它。
答案 4 :(得分:0)
使用Xcode 11,您只需创建一个包目标,然后从库代码中引用该包即可引用该笔尖。用分发包分发库。
iOS上的类似过程: https://www.youtube.com/watch?v=WQI02KR9kQw