Nat! bio photo

Nat!

Senior Mull

Twitter Github Twitch

Decoding old Nibs. A sad tale of vendor lock-in and abandonment.

I have over 200 Nib Files of which most of them have EOInterface objects in them. The problem is, that they don’t open in the newer Interface Builders anymore.

Nibs are an Apple user interface serialization format. Why can’t I edit them ? See Idea #3

With “new” i mean any Interface Builder with a version number higher than 2, especially those, that are integrated into Xcode. If I redo 200 NIBs manually, I am spending a year on this alone.

Idea #1: Use MEUnarchiver to dearchive

Use MEUnarchiver to decode the NIB archives. Create a fake runtime to dynamically create classes, that decode and detect the archive until everything decodes and the initWithCoder: method has basically written itself.

That was technological too interesting not to try, until I realized a few hours later, that I don’t have a problem decoding in the first place… The nibs still load fine, but I can’t edit them.

Abandoned.

Idea #2: Write out ObJC code during NSKeyedArchiver

Load the NIB “manually” and substitute various strategic classes with invocation sinks a la

- (void) forwardInvocation:(NSInvocation *)invocation
{
   NSLog( @"added -[%@ %@]", _name, NSStringFromSelector( [invocation selector]));
   [_invocations addObject:invocation];
}

- (NSMethodSignature *) methodSignatureForSelector:(SEL)selector
{
   return( [NSMethodSignature signatureWithObjCTypes:"v@:@"]);
}

then use a custom subclass of NSKeyedArchiver that in parallel to the regular operation also archives into ObjC code. That sounded promising.

Unfortunately, the objects that are dearchived are not necessarily the same as those that you would want to archive. In other word dearchiving is sort of a lossy operation.

The basic idea could still work, but it’s a lot of work and piggybacking on top of NSKeyedArchiver is probably not a good idea.

Idea #3: ibtool with custom IBPlugin

I created some IBPlugins that contained the required Frameworks. I thought that ibtool could magically transform the NIB to XIB without complaining and I could deal with the other problems somehow later. IBPlugin is a technology, that was abandoned by Apple with the advent of Xcode 4.

But it doesn’t work, as ibtool is eager to note:

EOAspectConnector connections are not supported by Interface Builder 3.0.

More wasted time for another dead end.

Idea #4: nib2objc

Use and modify nib2objc. As amusing as it is tragic this projects GUI uses Apple’s equally abandoned Garbage Collection technology. So it doesn’t work anymore. There are some maintained forks, which also mostly still use GC …

Anyway all these variants use ibtool to convert the input into a plist or XML representation first, so this is a non-starter.

I would have to mix up Idea #1 with #4 to get something going here, and nib2objc is for UIKit apps anyway.

Idea #5: Use GORM to edit the files

I didn’t find any recent success story of someone getting Gnustep to run on OS X. So I assume GORM doesn’t run on OS X but just on Linux, that’s already pretty inconvenient for me. I don’t know how compatible the palettes are. It sounds like a lot of work. Also GORM looks extremely ancient.

Idea #6: Convert NIBs to post 10.2 “human readable” XML

I am not sure what that’s gonna buy me. The XML is readable but highly unscrutable. This is in no way better than Idea #1.

Idea #7: Use IBInspectable

This doesn’t really work well for the kind of custom bindings EOInterface needs. It’s good, that you can put NSObject based instances into XIBs (again ?), but the kind of typed connection EOInterface has are not possible with IBOutlet alone (unless you expose every EOAssociation). But I can’t load the NIBs anyway, because the loader complains even with all classes present.


What I really want

What I really want is a simple file format, where I can structure the UI without any geometry or style information. Just type it in like the following example, and a custom unarchiver creates an ugly but working UI from it:

NSWindow  						window
	MyScrollView
		NSTableView
			NSTableColumn			name
			NSTableColumn			age
				EOTableColumnAssociation	assoc0
			NSTableColumn			sex
			NSTableColumn			birthday
				NSDateFormatter	birthdayFormatter
	NSView							whatever

NSWindow  						window2
	NSBox
		NSTextField				name2

EODisplayGroup					group

This would build the hierarchy and gives out classes and IDs to objects. The first string is the class, the second string is the ID. The hierarchy is formed by identation.

I want to make connections with outlets, actions and EOAssociations somewhat similar to this, possibly in the same file. The property are accessed with standard KVC. This would be a separate section, or maybe just a separate file for now.

// create an action and connect an outlet
#name
{
	action = FirstResponder.doSomething;
}

#FilesOwner
{
	outlet = birthday;
}


#assoc0
{
	value	 = group.age;
	enabled = group.isEditable;
}

I want to style everything with some sort of CSS or probably more than likely just with CSS and key value coding itself. Also in a separate file for now:

#window2
{
   frame: 				25px 50px 75px 100px;
   backgroundColor: 	#ffeecc;
}

#birthdayFormatter
{
	formatString:			L"hhmmdd HHMM"M;
}

This could be a little bit too string based, but that’s solvable, with some linting.

This is actually just as easily said as it is done (2 days of work). I created MulleIB, which can do the deserialization in very simple cases. Now I need to get the serialization happening, but that shouldn’t be too bad either, if I forego using NSCoder and just do it myself also.


Post a comment

All comments are held for moderation; basic HTML formatting accepted.

Name:
E-mail: (not published)
Website: