NSView and Autresizing. Yes, Again.
The first post I made on this blog had to do with NSView’s autoresizing behavior being unreliable. As a Cocoa UI developer, this is a real problem that I just have to deal with. But, that’s not the worst thing about autoresizing in NSView. The worst thing about autoresizing in NSView is that setting an autoresizing mask requires that your view controller or window controller explicitly set the size and position of the view within its superview before it can set the autoresizing mask. And whenever the view hierarchy changes, lets say that you need your layout to accommodate a new sibling view at some level of the hierarchy, you have to recalculate everyone’s frame and reset everyone’s mask at that level. Icky, dirty code.
I can see that Cocoa’s getting more sophisticated with how it approaches layout. We can use “layout managers” with CALayers that have this great “constraints” system. From the docs:
Constraint-based layout allows you to describe the position and size of a layer by specifying relationships between a layer and its sibling layers or its superlayer
Relationships. That makes more sense. I want my views to have relationships to each other and I want the views or some layout manager to have the responsibility of maintaining those relationships when the view hierarchy changes, not the controller classes. That’s not what view controllers and window controllers are for.
So I wonder why all this great layout development for layers and not views? Since layers aren’t in the responder chain, they’re not a viable view substitute and I can’t imagine that CALayer will ever become an NSResponder because of its relationship to another framework that we can’t talk about. Maybe NSView is on its way out? There are slight hints that some changes are underway, but even if that’s the case, I can’t imagine that it’ll happen any time soon. NSView does a lot. So, how about an NSViewLayoutManager class in the mean time? Or new options for autoresizing masks? Yay! We Love View!
I filed a bug report requesting a layout manager class for NSView: Bug ID# 5809928.
March 20th, 2008 at 3:05 pm
After playing (well working) with the framework that shall not be named for a while I’m really hoping that AppKit will be put to pasture sooner rather than later. Although it does have layout limitations, obviously because of limitations of the device it is running on, things are so much cleaner.
I’m a big fan of CALayer’s layout options, it is really as simple or as complex as you need it to be, and that’s a big plus. Good luck with your bug!
March 20th, 2008 at 3:20 pm
Yeah, after taking a look at the other framework I also can’t help but thinking that this is the beginning of the end of AppKit. But I imagine that it’ll take a long time. Hope that other framework gets a different license agreement before then ; )
March 23rd, 2008 at 10:32 am
I don’t think you really want to get rid of AppKit.
That would mean getting rid of all 177 public classes listed in the AppKit headers, many of which solve some very tricky programming problems. Practically every modern piece of Mac software in use or currently in development (with a few notable exceptions) is based on AppKit.
It sounds like what you want is an updated/refreshed view API, which is totally reasonable and possible to do without tossing out the entire framework. The layout techniques in NSView are one part of a much larger body of code.
March 23rd, 2008 at 11:57 am
Haha, no I don’t want to get rid of AppKit, but I do want a refreshed/updated view API. I don’t think that’s any secret : )
March 25th, 2008 at 1:44 am
The solution to your problems is quite simple and described in “View Programming Guide” in the same section you quoted in your first blog:
“When you turn off a view’s autoresizing, all of its descendants are likewise shielded from changes in the superview. Changes to subviews, however, can still percolate downward. Similarly, if a subview has no autoresize mask, it won’t change in size, and therefore none of its subviews autoresize.
A subclass can override resizeSubviewsWithOldSize: or resizeWithOldSuperviewSize: to customize the autoresizing behavior for a view. “
March 25th, 2008 at 2:50 am
Hi twobyte,
I could subclass each of the views in my example project from the first post and hard code the resizing behavior using these methods. It would work in this case.
The one that stays centered is easy, but for the one that resizes with the window, I’ll have to make some iVars to keep track of the margins I’m trying to maintain since I can’t get them from NSView. I’ll also want to subclass the setAutoresizingMask method in case that information changes during runtime. Already, things are getting a little messy, but that’s fine, there are two views in that example.
In a medium to large interface project, this kind of approach isn’t really maintainable and really susceptible to bugs.
I think that if you want to define your own layout behavior for NSView, it’s cleaner and easier to debug if you make some sort of layout class that you keep in NSView instead of using the built-in autoresizing. You could still use the masks, but why limit yourself to those options at that point?
Also, this still doesn’t change the issue I’m ranting about in this post, which is, I think, the harder thing to deal with when you have a view hierarchy that changes while the app is running. A constraints based system is a much nicer way to define a layout for a view hierarchy that is going to change during runtime.
March 25th, 2008 at 10:04 am
I’ve been using the AppKit since 1989, and I’m glad to see that Apple’s taking a long hard look at what we’ve learned from it, and how a new UI framework should be implemented. I’m not sure that we’re looking at the “beginning of the end of the AppKit”, but if we are, that’s probably a good thing.
I do hope that CocoaTouch is made available for Mac apps to use. It’s a better implementation in many ways, and it was designed by people who lived and breathed the AppKit for decades.
-jcr
March 28th, 2008 at 8:43 pm
I don’t understand what is the framework that “shall not be named”. Cocoa touch clearly has a name already. (?) And Cathy, please post your NSView layout manager for others to use.
April 17th, 2008 at 11:01 pm
Great blog. Went right into my RSS reader.
A small tip (that someone else handed to me). If you’re going to post bug-report numbers publicly, you might want to use the ‘rdar’ URL. Supposedly, it’ll help Apple folks find quickly look up bug reports. Details here: http://rentzsch.com/notes/rdarUrls