How can I include a nib in an OS X static library?
No it isn't possible, because a static library is not the same as a "bundle".
A static library is a single file that contains classes, code and variables that were linked together by the library creator. It does not "contain" other files, it is essentially a database of compiled code. Although it would be possible to put the data for the xibs in there, Xcode would have no way of knowing that it was in there, as it looks for them as individual files on the filesystem.
Option 1: (not good)
Just keep the xib with the static library with a README file including instructions. Kind of dumb way but it's fast and not horrible since you already have everything.
Option 2: (fairly good)
You may create a "Framework" which is essentially a bundle of code, resources, settings etc which may be reused by multiple projects
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
Random guide for OS X Frameworks: (it's with older version of Xcode but it's the same concept) http://www.intridea.com/blog/2010/12/28/a-visual-guide-to-creating-an-embeddable-framework-for-mac-osx
[UPDATE 1] Note that it won't work with iOS, since frameworks in app bundles aren't allowed by the App Store rules. (Dynamically loaded code isn't anyway). [Credit to @nielsbot who remind me of this in comments.]
[UPDATE 2] Read more about iOS 8 they changed a lot of things in this regard. (Cannot talk on that because of the Apple's NDA)
Ok I took the time to put together a sample of how you can do this. It's built on @TomSwift's answer and this: http://www.cocoanetics.com/2012/02/xcode-build-rules/
I uploaded a sample project here: https://github.com/nielsbot/StaticLibraryXIB
You add a custom rule for XIB files to your static library target. It inserts a class method on NSNib
that instantiates your XIB whenever it's called. The method is the name of your XIB. So if you have "TestNib.xib", you would call +[NSNib TestNib]
.
In more detail:
Add a custom compiler for XIB files (This is really just a bit of shell script we want to run for each XIB file in the project)
a) In your static lib build rules, enter "XIB" in the search box and click the "Copy to target" button to create a XIB file rule in your project.
b) leave Process as "Interface Builder files", set Using to "Custom script:" Here's the 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"
This will transform your XIB files into .m files that will be automatically compiled into your project. The template is CompiledNibTemplate.m, which looks like this:
#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
Based on the example above, if your XIB was called "StaticLibraryWindowController.xib",
NSNib
will now have a new class methodStaticLibraryWindowController
. )Invoking[ NSNib StaticLibraryWindowController ]
will return anNSNib
object. You can call-instantiateWithOwner:topLevelObjects:
on that like any other nib handle)