Dynamically loading a part of a Window in Cocoa
-
I have an area of a Window (in my MainMenu.xib) which I'd like to populate
dynamically with unrelated "views" such as an NSTable, IKImageBrowserView
etc. at different points of time depending on some user-selected criteria.
- How do I define this area of the window such that it can be "replaced"
with different views?
- How do I attach a table or some other view to this area of the window?
(Is it enough to place a generic NSView there and add a subview each time?
I'm fairly new to Cocoa, so any pointers are welcome) -
On 1 Jul 2009, at 09:21, Debajit Adhikary wrote:> I have an area of a Window (in my MainMenu.xib) which I'd like to
> populate
> dynamically with unrelated "views" such as an NSTable,
> IKImageBrowserView
> etc. at different points of time depending on some user-selected
> criteria.
>
> - How do I define this area of the window such that it can be
> "replaced"
> with different views?
Stick an NSView in the gap, add an outlet to your controller, and
connect it up.> - How do I attach a table or some other view to this area of the
> window?
Using add/removeSubview:> (Is it enough to place a generic NSView there and add a subview each
> time?
> I'm fairly new to Cocoa, so any pointers are welcome)
Yes -- at least that's what I do, if I'm doin it rong, hopefully
someone will tell me :)
Bob -
On Jul 1, 2009, at 12:21 AM, Debajit Adhikary wrote:> I have an area of a Window (in my MainMenu.xib) which I'd like to
> populate
> dynamically with unrelated "views" such as an NSTable,
> IKImageBrowserView
> etc. at different points of time depending on some user-selected
> criteria.
>
> - How do I define this area of the window such that it can be
> "replaced"
> with different views?
> - How do I attach a table or some other view to this area of the
> window?
>
> (Is it enough to place a generic NSView there and add a subview each
> time?
> I'm fairly new to Cocoa, so any pointers are welcome)
The typical way to do this is with an NSTabView. YOu can show the
tabs or not.
-jcr -
Perhaps the simplest way is to use a NSTabView - (you can set it to
tabless). Then create all of your 'unrelated views' in separate tabs,
and switch the tabs in your code.
On Jul 1, 2009, at 3:21 AM, Debajit Adhikary wrote:> I have an area of a Window (in my MainMenu.xib) which I'd like to
> populate
> dynamically with unrelated "views" such as an NSTable,
> IKImageBrowserView
> etc. at different points of time depending on some user-selected
> criteria.
>
> - How do I define this area of the window such that it can be
> "replaced"
> with different views?
> - How do I attach a table or some other view to this area of the
> window?
>
> (Is it enough to place a generic NSView there and add a subview each
> time?
> I'm fairly new to Cocoa, so any pointers are welcome) -
On Jul 1, 2009, at 00:28, Thomas Davie wrote:> On 1 Jul 2009, at 09:21, Debajit Adhikary wrote:
>
>> (Is it enough to place a generic NSView there and add a subview
>> each time?
>> I'm fairly new to Cocoa, so any pointers are welcome)
>
> Yes -- at least that's what I do, if I'm doin it rong, hopefully
> someone will tell me :)
As others have said, using a tabless NSTabView is generally easier,
though if you need to actually release the view which isn't currently
in the window, this technique doesn't do that. (Typically you don't
need to release it.)
But if you are going to replace the subview "manually", the tricky
part is to make sure that its nib objects are released properly, which
means carefully studying the NSNib nib-loading and ownership document
to decide if there's anything you need to do.
In Leopard (and the iPhone, I guess), the easier way is to use a
NSViewController, because it handles nib object ownership issues for
you. The view controller loads the nib for you, though you still need
to swap the subviews manually.
The other advantage of NSViewController is that if your subviews each
need some controller logic, it modularizes your code if you can move
it to the NSViewController, instead of having to dump it all in the
window controller. -
On Jul 1, 2009, at 12:54 AM, Quincey Morris wrote:> On Jul 1, 2009, at 00:28, Thomas Davie wrote:
>
>> On 1 Jul 2009, at 09:21, Debajit Adhikary wrote:
>>
>>> (Is it enough to place a generic NSView there and add a subview
>>> each time?
>>> I'm fairly new to Cocoa, so any pointers are welcome)
>>
>> Yes -- at least that's what I do, if I'm doin it rong, hopefully
>> someone will tell me :)
>
> As others have said, using a tabless NSTabView is generally easier,
> though if you need to actually release the view which isn't
> currently in the window, this technique doesn't do that. (Typically
> you don't need to release it.)
I'm curious as to why people recommend a tabless NSTabView for this.
I've always found tabview subviews to be a pain to set up in IB; the
alignment and sizing seem really fiddly to get right. Maybe I've been
doing something wrong.> In Leopard (and the iPhone, I guess), the easier way is to use a
> NSViewController, because it handles nib object ownership issues for
> you. The view controller loads the nib for you, though you still
> need to swap the subviews manually.
>
> The other advantage of NSViewController is that if your subviews
> each need some controller logic, it modularizes your code if you can
> move it to the NSViewController, instead of having to dump it all in
> the window controller.
This is the way I'd recommend, although it's not that bad even without
NSViewController. Using multiple nibs instead of building one really
complicated nib has some distinct benefits for maintenance, in my
experience.
--
Adam -
On Jul 1, 2009, at 08:54, Adam R. Maxwell wrote:> I'm curious as to why people recommend a tabless NSTabView for
> this. I've always found tabview subviews to be a pain to set up in
> IB; the alignment and sizing seem really fiddly to get right. Maybe
> I've been doing something wrong.
I agree with you about the IB side of setting it up, although it
*really* depends on the particular situation.> Using multiple nibs instead of building one really complicated nib
> has some distinct benefits for maintenance, in my experience.
But drawbacks, too:
-- When you add a subview, you have to write code to resize it to fit
the window real estate it's supposed to occupy. That's not hard, but
it's a line or two of glue code you don't have to write with tab views.
-- You can't hook up IBOutlets directly from the window controller to
the view controller's objects in IB. Sometimes you can eliminate the
need for the outlet or move it to the view controller. If not, it's
not terribly hard to code around, but that's a few more lines of glue
code.
-- If you modularize your controllers, then bindings from the view
controller's objects get a bit harder. Either you have to defeat the
modularization by binding to File's Owner.windowController.whatever
(File's Owner being the view controller subclass, of course, and
windowController being a property you added to it), or you have to
"proxy" the bound properties in the view controller, which means more
glue code to forward the relevant accessors *and* KVO notifications.
Regardless of that, I prefer the modular view controller approach,
along with the modular IB design approach, but I think the tab view
approach is "generally easier" in a monolithic sort of way in many
cases.
Lastly, view controllers are Leopard only, so tab views win in Tiger-
compatible apps. :) -
On 1 Jul 2009, at 18:26, Quincey Morris wrote:> Either you have to defeat the modularization by binding to File's
> Owner.windowController.whatever (File's Owner being the view
> controller subclass, of course, and windowController being a
> property you added to it)
This is how I do it, but I don't add a windowController property to
each of the the view controllers. I instead add a parentController
outlet typed as id; which allows the parent to be either a window
controller or another view controller.
Then add a -windowController getter in an NSViewController category
which walks the parentController chain and finds the top-level
controller which -isKindOfClass:[NSWindowController class]
This retains the modularity of the view controllers and still provides
simple access to the window controller's properties and document.
Keith -
On Jul 1, 2009, at 10:26 AM, Quincey Morris wrote:> On Jul 1, 2009, at 08:54, Adam R. Maxwell wrote:
>
>> I'm curious as to why people recommend a tabless NSTabView for
>> this. I've always found tabview subviews to be a pain to set up in
>> IB; the alignment and sizing seem really fiddly to get right.
>> Maybe I've been doing something wrong.
>
> I agree with you about the IB side of setting it up, although it
> *really* depends on the particular situation.
I've mostly tried with a tabview as a subview of a splitview, and I've
found that once it's set up, I don't dare move it.>> Using multiple nibs instead of building one really complicated nib
>> has some distinct benefits for maintenance, in my experience.
>
> But drawbacks, too:
>
> -- When you add a subview, you have to write code to resize it to
> fit the window real estate it's supposed to occupy. That's not hard,
> but it's a line or two of glue code you don't have to write with tab
> views.
>
> -- You can't hook up IBOutlets directly from the window controller
> to the view controller's objects in IB. Sometimes you can eliminate
> the need for the outlet or move it to the view controller. If not,
> it's not terribly hard to code around, but that's a few more lines
> of glue code.
Good point; not being able to connect outlets can be a hassle. I
typically end up making weak references from the view controller to a
document object or similar controller, and that can get messy.> -- If you modularize your controllers, then bindings from the view
> controller's objects get a bit harder. Either you have to defeat the
> modularization by binding to File's Owner.windowController.whatever
> (File's Owner being the view controller subclass, of course, and
> windowController being a property you added to it), or you have to
> "proxy" the bound properties in the view controller, which means
> more glue code to forward the relevant accessors *and* KVO
> notifications.
Well, I generally avoid bindings, since I can't comment nib/xib files,
and it takes too long to reverse engineer my own (or worse, someone
else's) bindings when I'm doing maintenance work. With that
perspective, the minor glue code to swap views is no big deal :).> Lastly, view controllers are Leopard only, so tab views win in Tiger-
> compatible apps. :)
I've used NSWindowControllers and custom objects for this for years,
so that's also no big deal :). If the OP has a fixed set of views,
tabview could well be the easiest way to go, depending on the
complexity of the overall view hierarchy.
regards,
Adam -
On Jul 1, 2009, at 6:50 PM, Adam R. Maxwell wrote:> Well, I generally avoid bindings, since I can't comment nib/xib
> files, and it takes too long to reverse engineer my own (or worse,
> someone else's) bindings when I'm doing maintenance work. With that
> perspective, the minor glue code to swap views is no big deal :).
Warning: subject creep.
That leads directly to something I've been thinking about as one new
to cocoa:
how do you document your bindings? Any preferred formats other than
a text
file stuck somewhere in a project?
/\/\arc -
On Jul 1, 2009, at 8:18 PM, Marco S Hyman wrote:> On Jul 1, 2009, at 6:50 PM, Adam R. Maxwell wrote:
>
>> Well, I generally avoid bindings, since I can't comment nib/xib
>> files, and it takes too long to reverse engineer my own (or worse,
>> someone else's) bindings when I'm doing maintenance work. With
>> that perspective, the minor glue code to swap views is no big
>> deal :).
>
> Warning: subject creep.
>
> That leads directly to something I've been thinking about as one new
> to cocoa:
> how do you document your bindings? Any preferred formats other
> than a text
> file stuck somewhere in a project?
If you are new to Cocoa, I strongly recommend that you avoid bindings
until you're comfortable with datasource/delegate/target-action and
outlets. Having said that, a separate file is the only way I know of
to document a nib, and in the open-source projects that I've worked
on, refactoring and debugging are more painful with bindings.
I think bindings are really helpful in automatic change propagation
and validation. However, they are also tricky to debug; if you
naively try binding a toolbar button's enabled state to
[[NSOperationQueue operations] count], for instance, you'll get random
crashes. KVO-compliant code such as indexed accessors can be
generated for bindings, but that's as tedious as a tableview
datasource, IMO. Likewise, keypaths and array/set operators can be
really powerful, but the compiler won't catch mistakes in spelling of -
mutableArrayValueForKeyPath:@"someKyePath". If you're not as error-
prone as I am, this may not be an issue :).
--
Adam -
On Wed, Jul 1, 2009 at 11:18 PM, Marco S Hyman<marc...> wrote:> On Jul 1, 2009, at 6:50 PM, Adam R. Maxwell wrote:
>
>> Well, I generally avoid bindings, since I can't comment nib/xib files, and
>> it takes too long to reverse engineer my own (or worse, someone else's)
>> bindings when I'm doing maintenance work. ÃÂ With that perspective, the minor
>> glue code to swap views is no big deal :).
>
> Warning: subject creep.
>
> That leads directly to something I've been thinking about as one new to
> cocoa:
> how do you document your bindings? ÃÂ Any preferred formats other than a text
> file stuck somewhere in a project?
If you're going to stick your bindings in a text file, why not stick
them in a text file which happens to end in .m, and document them in a
format that the compiler can understand? In other words, why not just
make your bindings in code? Then you can easily see them, you can
comment them to your heart's content, you can search for them, and all
the other benefits of having stuff not be in your nib.
Mike -
On Thursday, July 02, 2009, at 11:39AM, "Michael Ash" <michael.ash...> wrote:> On Wed, Jul 1, 2009 at 11:18 PM, Marco S Hyman<marc...> wrote:[...]>> That leads directly to something I've been thinking about as one new to
>> cocoa:
>> how do you document your bindings? Â Any preferred formats other than a text
>> file stuck somewhere in a project?
>
> If you're going to stick your bindings in a text file, why not stick
> them in a text file which happens to end in .m, and document them in a
> format that the compiler can understand? In other words, why not just
> make your bindings in code? Then you can easily see them, you can
> comment them to your heart's content, you can search for them, and all
> the other benefits of having stuff not be in your nib.
My first reaction was: "Elegantly put!" But then I thought, isn't *not* generating this kind of code one of the reasons we tell people nibs are good? Wouldn't a .m be a good place to "document" targets and actions as well? And delegates and other outlets? Or do you think there's something about bindings that makes them subtle enough that for *them*, in some cases, it might make sense to "document" them by coding them?
--Andy -
On Thu, Jul 2, 2009 at 2:25 PM, Andy Lee<aglee...> wrote:> My first reaction was: "Elegantly put!" Â But then I thought, isn't *not* generating this kind of code one of the reasons we tell people nibs are good? Â Wouldn't a .m be a good place to "document" targets and actions as well? Â And delegates and other outlets? Â Or do you think there's something about bindings that makes them subtle enough that for *them*, in some cases, it might make sense to "document" them by coding them?
If you've decided that it will be better for the long-term health of
your application to document your bindings, it really isn't that hard
to do it in code rather than a text file. I mean how is this:
nameTextField.value -> [Array Controller].arrangedObjects.name
|- Value Transformer: CapitalizeTransformer
|- Null Placeholder: <null>
|- Multiple values placeholder: <multiple selection>
all that different from this:
- (void)awakeFromNib {
[nameTextField bind:@"value" toObject:arrayController
withKeyPath:@"arrangedObjects.name" options:
[NSDictionary dictionaryWithObjectsAndKeys:
@"CapitalizeTransformer", NSValueTransformerNameBindingOption,
@"<null>", NSNullPlaceholderBindingOption,
@"<multiple selection>", NSMultipleValuesPlaceholderBindingOption, nil]];
}
The important point is that your binding setup needs to get
complicated enough to warrant documentation in the first place -- from
there the extra effort required to get your documentation to compile
is trivial compared to the effort of documentation in the first place.
Target-action setups rarely get this complicated; most of the time
you just wire up your controls to First Responder.
--Kyle Sluder -
On Thu, Jul 2, 2009 at 5:25 PM, Andy Lee<aglee...> wrote:> On Thursday, July 02, 2009, at 11:39AM, "Michael Ash" <michael.ash...> wrote:
>> On Wed, Jul 1, 2009 at 11:18 PM, Marco S Hyman<marc...> wrote:
> [...]
>>> That leads directly to something I've been thinking about as one new to
>>> cocoa:
>>> how do you document your bindings? ÃÂ Any preferred formats other than a text
>>> file stuck somewhere in a project?
>>
>> If you're going to stick your bindings in a text file, why not stick
>> them in a text file which happens to end in .m, and document them in a
>> format that the compiler can understand? In other words, why not just
>> make your bindings in code? Then you can easily see them, you can
>> comment them to your heart's content, you can search for them, and all
>> the other benefits of having stuff not be in your nib.
>
> My first reaction was: "Elegantly put!" ÃÂ But then I thought, isn't *not* generating this kind of code one of the reasons we tell people nibs are good? ÃÂ Wouldn't a .m be a good place to "document" targets and actions as well? ÃÂ And delegates and other outlets? ÃÂ Or do you think there's something about bindings that makes them subtle enough that for *them*, in some cases, it might make sense to "document" them by coding them?
Sure, that would be a fine place to document them. And yes, I don't
think anybody ever does. Why not? Well, I don't think they document
them *anywhere else* either. Target/actions and outlets and such are
simple enough that people don't seem to feel the need to document them
at all.
If for some reason you *did* feel the need to document those, setting
them up in code would be a fine way to go.
Mike -
On Jul 2, 2009, at 4:25 PM, Andy Lee wrote:> On Thursday, July 02, 2009, at 11:39AM, "Michael Ash" <michael.ash...>
>> wrote:
>> On Wed, Jul 1, 2009 at 11:18 PM, Marco S Hyman<marc...> wrote:
> [...]
>>> That leads directly to something I've been thinking about as one
>>> new to
>>> cocoa:
>>> how do you document your bindings? Any preferred formats other
>>> than a text
>>> file stuck somewhere in a project?
>>
>> If you're going to stick your bindings in a text file, why not stick
>> them in a text file which happens to end in .m, and document them
>> in a
>> format that the compiler can understand? In other words, why not just
>> make your bindings in code? Then you can easily see them, you can
>> comment them to your heart's content, you can search for them, and
>> all
>> the other benefits of having stuff not be in your nib.
>
> My first reaction was: "Elegantly put!" But then I thought, isn't
> *not* generating this kind of code one of the reasons we tell people
> nibs are good? Wouldn't a .m be a good place to "document" targets
> and actions as well? And delegates and other outlets? Or do you
> think there's something about bindings that makes them subtle enough
> that for *them*, in some cases, it might make sense to "document"
> them by coding them?
>
> --Andy
This is why I tell people nibs are no good.
Also bindings. ;-)
-Jeff -
On Jul 1, 2009, at 8:18 PM, Marco S Hyman wrote:> On Jul 1, 2009, at 6:50 PM, Adam R. Maxwell wrote:
>
>> Well, I generally avoid bindings, since I can't comment nib/xib
>> files, and it takes too long to reverse engineer my own (or worse,
>> someone else's) bindings when I'm doing maintenance work. With
>> that perspective, the minor glue code to swap views is no big
>> deal :).
>
> Warning: subject creep.
>
> That leads directly to something I've been thinking about as one new
> to cocoa:
> how do you document your bindings? Any preferred formats other
> than a text
> file stuck somewhere in a project?
You can document bindings, as well as target-action and outlet
connections, by writing unit tests to specify them. You can even do
test-driven development of your xib files this way.
This can be as simple as writing tests that say âthe value of the
tableâs name column is bound to the Employees array controllerâs
âarrangedObjects.nameâ propertyâ and the creating the appropriate
bindings to make this test pass.
All of the information you need to test bindings can be easily found
using the -infoForBinding: method on any view or controller that
supports bindings. Iâve written some weblog posts on the topic:
Unit testing Cocoa user interfaces: Target-Action <http://eschatologist.net/blog/?p=10>
Unit testing Cocoa user interfaces: Cocoa Bindings <http://eschatologist.net/blog/?p=12>
These show how you might actually write some code to specify a
binding, or a target-action connection, in your application or
frameworkâs unit tests.
â Chris -
On Jul 3, 2009, at 00:25 AM, Jeff Johnson wrote:>
> This is why I tell people nibs are no good.
>
> Also bindings. ;-)
Bindings are definitely the worst-case scenario for nibs. They tend to
proliferate, and they are burrowed deep in the IB UI making them hard
to miss if you don't check every widget on every tab view, etc.
Where I work, we implement experiments as loadable bundles. Since the
experiments tend to be very similar but specific to a student's
particular line of research, we have a tool that clones an existing
experiment project into a new project folder. It modifies class, ivar,
and constant identifier prefixes, removing a lot of drudge work, but
can't get into the nibs to change the bindings to refer to the new
keys. So we have to go through the nibs, track down all the bindings,
and make sure they're updated with keys that use the new project's
prefix string rather than the old one.
Some kind of bindings editing tool would be very much appreciated.
Maybe a table listing a nib's keys that are bound in the first column,
with additional info in additional columns, such as the associated UI
objects.
That at least would let you sort alphabetically, which would catch
stragglers, and would let you more easily check for missing keys.


