2013-10-25 51 views
8

我已经看过几篇关于iOS的文章,但是关于OS X的一两句话只是说要构建一个框架而不是一个静态库。 (我找不到有体面的框架指令的帖子。)如何在OS X静态库中包含一个笔尖?

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

什么是最好的方法?

编辑:

对于背景:我创建了一个笔尖在Mac应用程序初始化一个NSWindowController

+0

代码创建VC代替? – Kevin

+0

我可能误解了这个问题,但似乎在网上有一些关于安静的文章。 以下是几个: * http://www.galloway.me.uk/tutorials/ios-library-with-resources/ * http://www.arcanelab.com/post/43939133725/creating-and -using-a-static-library-with-a-resources –

+0

我继续并创建了一个工作示例。实际上花了几个小时!检查我的答案。 – nielsbot

回答

7

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

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

选项1:(不好)

只要保持厦门国际银行与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-embeddable-framework-for-mac-osx

[更新1] 注意,它不会与iOS工作,因为在应用程序束框架不被App Store的规则所允许。 (动态加载的代码是不是)。 [感谢@nielsbot谁提醒我这评论]

[更新2] 了解更多关于iOS 8的他们改变了很多东西在这方面。 (不能上,由于苹果的保密协议的商谈)

+0

框架是要走的路。尽管如此, –

+1

不适用于iOS,因为App Store规则不允许应用程序包中的框架。 (好吧,动态加载的代码不是) – nielsbot

+0

我继续前进并创建了一个工作示例。实际上花了几个小时!检查我的答案。 – nielsbot

1

简单地转换你笔尖为目标C级:http://kosmaczewski.net/projects/nib2objc/

然后包括你将你的其他来源*

*从来没有这样做,而是理论上它应该工作,对吧?

+1

人们为了声誉而做的事情。 :p只是开玩笑,很酷的建议,将调查。 – Moshe

+0

那么一个静态库并不意味着它有任何的UI信息。 – Mojtaba

1

正如其他人指出的那样,将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]; 

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

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

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

+0

如果你打算走这条路,不要用base64编码它;只需创建一个原始字节值的C数组,然后为其分配'NSData'。这就是说,这会起作用,但它也会膨胀你的二进制文件的大小。 –

+0

@Dave DeLong。好点,我没有想过使用c数组。你仍然需要一个工具来将二进制代码编码为十六进制符号,是的? – TomSwift

+0

是的,你仍然需要一个工具来生成代码。 –

4

好吧,我花时间把你如何做到这一点的样本放在一起。它是建立在@ TomSwift的答案,这一点:http://www.cocoanetics.com/2012/02/xcode-build-rules/

我在这里上传了一个样本项目:https://github.com/nielsbot/StaticLibraryXIB

您添加的厦门国际银行文件自定义规则,以你的静态库的目标。它在NSNib上插入一个类方法,在调用XIB时实例化你的XIB。该方法是您的XIB的名称。所以如果你有“TestNib.xib”,你可以拨打+[NSNib TestNib]

的详细信息:

  1. 添加XIB文件自定义编译器(这仅仅是一个有点shell脚本的,我们要为项目中的每个XIB文件运行)

    一)在静态库构建规则中,在搜索框中输入“XIB”,然后单击“复制到目标”按钮以在项目中创建XIB文件规则。

    B)离开过程为“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 
    
  2. 根据上面的例子,如果你的XIB被称为“StaticLibraryWindowController.xib”,NSNib现在有一个新的类方法StaticLibraryWindowController。 )调用[ NSNib StaticLibraryWindowController ]将返回一个NSNib对象。你可以打电话-instantiateWithOwner:topLevelObjects:像那个像其他笔尖手柄)

+0

我正要吓坏了 - 并且因为肮脏而阅读 - (跛脚/不正确)授予回答者的愚蠢的帖子..与您的回购链接和故事..然后我看到了您的答案。对你有好处...还有关于这个问题的注意事项是...... [这样的东西,它允许一个嵌入数据在任何二进制,捆绑,lib等](https://github.com/Daij-Djan/DDMountainNotifier /blob/master/MountainNotifier/DDEmbeddedDataReader.h) –

+0

另外,我听说动态代码加载的一些限制已经在iOS 8中解除了...因此,这可能不再适用 – nielsbot

+0

@alexgray这非常酷,谢谢。 – nielsbot

相关问题