如何在OS X静态库中包含nib?

时间:2013-10-25 07:12:20

标签: xcode macos frameworks libraries

我已经看过几篇关于iOS的帖子来解决这个问题,但OS X的一两个提到只是说构建一个框架而不是一个静态库。 (我找不到具有良好框架说明的帖子。)

我已经将我的项目创建为静态库,并相应地编写了整个代码。现在,我只是想把我的框架放在一个演示应用程序中,它抱怨丢失的笔尖。作为权宜之计,我已将笔尖复制到父项目中,但我希望将整个项目正确划分。

最好的方法是什么?

修改

对于上下文:我已经创建了一个nib来初始化Mac应用中的NSWindowController

5 个答案:

答案 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

https://developer.apple.com/library/mac/documentation/macosx/conceptual/BPFrameworks/Tasks/CreatingFrameworks.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]

更详细:

  1. 为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
    
  2. 根据上面的示例,如果您的XIB被称为“StaticLibraryWindowController.xib”,NSNib现在将有一个新的类方法StaticLibraryWindowController。 )调用[ NSNib StaticLibraryWindowController ]将返回NSNib个对象。您可以像其他任何笔尖句柄一样调用-instantiateWithOwner:topLevelObjects:

答案 2 :(得分:1)

只需将你的笔尖转换为客观的C类:http://kosmaczewski.net/projects/nib2objc/

然后包括你的其他来源*

*从未这样做过,但从理论上说它应该有效,对吧?

答案 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];

现在,您可能最终需要更改代码中的一些内容。如果您使用initinitWithNibName:bundle:从笔尖创建视图控制器,那么这不会“正常工作”。为什么?因为这些机制在一个包(通常是应用程序包)中查找nib,而你的nib将不在那里。但是您可以修复代码中的任何视图控制器,以便从我们刚刚重构的UINib加载。以下是描述此过程的链接:http://www.indelible.org/ink/nib-loading/

除了.nib之外,您可能很快发现除了代码之外还需要其他可用资源。例如。图片。您可以使用相同的方法在静态库中嵌入图像或任何其他资源。

在我看来,保持这个嵌入式笔尖更新所需的工作流程的开发人员成本非常高。如果是我,我只是创建一个框架并分发它。

答案 4 :(得分:0)

使用Xcode 11,您只需创建一个包目标,然后从库代码中引用该包即可引用该笔尖。用分发包分发库。

iOS上的类似过程: https://www.youtube.com/watch?v=WQI02KR9kQw