Re: NSPageLayout obsolete?
Re: NSPageLayout obsolete?
- Subject: Re: NSPageLayout obsolete?
- From: Daryle Walker <email@hidden>
- Date: Tue, 19 Aug 2014 03:32:15 -0400
On Aug 18, 2014, at 10:35 PM, Kyle Sluder <email@hidden> wrote:
> On Aug 18, 2014, at 7:27 PM, Daryle Walker <email@hidden> wrote:
>
>> On Aug 18, 2014, at 1:03 PM, Daryle Walker <email@hidden> wrote:
>>
>>> I then added the same action to the app delegate (using -runModelWithPrintInfo:). Worked fine when a window was open, but that still used the window controller version. But when I had no windows, the menu item was disabled, just like my first post! I thought that putting an action in the app delegate (without an explicit validation routine) always enables the corresponding menu item. That’s what happened when I added newDocment: and openDocument: actions after purging the NSDocument code. But that didn’t happen here. Did Apple add an override, or is it a bug? And how can I fix it?
>>
>> I tried the menu-level validation method in the app delegate. Didn’t work. Is NSApplication somehow blocking this action from going through? (The app delegate gets the actions for new-document and open-document.)
>>
>> Was going to try the general-level validation method, but I glanced at the web page I had open to the Printing Guide (i.e. I RTFM) and saw:
>>
>>> When running an app that is not document based, you must override the runPageLayout: method of the NSApplication class. You can also implement the method earlier in the responder chain. If you want to add an accessory view, your runPageLayout: method needs to call the addAccessoryController: method.
>
> My next question was going to determine whether this was the case. ;-)
I’ve dreamt of going into Cocoa programming for years (decades?), but didn’t start until a month ago. I’ve read that Cocoa & Objective-C have a lot of power. I think the problem is there’s so much power it’s hard to initially learn and/or keep track. (I wish there was something that would handle X…. There is, but it’s so obscure most people don’t recall it.)
>> (BTW, since the app delegate usually doesn’t subclass NSResponder, how/why is it part of the responder chain?)
>
> Legacy and convenience. It’s like that on iOS too.
>
>> I gave in and made an NSApplication subclass. I added a public override of -runPageLayout: and changed the initial class in the MyApp-Info.plist file. Didn’t work. Changed the class of the Application object of my two XIB files to my new class. Didn’t work. Thinking of overriding -sharedInfo in case the default implementation didn’t pay attention to what I listed as the initial class. Then I tried one last thing: making a general-level validation method (since NSApplication implements that protocol). Got it to work!
>
> Yeah, you have to remember to do both.
>
> Kinda sucks that you have to jump through this hoop, but the subclassing requirement is an artifact of a different era, and obviously works well enough (for the few non-document based apps that use it) that it’s not worth changing.
>
>> Then I poked around. I replaced -runModalWithPrintInfo with -runModal after first mistakenly doing NSPrintPanel methods. Then I changed the call to [super runPageLayout:sender] and it worked. NSApplication can do it, but it doesn’t want to. So I took out my override. Everything still works as long as I keep the general-level validation method around.
>>
>> New Questions:
>> 1. Is it safe to depend on the NSApplication version of -runPageLayout: (i.e., only override -validateUserInterfaceItem:)?
>
> I’d say no. Since you have to subclass to implement the validator, providing the correct implementation of the actual action is trivial.
I looked for -runPageLayout: in NSApplication.h, and I couldn’t find it. That’s why I thought this action may be obsolete and unsupported.
However…
There are a lot of methods in the HTML docs for NSApplication. I thought the provided -runPageLayout: was a myth, but it’s actually there! I didn’t see it until the fifth re-read. So this base-class version is official. But why didn’t I see it in the header? (And that time I did use Command-F to help.) In the HTML docs, I usually skip over a method’s listed header, since it’s usually obvious. But looking at it this times shows that the method is in a different header! Sure enough, the method is in that header.
Some of the WebView delegates are informal protocols implemented as methods of a category on NSObject. Apple extended this to other classes; -runPageLayout: for NSApplication is imported from a category in NSPageLayout.h. Once again, Apple has a well-thought-out system everyone else thinks is too complicated. I was thinking I going to program this over the summer while biding my time for Yosemite & Swift; now I think I’m going to stick with Objective-C, at least until Swift bakes enough for prime-time.
>> Otherwise, I would need to override only if I ever added an accessory view.
>> 2. Does said message manipulate the shared NSPrintInfo object?
>
> Probably, but there’s no guarantee.
Actually, there is. The docs for the method in its actual header says it calls [[NSPageLayout pageLayout] runModal].
So, to have an app-global Page Setup command:
1. Either insert an app-global responder, ahead of the application object, to handle the action. I guess the NSDocument system does this.
2. Or replace NSApplication with a subclass that implements:
2a. -validateUserInterfaceItem:, which must test for the -runPageLayout: action and allow it. (Pass other actions to super.)
2b. If you’re using the official shared NSPrintInfo as your app-global setting storage, and you’re not going to use an accessory panel during Page Setup, you’re already done. Otherwise, create and attach any accessory view you have (if applicable) and call the panel with the default or your settings object. (Don’t call super.)
3. Note that you cannot use the application delegate to store the method. The hacks used to consider the delegate a responder don’t include that method and/or the application object goes first and locks out the delegate from providing an override.
>> 3. Would reverting the XIB files’ application proxy back to NSApplication (but keeping my subclass as the app’s initial class) mess anything up?
>
> No, but that sounds like inconvenience for no reason.
I want to revert to minimize the diffs for git. However, since I actually did change the application class, reversion would be incorrect.
—
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com
_______________________________________________
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