7

我已经看过几篇关于 iOS 的关于这个主题的帖子,但是提到 OS X 的一两次只是说要构建一个框架而不是静态库。(我找不到有不错的框架说明的帖子。)

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

最好的方法是什么?

编辑:

对于上下文:我创建了一个笔尖来NSWindowController在 Mac 应用程序中初始化一个。

4

5 回答 5

8

不,这是不可能的,因为静态库与“捆绑包”不同。

静态库是包含由库创建者链接在一起的类、代码和变量的单个文件。它不“包含”其他文件,它本质上是一个编译代码的数据库。尽管可以将 xib 的数据放在那里,但 Xcode 无法知道它在那里,因为它会在文件系统上将它们作为单独的文件查找。

选项1:(不好)

只需将 xib 与包含说明的 README 文件一起保存在静态库中即可。有点愚蠢的方式,但它很快而且不可怕,因为你已经拥有了一切。

选项2:(相当不错)

您可以创建一个“框架”,它本质上是一组代码、资源、设置等,可以被多个项目重用

框架的苹果文档: 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-用于 mac-osx 的可嵌入框架

[更新 1] 请注意,它不适用于 iOS,因为 App Store 规则不允许应用程序包中的框架。(无论如何都不是动态加载的代码)。[感谢@nielsbot,他在评论中提醒我这一点。]

[更新 2] 阅读有关 iOS 8 的更多信息,他们在这方面改变了很多东西。(由于 Apple 的 NDA,无法谈论该问题)

于 2013-10-28T22:49:42.797 回答
3

好的,我花时间整理了一个示例,说明如何做到这一点。它建立在@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) 在您的静态库构建规则中,在搜索框中输入“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:像任何其他笔尖手柄一样调用它)

于 2013-11-03T02:48:53.703 回答
1

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

然后像其他来源一样包含它*

*从来没有这样做过,但理论上它应该可以工作,对吧?

于 2013-11-01T03:26:32.090 回答
1

正如其他人指出的那样,将 nib 文件与静态库捆绑在一起的方式与将 nib 与框架捆绑在一起的方式是不可能的。静态库仅包含已编译的代码。它不是代码和其他资源集合的容器。

也就是说,如果您对此很认真,则可以选择具有相同效果的选项。基本上,你会将你的 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 之外,您可能很快就会发现您的代码还需要其他可用资源。例如图像。您可以使用相同的方法在静态库中嵌入图像或任何其他资源。

在我看来,让这个嵌入式 nib 保持最新所需的工作流程的开发人员成本相当高。如果是我,我会创建一个框架并分发它。

于 2013-11-01T23:00:09.633 回答
0

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

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

于 2020-01-15T06:36:37.060 回答