我已经看到了几篇有关iOS的主题的文章,但是提到OS X的一两个内容只是说要构建框架而不是静态库。 (我找不到具有不错的框架说明的帖子。)
我已经将我的项目创建为静态库,并对整个内容进行了相应的编码。现在,我只想将我的框架放在演示应用程序中,并且抱怨缺少笔尖。作为权宜之计,我已将笔尖复制到父项目中,但是我想适当地划分整个内容。
最佳方法是什么?
编辑:
对于上下文:我创建了一个笔尖来初始化Mac应用中的NSWindowController
。
不,这不可能,因为静态库与“捆绑包”不同。
静态库是一个单个文件,其中包含由库创建者链接在一起的类,代码和变量。它不“包含”其他文件,它实质上是一个已编译代码的数据库。尽管可以将xib的数据放在其中,但是Xcode无法知道它是否在其中,因为Xcode会将它们作为文件系统中的单个文件进行查找。
选项1 :(不好)
只需将xib保留在带有说明的README文件的静态库中。有点愚蠢的方法,但是它很快而且并不可怕,因为您已经拥有了一切。
选项2 :(相当不错)
您可以创建一个“框架”,实质上是一堆代码,资源,设置等,可以被多个项目重用
Apple Doc for Framework:https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
OS X Framework的随机指南:(与旧版本的Xcode相同,但概念相同)http://www.intridea.com/blog/2010/12/28/a-visual-guide-to-creating-an-embeddable-framework-for-mac-osx
[UPDATE 1]请注意,它不适用于iOS,因为App Store规则不允许应用捆绑包中的框架。 (不是动态加载的代码)。 [感谢@nielsbot,他在评论中让我想起了这一点。]
[UPDATE 2]阅读有关iOS 8的更多信息,他们在这方面进行了很多更改。 (由于苹果的NDA不能谈论它)
好吧,我花了一些时间来整理如何执行此操作的示例。它基于@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)在您的静态库构建规则中,在搜索框中输入“ XIB”,然后单击“复制到目标”按钮以在您的项目中创建XIB文件规则。
b)将Process保留为“ Interface Builder文件”,将“使用”设置为“自定义脚本:”这是自定义脚本:
/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:
)
正如其他人指出的那样,将nib文件与静态库捆绑在一起的方式与将nib与框架捆绑在一起的方式是不可能的。静态库仅包含编译后的代码。它不是用于收集代码和其他资源的容器。
也就是说,如果您对此很认真,则可以选择具有相同效果的选项。基本上,您将使用base64将笔尖编码为字符串,然后在运行时重构它。这是我的食谱:
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:
从笔尖创建视图控制器,那么这将无法正常工作。为什么?因为这些机制会在笔尖的捆绑包(通常是应用程序捆绑包)中查找,所以您的笔尖不会在那里。但是,您可以修复代码中的任何视图控制器,以从刚刚重构的UINib加载。这是描述此过程的链接:http://www.indelible.org/ink/nib-loading/
您可能会很快发现,除了.nib之外,您还需要其他可用于代码的资源。例如。图片。您可以使用相同的方法在静态库中嵌入图像或任何其他资源。
我认为,使此嵌入式笔尖保持最新状态所需的工作流程开发人员成本非常高。如果是我,我将创建一个框架并将其分发。
使用Xcode 11,您只需创建一个包目标,并从库代码中引用该包即可引用该笔尖。使用分发包分发库。