[MacRuby-devel] Problem with a window controller
jdmuys at kleegroup.com
Mon Dec 10 01:27:32 PST 2012
On 7 déc. 2012, at 19:48:39, david kramf <dakr.012 at gmail.com>
> Message: 1
> Date: Fri, 7 Dec 2012 19:48:39 +0200
> From: david kramf <dakr.012 at gmail.com>
> To: "MacRuby development discussions."
> <macruby-devel at lists.macosforge.org>
> Subject: Re: [MacRuby-devel] Problem with a window controller
> Message-ID: <1F1681C7-9DE6-4971-8D17-722F5EC630CA at gmail.com>
> Content-Type: text/plain; charset="us-ascii"
> Hi Bob,
> "As you become more familiar with IB, you will probably do more initialization of objects in IB and less in MacRuby. Nib file expansion instantiates objects and then makes calls to initialize the objects using the same methods that you are using to initialize objects in MacRuby. Actually, in a large application, it would difficult to hook up all of the outlets without using IB."
> From my modest acquaintance with MacRuby that is not exactly the case since when the NIB instantiates an NSWindowController object , it does not call "initialize"
Cocoa, whether accessed from Ruby, Python, Objective-C or any language, uses the Cocoa initialization patterns. It's unrealistic to assume the framework patterns to change when you change the client language.
> ,as defined in Ruby , but calls "awakeFromNib".
It does, but caveat: awakeFromNib is *not* an initialization method, even though it is often used as such. I was bitten before. The correct initialization method to use for Nib files is initWithCoder:. What's the difference, says you (and me)? Behold: awakeFromNib can be called several times in the lifetime of an object. This is no big deals for most initializations, but becomes a major issue in others. In my case, I was registering for notifications in awakeFromNib. Since I was registered several times, I got the notifications multiple times, and since I only unsubscribed once in dealloc, my app would crash.
Many cases when awakeFromNib is called more than once are programming errors, but not all. And since there *is* a real initializer, I recommend using it.
So in that case why is there an awakeFromNib method at all? It is because at initWithCoder: time, IB outlets are not yet loaded and are all nil. So awakeFromNib is meant to for initialization code that configures outlet.
So here is a recipe:
1- Does you initialization code requires IB outlets to be alive? If not, override initWithCoder:
2- If so, put it in awakeFromNib
3- Does that awakeFromNib initialization code need to be called once only? if so, make it conditional on it having been already be called.
4- Optional: assert that awakeFromNib was not called before, and if that assert fires, investigate whether the case is legitimate or due to a bug in your code.
> Only when you instantiate your controller from the code itself , you get your "initialize"method called.
That is a bonus you just can be happy to have due to the deep integration of MacRuby in the Objective-C runtime system. There is no reason to assume that bonus to expand to objects created by the framework.
> I know I still have a lot of practicing on IB. What I find disturbing ,is that when I do something with IB I cannot see the code created to accommodate my actions ( maybe because I only work in MacRuby and not Objective-C?).
No. This is simply because there **no code created**. At all. IB does't generate code. And lest I forget: Interface Builder is not a code generation tool. IB instantiates and populates objects, and then serializes them to disk. Those objects are then simply deserialized from disk in your app. At no point ever is any code generated. Therefore, there is no "code created to accommodate your actions" for you to see. Even in Objective-C.
More information about the MacRuby-devel