On Aug 18, 2014, at 10:35 PM, Kyle Sluder <k...@ksluder.com> wrote:

> On Aug 18, 2014, at 7:27 PM, Daryle Walker <dary...@mac.com> wrote:
> 
>> On Aug 18, 2014, at 1:03 PM, Daryle Walker <dary...@mac.com> 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 (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to