Skip navigation.
 
mlRe: NSProgressIndicator and some very basic stuff ...
FROM : Mike Abdullah
DATE : Mon May 19 23:27:00 2008

On 19 May 2008, at 20:58, John Love wrote:

> I am having some basic problems getting an indeterminate 
> NSProgressIndicator
> (INSPI) to spin.  Since I have just recently started to learn XCODE 
> and
> Cocoa, I began with "Learning Cocoa and Objective C".  I have also 
> printed
> out much of Apple's docs, e.g., on the INSPI.  I just finished 
> developing an
> app in AppleScript Studio, so I am very familiar with XCODE and IB. 
> Plus, a
> long time ago, I delved into C++ ... so that helps ... and I have 
> poured
> over the concepts of outlets and actions and how to connect 
> everything in IB
> ... but something is just not working right.  So, I decided to go 
> from the
> beginning and describe everything to you so you can tell me where "I 
> parked
> my brain".
>
> I have developed a multi-document Cocoa app whose nib contains the 
> usual
> stuff plus a Window and an NSObject, 
> "CalculationIndicatorController" (CIC),
> whose class has the same name.  The Window has an INSPI, whose class 
> is
> CIC.


This all be a bit crazy. There's almost certainly NO need for you to 
subclass NSProgressIndicator ever, especially in this case.

> Within IB, the CIC has one outlet = "itsWindow" and one action =
> "spin:".  In general, I must be doing something right, because in each
> window, via CMD-N, I have a Toolbar showing ... the INSPI is just 
> giving me
> fits for now.
>
> // CIC.h looks like:
>
> #import <Cocoa/Cocoa.h>
>
> @interface CIC:NSProgressIndicator {
>    IBOutlet NSWindow *itsWindow;
> }
>
> - (IBAction) spin:(NSWindow *)sender on:(BOOL)start;
> @end
>
> =====
>
> // CIC.m looks like:
>
> #import "CIC.h"
>
> @implementation CIC
>
> - (id) init {
>    if (self = [super init]) {
>        [self setUsesThreadedAnimation:YES];
>    }
>
>    return self;
> }
>
>
> - (void) awakeFromNib {
>    itsWindow = [self window];
>    [self spin:itsWindow on:TRUE];
> }
>
>
> - (IBAction) spin:(NSWindow *)sender on:(BOOL)start; {
>    if (start)  [self startAnimation:sender];
>    else        [self stopAnimation:sender];
> }
>
>
> Now ... back to IB:
>
> 1) When I control-drag from the INSPI (the "lock washer") in the 
> window to
> the window's title bar, I select outlet = "itsWindow" .. so far, so 
> good ..
> but when I control-drag from the CIC in the nib window to the 
> window's title
> bar, I see TWO outlets = "itsWindow" .. so confusion #1 ??
>
> 2) Now, there is clearly an Action labelled "IBAction" in the source 
> code
> and there is an Action in the Class Actions pane of IB when I have 
> selected
> the CIC in the nib window.  As an aside, the Outlet appeared 
> automatically
> once I placed the IBOutlet in the source code .. however, even 
> though the
> IBAction was also in the source code, I had to manually add the 
> Action =
> "spin:" within IB .. so confusion #2 ??


You've used (IBAction) but the actual method itself is not a valid 
action message. Actions MUST take the form:

- (IBAction)doSomething:(id)sender

where sender is an object of some kind. You can even do this if you 
really wanted to but it's slightly pointless:

- (IBAction)doSomething:(MyClass *)sender

Either way it doesn't matter, because you don't need to be doing all 
this subclassing.
>
>
> 3) So, just like I did in Apple's Currency Converter Project (whose 
> source
> for the control-drag was a Button), I control-drag from the window's 
> title
> bar to the INSPI (the "lock washer") in this window - based on the
> assumption that the sender is the NSWindow (???).  I expected to be 
> greeted
> with having to select the Action = "spin:" .. but all I saw was the 
> choice
> of outlets = "delegate" and "initialFirstResponder".  The same thing
> occurred when I control-drag from the window's title bar to the CIC 
> in the
> nib window.  Just for the record, I did select 
> "initialFirstResponder" ..
> but where is the Action selection = "spin:" .. confusion #3 ??
>
> My MainDocument.m file has a *- (void)
> windowControllerDidLoadNib:(NSWindowController*)aController* method 
> which
> sets up everything once the Window is showing.


Right, what you actually want to do is create an outlet in 
MainDocument.h along the lines of:

IBOutlet NSProgressIndicator *progressIndicator;

Then if your -windowControllerDidLoadNib: method, you can do something 
like:

[progressIndicator setUsesThreadedAnimation:YES];
[progressIndicator startAnimation:self];

>
>
> But, *somewhere?,* I read that in the process of getting that Window 
> to
> show, the - (void) awakeFromNib method of each and every NSView 
> contained
> within the Window
> is called.  Therefore, I called *[self spin:itsWindow on:TRUE];* 
> within the
> CIC's *awakeFromNib*.
>
> I expected to see a rotating INSPI, or "lock washer" ... but not 
> this trip.
>
> Let me finish by asking one question: "Just where did I park my 
> brain?"


Trying to manage the animation entirely from within your progress 
indicator subclass (the view layer) is poor design as the progress 
indicator itself is ill-equipped to know whether it should be 
animating. Instead, the whole point of the MVC paradigm (which Cocoa 
relies heavily upon) is to have a controller object (in this case 
MainDocument) tell it to start animating.

I also came originally from AppleScript studio and I have to admit it 
actually makes life harder as the two approaches are very different. 
Good luck!

Mike.

Related mailsAuthorDate
mlNSProgressIndicator and some very basic stuff ... John Love May 19, 21:58
mlRe: NSProgressIndicator and some very basic stuff ... Mike Abdullah May 19, 23:27