Re: Still trying to refactor a category as a class
Re: Still trying to refactor a category as a class
- Subject: Re: Still trying to refactor a category as a class
- From: Ken Thomases <email@hidden>
- Date: Fri, 13 Jun 2008 20:19:44 -0500
On Jun 13, 2008, at 2:16 PM, Paul Archibald wrote:
The project I am working on is used to make and distribute copies
of certain files. I am trying to add a module that will do some
extra processing of the files, and then distributing copies of that
new, processed file. I was given the interface (a window with a
bunch of popups and stuff) for the new module in the NIB, and there
was originally a category (AppController(ExtraCategory)) for the
extra "module".
One typical case, and one that works well for a lot of folks, is
something like this:
An independent window is described in its own nib. That nib may
contain some NSController-derived objects for facilitating bindings.
In your code, you define a custom subclass of NSWindowController that
has the logic specific to that window. Let's call this class
MyWindowController. In the nib, you set the class of File's Owner to
be MyWindowController. You connect its "window" outlet (inherited
from NSWindowController) to refer to the main window of the nib;
likewise, you set the "delegate" outlet of the window to refer to
File's Owner.
If MyWindowController requires access to any of the other objects in
the nib, you declare outlets for them in the header and hook them up
in the nib.
In all likelihood, the window described by the nib will need to
present model data and/or allow the user to set model data. To
accomplish this, MyWindowController needs to be the go-between.
MyWindowController might receive a pointer(s) to the relevant parts
of the model as an argument to its init... method. Alternatively, if
the model is specific to the window, then MyWindowController could
actually instantiate the model on-demand or during initialization.
Either way, it needs to expose the relevant facets of the model
through properties in its interface. (Not necessarily Objective-C
2.0 properties, but in the more general sense of the term.)
If you're using bindings, the NSController-derived objects in the nib
will be bound to these model-revealing properties of File's Owner.
The views will in turn be bound to the NSController-derived objects.
If you're not using bindings, then MyWindowController will contain
glue code to respond to actions from the controls in the window by
updating the model, and (vice-versa) respond to model changes by
updating the contents of the views.
In your application controller, when it comes time to present this
specific window, there will be code to instantiate an instance of
MyWindowController. MyWindowController may be coded with knowledge
of which nib it uses, or that information may be passed in to the
initializer. Likewise, a reference to the model may be passed in.
Then, the app controller would invoke -showWindow: on the
MyWindowController instance.
I tried making a new controller for the new window/module, on the
theory that since they don't share much data or functionality, they
ought to be separate class objects. However, I am had some problems
with that approach. In particular, I was getting several runtime
errors of the type: "Could not connect the action
someNSApplicationAction: to target of class MyController". I don't
understand this at all, but I am more worried that I am just
completely off track in trying to create a new controller, and that
fixing this problem will just allow me to go even farther into the
weeds.
This sounds like the nib you received had controls which were
configured to deliver their action to the File's Owner target. When
you change the class of File's Owner, you change which actions it
responds to. These actions are/were part of AppController or its
category AppController(ExtraCategory), but are not part of your new
controller.
There are a number of possible solutions to this. Which you choose
depends on the nature of the actions and the design of your app.
You can move the actions from the AppController to
MyWindowController. (Or, in your case, copy them.) This requires
that MyWindowController has the necessary knowledge and scope of
influence to carry out the actions. It's possible for
MyWindowController to simply forward the actions to the AppController
instance (probably [NSApp delegate]), if necessary.
Another possibility is to take advantage of the Responder Chain's
processing of actions. In this case, you reconfigure the controls in
the nib to send their actions to First Responder. This causes the
action to proceed up the responder chain in search of an object which
can handle it. The window controller is in that chain, which is
useful if you add the action implementation to it, which is similar
to the previous approach. However, the application delegate is also
in that chain. It's quite likely that AppController is already the
application delegate, and so the action implicitly ends up where the
nib was original sending it explicitly.
In IB 3.x nibs, there is a proxy for the application object in window
nibs. Using this proxy as the target for an action is only useful if
you've subclassed NSApplication, which isn't too common. (Remember,
the application object and AppController are two different things.)
However, it is possible to access the application delegate, which is
often the application controller, through the delegate outlet of the
application object. You can't target an action there directly, but
it is possible to configure targets using bindings. So, it is
possible to use bindings to configure a control so that it targets
the application delegate, which is probably the same as
AppController. This is quite convoluted and I don't believe it's
common, but it is an option.
(And, a followup question would be: where could I find an example
of an app that has multiple controllers which do not relate to the
same document? The samples I have looked at so far seem to be based
on the MCV pattern. I am looking for something more like MCV(1)+MCV
(2).)
Well, for example, the code for TextEdit is installed with the
developer tools. It's at /Developer/Examples/AppKit/TextEdit. Its
Preferences.nib would be independent of DocumentWindow.nib, for example.
I hope that's helpful.
Cheers,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden