 |
|
 |
|
Next: newbie question: app only works from terminal
|
| Author |
Message |
External

Since: Dec 16, 2003 Posts: 327
|
(Msg. 1) Posted: Thu Jan 10, 2008 6:35 pm
Post subject: Objective C, Cocoa, Interface Builder, and NSPopUpButtons Archived from groups: comp>sys>mac>programmer>help (more info?)
|
|
|
Over Xmas, I started delving into the mysteries of Objective C and
Cocoa. For the record, I'm still (and will continue to be until finances
improve) running 10.3.9, with the newest-that-will-run-on-it (XCode 1.5)
developer tools.
It's been basically fairly pleasant, so far - I'm finding that Obj-C
actually "makes sense", even though I've been left wondering "what
happened?!?!?" in every previous encounter I've had with OOP languages
like C++.
I've had success with subclassing/extending various Cocoa classes, and
gotten some pretty good results, but I've hit a seemingly insurmountable
obstacle when trying to "talk to" IB-created UIs.
I've been beating on a variation on the Obj-C tutorial's "Currency
Converter" program. I'm wanting to turn it "universal" and "realtime",
in that it will go out to a web site, retrieve current conversion rates,
parse the returned data to extract currency names and exchange rates,
then use those to do the conversion. The "go get the data" and "parse
it" portions are working exactly as they should be - I end up with,
exactly as planned, an NSMutableArray stuffed full of custom
"CurrencyValueItem" objects (with associated get/set/play with/etc
methods) that hold the names and "units of this currency per dollar" and
"dollars per unit of this currency" values for a variable number of
currencies. In the debugger, manually setting up variables then letting
things fall through into calling the convert method is doing fine.
Displaying the result likewise works great.
Where I'm hitting trouble is letting the user select what currency to
convert from/to, and based on the user's selections, doing the correct
conversion.
The way I've got things laid out in Interface Builder, I have an
NSTextfield for input of the "number of currency units". Following that,
I have what seems the most sensible method of selecting the "source
currency" - an NSPopUpButton, then another NSPopUpButton to select the
"target currency", and finally, another NSTextfield to accept the
converted value from the converter controller function. And, of course,
there's a "Make it happen" button to kick the whole thing into action
once the user has plugged in the value to convert and selected what the
conversion should be.
This is where I hit my "real trouble" -
How do I set up and use the menus???
More specifically, I can't figure out how to tell what menu I'm working
with. Putting them together in Interface Builder is easy enough, but
trying to make two separate instances of NSPopUpButton objects so that
they're independently "tinker-with-able" within the program code eludes
me.
I'm not having trouble populating the menus, or retrieving the index of
the user-selected item - that's quite simple. What's difficult is
figuring out which menu I'm talking to.
I *COULD*, I guess, build the currency info into the nib file, but that
would rather defeat the purpose of a "live" read of the data from the
website.
The documentation for NSPopUpButton is adequate, as far as it goes, but
nothing I've spotted addresses the interplay between the NSPopUpButton
class and the IB-created button that it should be talking to/using in a
way that lets me accomplish what I'm trying to do.
Suggestions?
--
Don Bruder - dakidd.TakeThisOut@sonic.net - If your "From:" address isn't on my whitelist,
or the subject of the message doesn't contain the exact text "PopperAndShadow"
somewhere, any message sent to this address will go in the garbage without my
ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Jun 25, 2003 Posts: 451
|
(Msg. 2) Posted: Fri Jan 11, 2008 5:01 am
Post subject: Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
On Thu, 10 Jan 2008 18:35:27 -0800, Don Bruder wrote:
> Over Xmas, I started delving into the mysteries of Objective C and
> Cocoa. For the record, I'm still (and will continue to be until finances
> improve) running 10.3.9, with the newest-that-will-run-on-it (XCode 1.5)
> developer tools.
> It's been basically fairly pleasant, so far - I'm finding that Obj-C
> actually "makes sense", even though I've been left wondering "what
> happened?!?!?" in every previous encounter I've had with OOP languages
> like C++.
> I've had success with subclassing/extending various Cocoa classes, and
> gotten some pretty good results, but I've hit a seemingly insurmountable
> obstacle when trying to "talk to" IB-created UIs.
You can solve these problems by using outlets and actions, which can be
set up in Interface Builder.
> I've been beating on a variation on the Obj-C tutorial's "Currency
> Converter" program. I'm wanting to turn it "universal" and "realtime",
> in that it will go out to a web site, retrieve current conversion rates,
> parse the returned data to extract currency names and exchange rates,
> then use those to do the conversion. The "go get the data" and "parse
> it" portions are working exactly as they should be - I end up with,
> exactly as planned, an NSMutableArray stuffed full of custom
> "CurrencyValueItem" objects (with associated get/set/play with/etc
> methods) that hold the names and "units of this currency per dollar" and
> "dollars per unit of this currency" values for a variable number of
> currencies. In the debugger, manually setting up variables then letting
> things fall through into calling the convert method is doing fine.
> Displaying the result likewise works great.
> Where I'm hitting trouble is letting the user select what currency to
> convert from/to, and based on the user's selections, doing the correct
> conversion.
> The way I've got things laid out in Interface Builder, I have an
> NSTextfield for input of the "number of currency units". Following that,
> I have what seems the most sensible method of selecting the "source
> currency" - an NSPopUpButton, then another NSPopUpButton to select the
> "target currency", and finally, another NSTextfield to accept the
> converted value from the converter controller function. And, of course,
> there's a "Make it happen" button to kick the whole thing into action
> once the user has plugged in the value to convert and selected what the
> conversion should be.
> This is where I hit my "real trouble" -
> How do I set up and use the menus???
If you mean you want to do that programmatically, you should make each
NSPopUpButton an outlet of your controller class. Then you can send
appropriate messages to each one. For example, there are methods called
addItemWithTitle: and addItemsWithTitles:, plus methods for removing
items and so on.
You might choose to adopt a scheme like this:
// myController
#import <Cocoa/Cocoa.h>
@interface myController : NSObject {
IBOutlet NSTextField *numberOfCurrencyUnits;
IBOutlet NSPopUpButton *sourceCurrencyMenu;
IBOutlet NSPopUpButton *targetCurrencyMenu;
IBOutlet NSTextField *convertedValue;
// other instance variables here
}
// method declarations -- actions are discussed below:
- (IBAction)sourceCurrencyDidChange:(id)sender;
- (IBAction)targetCurrencyDidChange:(id)sender;
- (IBAction)doTheConversion:(id)sender;
// other methods, as needed
@end
Based on your description, you probably already have a controller object
instantiated in your nib file, you have at least the NSTextFields set up
as outlets and you should already have at least the skeleton of an action
method to be invoked by the pushbutton. All these things need to be
connected appropriately in Interface Builder.
You need to add the popups as additional outlets, so you can talk to them
and presumably populate them at runtime. If you haven't created the
source files from your controller yet, you can do this from Interface
Builder. If you already have generated source files, it may be easier to
edit them to include the IBOutlets and IBActions shown above, and then
drag the icon of the source file from your project window into the nib
file's window, to let Interface Builder know about the new outlets and
actions. Then make the necessary connections.
You can take a passive approach and just query each menu to see what the
current selection is when you need it. If you do that, you probably
won't use the menu actions sourceCurrencyDidChange: and
targetCurrencyDidChange: that I indicated. However, the point of these
action methods is that you can process a change in the state of a menu
immediately when it happens and then preserve that information for the
next time you need to process a conversion, instead of querying each menu
again for each transaction.
> More specifically, I can't figure out how to tell what menu I'm working
> with. Putting them together in Interface Builder is easy enough, but
> trying to make two separate instances of NSPopUpButton objects so that
> they're independently "tinker-with-able" within the program code eludes
> me.
It's no problem if each popup is an outlet, as shown above.
If you are using the action methods, you need to control-drag from each
menu back to the controller object (as the target) and select the desired
action in the inspector.
Your implementations might be something along the lines of
- (IBAction)sourceCurrencyDidChange:(id)sender {
NSString *newCurrency = [sender titleOfSelectedItem];
// do what needs to be done with the new currency
}
This is just an example. You may be more interested in getting the index
of the selected item instead of the title, by using indexOfSelectedItem.
> I'm not having trouble populating the menus, or retrieving the index of
> the user-selected item - that's quite simple. What's difficult is
> figuring out which menu I'm talking to.
When a control sends an action message to its designated target, it
always sends itself as an argument with the message. This means you know
who sent the message and you can go back to get more information about
the state of the sender by sending messages back to it.
> I *COULD*, I guess, build the currency info into the nib file, but that
> would rather defeat the purpose of a "live" read of the data from the
> website.
That's a separate problem, solved by making each popup an outlet.
> The documentation for NSPopUpButton is adequate, as far as it goes, but
> nothing I've spotted addresses the interplay between the NSPopUpButton
> class and the IB-created button that it should be talking to/using in a
> way that lets me accomplish what I'm trying to do.
> Suggestions?
Using outlets, you can populate the menus dynamically at runtime. That
doesn't stop you from setting up targets/actions in Interface Builder,
since those are probably static for this application.
--
Dave Seaman
Oral Arguments in Mumia Abu-Jamal Case heard May 17
U.S. Court of Appeals, Third Circuit
<http://www.abu-jamal-news.com/> >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Dec 16, 2003 Posts: 327
|
(Msg. 3) Posted: Fri Jan 11, 2008 5:01 am
Post subject: Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Dave Seaman wrote:
> On Thu, 10 Jan 2008 18:35:27 -0800, Don Bruder wrote:
<snip for space>
(First whack at some thoughts that you've given me, done at 2 in the AM
local time... I'll actually try some of them when daylight comes around
again...)
> > This is where I hit my "real trouble" -
>
> > How do I set up and use the menus???
>
> If you mean you want to do that programmatically,
Yep, that's exactly what I want to do. At each run, the first thing that
needs to happen is making a run to the website to harvest the currency
names and conversion values into my NSMutableArray of CurrencyItem
object (which in turn are subclassed from NSObject).
As mentioned, that "run for the data" operation is working exactly as
planned - I was absolutely shocked to get the guts of it right the very
first try. The "cosmetics" of data-manipulation that went into it needed
a couple of minor tweaks - as in "No, stupid, you don't get the currency
name by reading to this byte of the stream, you have to read until this
OTHER byte", and so on)
Once thats completed, I've got all the data I need to populate the
menus. Doing the actual populating is a simple matter - Iterate through
the NSMutableArray grabbing the currency name, and handing it off to the
NSPopUpButton to be added. (Which, incidentally, means that the menus
are in the same order as the array, which makes life easier - I think
the method is "getIndexOfSelectedItem", and presto - I've got the index
of the NSMutableArray item I need to retrieve to do the calculation)
> you should make each
> NSPopUpButton an outlet of your controller class.
Doesn't that run into the problem of "The menus need to be populated
before the controller gets a chance to run, therefore, the outlets need
to be part of some other class - But which one???"
Or am I making a rookie mistake? (I suspect I might be - after all, I
*AM* a rookie!)
> Then you can send
> appropriate messages to each one. For example, there are methods called
> addItemWithTitle: and addItemsWithTitles:, plus methods for removing
> items and so on.
Right - That part was pretty simple to figure out. Or would have been,
if it weren't for the "But where should I be sending the messages???"
concept... My first stab at it was in the form of class methods grafted
onto the NSPopUpButton class, but that failed miserably (Well, actually,
it worked, but left me with absolutely no clue which menu I had just
populated, and seemingly no way to find out - and no way to say
"[Menu"X" getIndexOfSelectedItem] so that I could retrieve the data to
do the conversion)
> You might choose to adopt a scheme like this:
>
> // myController
>
> #import <Cocoa/Cocoa.h>
>
> @interface myController : NSObject {
> IBOutlet NSTextField *numberOfCurrencyUnits;
> IBOutlet NSPopUpButton *sourceCurrencyMenu;
> IBOutlet NSPopUpButton *targetCurrencyMenu;
> IBOutlet NSTextField *convertedValue;
> // other instance variables here
> }
OK, that follows reasonably, but leaves me in a bit of a bind - Unless
I've missed (or misunderstood) something - all too possible since I'm so
completely green when it comes to doing things "The Objective C way" -
the myController object doesn't actually "do anything" until it gets an
action passed to it. Which means that until sometime after the first
pass through the controller (by whatever means that pass is caused to
happen...) my menus are both full of the default stuff that IB puts
there as placeholders.
I need to get a grip on the menus before the UI even becomes visible,
let alone has an action happen that makes the controller run, so I can
populate the menus. Or do I? Of COURSE I do... Don't I?
I looked at the awakeFromNib method, but that didn't get me anywhere
except frustrated. It looked *REALLY* promising at first, but as I dug
deeper, <pfffft> that idea went out the window. Or perhaps I need an
awakeFromNib method on/in the controller class itself? Something that
says "Oh, look! Here's an NSPopUpButton that needs to be populated! Call
somebody to do it!", perhaps?
>
> // method declarations -- actions are discussed below:
> - (IBAction)sourceCurrencyDidChange:(id)sender;
> - (IBAction)targetCurrencyDidChange:(id)sender;
> - (IBAction)doTheConversion:(id)sender;
> // other methods, as needed
>
> @end
>
> Based on your description, you probably already have a controller object
> instantiated in your nib file, you have at least the NSTextFields set up
> as outlets and you should already have at least the skeleton of an action
> method to be invoked by the pushbutton. All these things need to be
> connected appropriately in Interface Builder.
Right, that's covered. Took some twiddling based on the original
Currency Converter demo, but I figured out how to do the hookups for the
NSTextFields, and the action from the "do it" button so that things were
operational.
>
> You need to add the popups as additional outlets, so you can talk to them
> and presumably populate them at runtime.
Hmmm... But again, it (seems like it) runs into the problem of "can't
populate without knowing the object that needs to be populated, and
can't know that until the controller fires up".
> If you haven't created the
> source files from your controller yet, you can do this from Interface
> Builder. If you already have generated source files, it may be easier to
> edit them to include the IBOutlets and IBActions shown above, and then
> drag the icon of the source file from your project window into the nib
> file's window, to let Interface Builder know about the new outlets and
> actions.
<blink blink> Now THERE is something that hadn't dawned on me! I wasn't
aware that it was possible to take "code" and cram it into the nib
file/IB. This may be the key I've been missing...
> Then make the necessary connections.
As if my code were something that already exists in IB's "I know how to
do this" bag of tricks... Yeah, That definitely puts me on a new way of
thinking...
> You can take a passive approach and just query each menu to see what the
> current selection is when you need it. If you do that, you probably
> won't use the menu actions sourceCurrencyDidChange: and
> targetCurrencyDidChange: that I indicated. However, the point of these
> action methods is that you can process a change in the state of a menu
> immediately when it happens and then preserve that information for the
> next time you need to process a conversion, instead of querying each menu
> again for each transaction.
The passive approach you describe is, or so it seems to me, the only
viable way to do anything with this particular "mess" of mine.
>
> > More specifically, I can't figure out how to tell what menu I'm working
> > with. Putting them together in Interface Builder is easy enough, but
> > trying to make two separate instances of NSPopUpButton objects so that
> > they're independently "tinker-with-able" within the program code eludes
> > me.
>
> It's no problem if each popup is an outlet, as shown above.
>
> If you are using the action methods, you need to control-drag from each
> menu back to the controller object (as the target) and select the desired
> action in the inspector.
>
> Your implementations might be something along the lines of
>
> - (IBAction)sourceCurrencyDidChange:(id)sender {
> NSString *newCurrency = [sender titleOfSelectedItem];
> // do what needs to be done with the new currency
> }
>
> This is just an example. You may be more interested in getting the index
> of the selected item instead of the title, by using indexOfSelectedItem.
>
> > I'm not having trouble populating the menus, or retrieving the index of
> > the user-selected item - that's quite simple. What's difficult is
> > figuring out which menu I'm talking to.
>
> When a control sends an action message to its designated target, it
> always sends itself as an argument with the message. This means you know
> who sent the message and you can go back to get more information about
> the state of the sender by sending messages back to it.
>
> > I *COULD*, I guess, build the currency info into the nib file, but that
> > would rather defeat the purpose of a "live" read of the data from the
> > website.
>
> That's a separate problem, solved by making each popup an outlet.
>
> > The documentation for NSPopUpButton is adequate, as far as it goes, but
> > nothing I've spotted addresses the interplay between the NSPopUpButton
> > class and the IB-created button that it should be talking to/using in a
> > way that lets me accomplish what I'm trying to do.
>
> > Suggestions?
>
> Using outlets, you can populate the menus dynamically at runtime. That
> doesn't stop you from setting up targets/actions in Interface Builder,
> since those are probably static for this application.
--
Don Bruder - dakidd.RemoveThis@sonic.net - If your "From:" address isn't on my whitelist,
or the subject of the message doesn't contain the exact text "PopperAndShadow"
somewhere, any message sent to this address will go in the garbage without my
ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Oct 03, 2004 Posts: 2243
|
(Msg. 4) Posted: Fri Jan 11, 2008 8:43 am
Post subject: Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Don Bruder wrote:
> In article ,
> Dave Seaman wrote:
>
> > On Thu, 10 Jan 2008 18:35:27 -0800, Don Bruder wrote:
>
> <snip for space>
>
> (First whack at some thoughts that you've given me, done at 2 in the AM
> local time... I'll actually try some of them when daylight comes around
> again...)
>
> > > This is where I hit my "real trouble" -
> >
> > > How do I set up and use the menus???
> >
> > If you mean you want to do that programmatically,
>
> Yep, that's exactly what I want to do. At each run, the first thing that
> needs to happen is making a run to the website to harvest the currency
> names and conversion values into my NSMutableArray of CurrencyItem
> object (which in turn are subclassed from NSObject).
>
> As mentioned, that "run for the data" operation is working exactly as
> planned - I was absolutely shocked to get the guts of it right the very
> first try. The "cosmetics" of data-manipulation that went into it needed
> a couple of minor tweaks - as in "No, stupid, you don't get the currency
> name by reading to this byte of the stream, you have to read until this
> OTHER byte", and so on)
>
> Once thats completed, I've got all the data I need to populate the
> menus. Doing the actual populating is a simple matter - Iterate through
> the NSMutableArray grabbing the currency name, and handing it off to the
> NSPopUpButton to be added. (Which, incidentally, means that the menus
> are in the same order as the array, which makes life easier - I think
> the method is "getIndexOfSelectedItem", and presto - I've got the index
> of the NSMutableArray item I need to retrieve to do the calculation)
>
> > you should make each
> > NSPopUpButton an outlet of your controller class.
>
> Doesn't that run into the problem of "The menus need to be populated
> before the controller gets a chance to run, therefore, the outlets need
> to be part of some other class - But which one???"
>
> Or am I making a rookie mistake? (I suspect I might be - after all, I
> *AM* a rookie!)
Rookie mistake. Your controller can do things besides gather the input
data and calculate the result. There are several methods that you can
define that will be invoked at well-defined times before the user has
any chance to interact with your UI. How/when are you grabbing the units
and conversion rates? You should be able to populate the menus (since
they'll be static for any given run, right?) right then - as long as
you've defined the outlets in IB and in your source file such that your
controller has a reference to the controls.
> I looked at the awakeFromNib method, but that didn't get me anywhere
> except frustrated. It looked *REALLY* promising at first, but as I dug
> deeper, <pfffft> that idea went out the window. Or perhaps I need an
> awakeFromNib method on/in the controller class itself? Something that
> says "Oh, look! Here's an NSPopUpButton that needs to be populated! Call
> somebody to do it!", perhaps?
Ding!
> > If you haven't created the
> > source files from your controller yet, you can do this from Interface
> > Builder. If you already have generated source files, it may be easier to
> > edit them to include the IBOutlets and IBActions shown above, and then
> > drag the icon of the source file from your project window into the nib
> > file's window, to let Interface Builder know about the new outlets and
> > actions.
>
> <blink blink> Now THERE is something that hadn't dawned on me! I wasn't
> aware that it was possible to take "code" and cram it into the nib
> file/IB. This may be the key I've been missing...
It's documented, but not obvious. As a complement to IB's ability to
generate stub source files, it can also *read* header files and
create/update class definitions based on what's in them. You just make
sure you've got the instance variables you care about tagged as
IBOutlet, and make sure actions have a return to of (IBAction) and take
a single argument typed as 'id'.
You can also do it manually, of course. You just have to take care to
make sure you type the same name into IB that you did in the header file.
This goes away in XCode 3...IB is more tightly integrated with XCode and
reads the header files on the fly without effort on your part.
G >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Jun 25, 2003 Posts: 451
|
(Msg. 5) Posted: Fri Jan 11, 2008 2:01 pm
Post subject: Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
On Fri, 11 Jan 2008 02:02:45 -0800, Don Bruder wrote:
> In article ,
> Dave Seaman wrote:
>> On Thu, 10 Jan 2008 18:35:27 -0800, Don Bruder wrote:
><snip for space>
> (First whack at some thoughts that you've given me, done at 2 in the AM
> local time... I'll actually try some of them when daylight comes around
> again...)
>> > This is where I hit my "real trouble" -
>> > How do I set up and use the menus???
>> If you mean you want to do that programmatically,
[snip comments]
>> you should make each
>> NSPopUpButton an outlet of your controller class.
> Doesn't that run into the problem of "The menus need to be populated
> before the controller gets a chance to run, therefore, the outlets need
> to be part of some other class - But which one???"
> Or am I making a rookie mistake? (I suspect I might be - after all, I
> *AM* a rookie!)
There's no problem. You would populate the menus in your controller's
awakeFromNib method.
>> Then you can send
>> appropriate messages to each one. For example, there are methods called
>> addItemWithTitle: and addItemsWithTitles:, plus methods for removing
>> items and so on.
> Right - That part was pretty simple to figure out. Or would have been,
> if it weren't for the "But where should I be sending the messages???"
To the outlet in your controller class, that you connected to the popup
in IB.
> concept... My first stab at it was in the form of class methods grafted
> onto the NSPopUpButton class, but that failed miserably (Well, actually,
> it worked, but left me with absolutely no clue which menu I had just
> populated, and seemingly no way to find out - and no way to say
> "[Menu"X" getIndexOfSelectedItem] so that I could retrieve the data to
> do the conversion)
>> You might choose to adopt a scheme like this:
>> // myController
>> #import <Cocoa/Cocoa.h>
>> @interface myController : NSObject {
>> IBOutlet NSTextField *numberOfCurrencyUnits;
>> IBOutlet NSPopUpButton *sourceCurrencyMenu;
>> IBOutlet NSPopUpButton *targetCurrencyMenu;
>> IBOutlet NSTextField *convertedValue;
>> // other instance variables here
>> }
> OK, that follows reasonably, but leaves me in a bit of a bind - Unless
> I've missed (or misunderstood) something - all too possible since I'm so
> completely green when it comes to doing things "The Objective C way" -
> the myController object doesn't actually "do anything" until it gets an
> action passed to it.
After the objects in your nib file have been unarchived and all the
outlets and actions connected as specified by IB, each object receives
the awakeFromNib message. You should implement that method in your
controller class and use it to populate your popup menus. You can't do
that in the controller's init method, because the IB connections haven't
been set up yet when init runs. That's why we have the awakeFromNib
method.
> Which means that until sometime after the first
> pass through the controller (by whatever means that pass is caused to
> happen...) my menus are both full of the default stuff that IB puts
> there as placeholders.
Your controller doesn't run all at once. It has a bunch of methods, each
of which runs when the corresponding message is received. Your
awakeFromNib method runs before any of your action methods, and it can
remove whatever IB put in the menu before adding new items.
> I need to get a grip on the menus before the UI even becomes visible,
> let alone has an action happen that makes the controller run, so I can
> populate the menus. Or do I? Of COURSE I do... Don't I?
> I looked at the awakeFromNib method, but that didn't get me anywhere
> except frustrated. It looked *REALLY* promising at first, but as I dug
> deeper, <pfffft> that idea went out the window. Or perhaps I need an
> awakeFromNib method on/in the controller class itself?
Bingo.
>> If you haven't created the
>> source files from your controller yet, you can do this from Interface
>> Builder. If you already have generated source files, it may be easier to
>> edit them to include the IBOutlets and IBActions shown above, and then
>> drag the icon of the source file from your project window into the nib
>> file's window, to let Interface Builder know about the new outlets and
>> actions.
><blink blink> Now THERE is something that hadn't dawned on me! I wasn't
> aware that it was possible to take "code" and cram it into the nib
> file/IB. This may be the key I've been missing...
>> Then make the necessary connections.
> As if my code were something that already exists in IB's "I know how to
> do this" bag of tricks... Yeah, That definitely puts me on a new way of
> thinking...
In fact, I never create outlets or actions in IB anymore. I always
create new class files in Xcode instead of IB. In Xcode 3.0, you don't
even need to drag the header file to the nib window, because
synchronization is automatic between Xcode and IB.
>> You can take a passive approach and just query each menu to see what the
>> current selection is when you need it. If you do that, you probably
>> won't use the menu actions sourceCurrencyDidChange: and
>> targetCurrencyDidChange: that I indicated. However, the point of these
>> action methods is that you can process a change in the state of a menu
>> immediately when it happens and then preserve that information for the
>> next time you need to process a conversion, instead of querying each menu
>> again for each transaction.
> The passive approach you describe is, or so it seems to me, the only
> viable way to do anything with this particular "mess" of mine.
You could implement it that way first, and consider putting in action
methods later in order to learn how to do that.
And, for the distant future, I'll just mention "Cocoa Bindings". This is
another way to keep things in sync, and it requires less code than the
target/action approach. In fact, in the developer examples you can find
a version of the Currency Converter application that uses Cocoa Bindings.
One of the visible results of doing it this way is that you no longer
need a button marked "Do It". The result field gets automatically
updated whenever you change either of the input fields.
--
Dave Seaman
Oral Arguments in Mumia Abu-Jamal Case heard May 17
U.S. Court of Appeals, Third Circuit
<http://www.abu-jamal-news.com/> >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Dec 16, 2003 Posts: 327
|
(Msg. 6) Posted: Fri Jan 11, 2008 3:25 pm
Post subject: Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Gregory Weston wrote:
> In article ,
> Don Bruder wrote:
> > Or am I making a rookie mistake? (I suspect I might be - after all, I
> > *AM* a rookie!)
>
> Rookie mistake. Your controller can do things besides gather the input
> data and calculate the result. There are several methods that you can
> define that will be invoked at well-defined times before the user has
> any chance to interact with your UI. How/when are you grabbing the units
> and conversion rates?
I've tried various times/ways of doing it, but none of them seemed to be
"right" - The data got grabbed and parsed, but where/how I did it just
didn't seem to be "correct", and once grabbed, I couldn't figure out
what to do with it next.
> You should be able to populate the menus (since
> they'll be static for any given run, right?)
I expect that most of the time, the answer would be yes, they're static.
Although I can see the possibility that the app sits idle for long
enough periods for the conversion values (though probably not the
currency names) to fluctuate significantly.
> right then - as long as
> you've defined the outlets in IB and in your source file such that your
> controller has a reference to the controls.
OK, let me bounce some code off you - maybe I understand what you're
saying, maybe I don't. You tell me which is the case!
(I'm deliberately not putting in "boilerplate" stuff to save space.
Assume it's there - in my local code, it is)
CurrencyItem.h
@interface CurrencyItem : NSObject
{
NSString *currencyName;
float dollarsPerUnit;
float unitsPerDollar;
}
// Return a new instance of CurrencyItem, inited with the values
// passed in.
+ (CurrencyItem *)newWithData:(NSString *)theName
dollarsPerUnit:(float)dpu
unitsPerDollar:(float)upd;
// Data getters
- (NSString *)name;
- (float)dollarsPerUnit;
- (float)unitsPerDollar;
// Data setters
- (void)setName:(NSString *)theName;
- (void)setDollarsPerUnit:(float)theValue;
- (void)setUnitsPerDollar:(float)theValue;
@end
RateSource.h
@interface RateSource : NSObject
{
BOOL Initialized;
NSMutableData *Buffer;
NSString *TheDate;
}
// Create and return an initialized, but empty, RateSource object.
+ (RateSource *)New;
// Finalize initializing a RateSource instance.
- (RateSource *)init;
// Fill the array passed to us with CurrencyItem objects parsed from
// the data we get from the website. Return the timestamp for the data
// as an NSString.
- (NSString *)fillArray:(NSMutableArray *)TheArray;
// Many lines of irrelevant (to this question) instance methods
// involved with parsing the HTML the website returns, building
// CurrencyItem objects using the parsed data, and stuffing those
// objects into the array elided to save space.
@end
Given these two interfaces, it *SOUNDS LIKE* you're saying I need my
controller to look similar to this:
MyController.h
@interface MyController:NSObject
{
// various other (not relevant to this question) instance variables
IBOutlet NSPopUpButton *Menu1;
IBOutlet NSPopUpButton *Menu2;
NSMutableArray *myArray;
}
// various irrelevant methods elided
- (void) awakeFromNib;
@end
MyController.m
@implementation myController
// other methods...
- (void)awakeFromNib
{
CFIndex counter;
RateSource *rateSource = [RateSource New];
// Perhaps much "other stuff", eventually leading to...
myArray = [NSMutableArray arrayWithCapacity:0];
// Get the data from the website
dataTimestamp = [rateSource fillArray:myArray];
// Now I think I need to populate the menus with the data
// that RateSource stuffed into myArray - right?
// Here's where I get confused...
// How do I instantiate "Menu1" and "Menu2"?
// Or do they already exist as ready-to-use objects when I
// reach this point?
// I'll assume that they do indeed exist, and that
// I can simply go to work on them. If that's not the case,
// PLEASE clue me as to how to "make" them.
[Menu1 removeAllItems]; // Empty out IB's placeholder items
[Menu2 removeAllItems]; // ditto
for (counter = 0; counter < [myArray count]; counter++)
{
[Menu1 addItemWithTitle:[[myArray objectAtIndex:counter] name]];
[Menu2 addItemWithTitle:[[myArray objectAtIndex:counter] name]];
}
}
@end
>
> > I looked at the awakeFromNib method, but that didn't get me anywhere
> > except frustrated. It looked *REALLY* promising at first, but as I dug
> > deeper, <pfffft> that idea went out the window. Or perhaps I need an
> > awakeFromNib method on/in the controller class itself? Something that
> > says "Oh, look! Here's an NSPopUpButton that needs to be populated! Call
> > somebody to do it!", perhaps?
>
>
> Ding!
"Ding" indeed... I'm thinking that the code above should do it - *IF*
I'm understanding what you've said correctly. Time for some testing...
(Time passes)
Uh-oh...
I've managed to break SOMETHING, it looks like. Got everything to
compile and link with zero warnings or errors, however, trying to run
the program to see if it's working does *ABSOLUTELY NOTHING*. No
bouncing icon in the dock, no earth-shattering kaboom, no nothing.
<sigh> I wonder what I've got wrong this time?
Back to the drawing board... Wuddayawannabet I mangled something while
re-creating the project that I foolishly trashed due to utter
frustration?
--
Don Bruder - dakidd.DeleteThis@sonic.net - If your "From:" address isn't on my whitelist,
or the subject of the message doesn't contain the exact text "PopperAndShadow"
somewhere, any message sent to this address will go in the garbage without my
ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Dec 16, 2003 Posts: 327
|
(Msg. 7) Posted: Fri Jan 11, 2008 5:21 pm
Post subject: SUCCESS! (Was Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons) [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Dave Seaman wrote:
> > Doesn't that run into the problem of "The menus need to be populated
> > before the controller gets a chance to run, therefore, the outlets need
> > to be part of some other class - But which one???"
>
> > Or am I making a rookie mistake? (I suspect I might be - after all, I
> > *AM* a rookie!)
>
> There's no problem. You would populate the menus in your controller's
> awakeFromNib method.
Greg managed to beat that into my thick skull  I think I've got it,
now. (and hopefully "forever"!)
> To the outlet in your controller class, that you connected to the popup
> in IB.
Except that, at the time I wrote that, I didn't quite grok the "add an
outlet" part.
> > I looked at the awakeFromNib method, but that didn't get me anywhere
> > except frustrated. It looked *REALLY* promising at first, but as I dug
> > deeper, <pfffft> that idea went out the window. Or perhaps I need an
> > awakeFromNib method on/in the controller class itself?
>
> Bingo.
Between you and Greg "double-teaming" me with it, that concept has
finally penetrated. And it works. Hooray!
> In fact, I never create outlets or actions in IB anymore. I always
> create new class files in Xcode instead of IB. In Xcode 3.0, you don't
> even need to drag the header file to the nib window, because
> synchronization is automatic between Xcode and IB.
A little beyond me right now, I'm thinking - Do please keep in mind that
prior to about Xmas eve, the only thing I knew about Objective C and/or
Cocoa could be summed up in *EXACTLY* two words. Those two words?
"It exists"
Maybe I'll "get there" some day, though
(But not before I manage to scrape together enough spare pennies to
upgrade to a newer kitty-cat than my current Panther, obviously...)
> >> You can take a passive approach and just query each menu to see what the
> >> current selection is when you need it. If you do that, you probably
> >> won't use the menu actions sourceCurrencyDidChange: and
> >> targetCurrencyDidChange: that I indicated. However, the point of these
> >> action methods is that you can process a change in the state of a menu
> >> immediately when it happens and then preserve that information for the
> >> next time you need to process a conversion, instead of querying each menu
> >> again for each transaction.
>
> > The passive approach you describe is, or so it seems to me, the only
> > viable way to do anything with this particular "mess" of mine.
>
> You could implement it that way first, and consider putting in action
> methods later in order to learn how to do that.
Yep, that's what I've done for now.
> And, for the distant future, I'll just mention "Cocoa Bindings". This is
> another way to keep things in sync, and it requires less code than the
> target/action approach. In fact, in the developer examples you can find
> a version of the Currency Converter application that uses Cocoa Bindings.
> One of the visible results of doing it this way is that you no longer
> need a button marked "Do It". The result field gets automatically
> updated whenever you change either of the input fields.
I bumbled onto that concept somewhere about New Years Day, took one
look, and fled screaming in abject terror... As I said above, "Maybe
I'll get there some day"
Meanwhile, this is supposed to be a success report!
And I'm happy to report that I do indeed have exactly correct
functionality! A few tweaks to the code in my previous message in the
thread (and *PROPERLY* re-creating the project... I botched something in
the first attempt, apparently) got me rolling.
Now I'm fully able to populate the menus (via the awakeFromNib method in
my controller object) and my "convert" action (also in the controller)
properly queries the individually.
One more comment:
Back around New Year's Eve, I tried (and failed) with something *VERY*
similar to what ended up working. The difference? In IB, I was trying to
connect *FROM* the NSPopUpButtons *TO* the "MyController" instance, and
failing every time because there was nothing to connect to. No matter
what I did, I couldn't figure out how to connect the button to the
controller. This time around, I went the other way - Connect *FROM* the
controller *TO* the button, and everything works as planned. D'OH!
Thanks for the help, guys!
Just in case anybody's interested, here's what I ended up with in my
controller class - a total of somewhere in the neighborhood of 65 lines
of code, counting comments and vertical whitespace. I guess Objective C
really CAN be compact!
/* MyController.h */
#import <Cocoa/Cocoa.h>
#import "Converter.h"
@interface MyController : NSObject
{
IBOutlet Converter *converter;
IBOutlet NSTextField *input;
IBOutlet NSPopUpButton *Menu1;
IBOutlet NSPopUpButton *Menu2;
IBOutlet NSTextField *output;
NSString *dataTimestamp; // holds the "generated on" timestamp
NSMutableArray *myArray; // holds currency names and exchange rates
}
- (IBAction)Convert:(id)sender;
- (void)awakeFromNib;
@end
And of course, the actual code... (I expect some lines are going to wrap
- beware...)
/* MyController.m */
#import "MyController.h"
#include "Converter.h"
#import "RateSource.h"
#import "CurrencyItem.h"
@implementation MyController
- (IBAction)Convert:(id)sender
{
// extract the source currency's dollars per unit value
float DPU = [[myArray objectAtIndex:[Menu1 indexOfSelectedItem]]
dollarsPerUnit];
// extract the target currency's units per dollar value
float UPD = [[myArray objectAtIndex:[Menu2 indexOfSelectedItem]]
unitsPerDollar];
// Convert the input value into dollars
float DollarValue = [converter ConvertInputToDollars:[input
floatValue] Rate:DPU];
// Convert the intermediate dollar value into the output value
float OutputValue = [converter ConvertDollarsToOutput:DollarValue
Rate:UPD];
// And finally, stuff the output field with the resulting number
[output setFloatValue:OutputValue];
}
- (void)awakeFromNib
{
CFIndex counter;
RateSource *rateSource = [RateSource New];
myArray = [NSMutableArray arrayWithCapacity:0];
// Hmmm... apparently I have to hold on to it via retain
// If I don't, Convert barfs.
[myArray retain];
// Get the data from the website
dataTimestamp = [rateSource fillArray:myArray];
converter = [Converter New];
// Ditto - Convert barfs if I don't explicitly retain. Interesting...
[converter retain];
// Now stuff the menus with the currency names from myArray.
[Menu1 removeAllItems]; // Empty out IB's placeholder items
[Menu2 removeAllItems]; // ditto
for (counter = 0; counter < [myArray count]; counter++)
{
[Menu1 addItemWithTitle:[[myArray objectAtIndex:counter] name]];
[Menu2 addItemWithTitle:[[myArray objectAtIndex:counter] name]];
}
}
@end
--
Don Bruder - dakidd.RemoveThis@sonic.net - If your "From:" address isn't on my whitelist,
or the subject of the message doesn't contain the exact text "PopperAndShadow"
somewhere, any message sent to this address will go in the garbage without my
ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Jun 25, 2003 Posts: 451
|
(Msg. 8) Posted: Sat Jan 12, 2008 12:50 am
Post subject: Re: SUCCESS! (Was Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons) [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
On Fri, 11 Jan 2008 17:21:53 -0800, Don Bruder wrote:
> Meanwhile, this is supposed to be a success report!
Great!
> And I'm happy to report that I do indeed have exactly correct
> functionality! A few tweaks to the code in my previous message in the
> thread (and *PROPERLY* re-creating the project... I botched something in
> the first attempt, apparently) got me rolling.
> Now I'm fully able to populate the menus (via the awakeFromNib method in
> my controller object) and my "convert" action (also in the controller)
> properly queries the individually.
> One more comment:
> Back around New Year's Eve, I tried (and failed) with something *VERY*
> similar to what ended up working. The difference? In IB, I was trying to
> connect *FROM* the NSPopUpButtons *TO* the "MyController" instance, and
> failing every time because there was nothing to connect to. No matter
> what I did, I couldn't figure out how to connect the button to the
> controller. This time around, I went the other way - Connect *FROM* the
> controller *TO* the button, and everything works as planned. D'OH!
The rule is, you drag *from* the object that needs to find something,
*to* the object that it needs to find. You wanted your controller to
know about the popup, so you needed to drag *from* the controller *to*
the popup.
It sometimes makes perfect sense to establish connections in both
directions. When you dragged from the popup to the controller, IB
thought you were trying to define the controller as the target of the
popup. Only trouble is, you hadn't defined any suitable IBAction methods
in the controller to connect to. If you were to define a
sourceCurrencyDidChange: action, as we discussed, then this is exactly
how you would make the connection.
--
Dave Seaman
Oral Arguments in Mumia Abu-Jamal Case heard May 17
U.S. Court of Appeals, Third Circuit
<http://www.abu-jamal-news.com/> >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Oct 03, 2004 Posts: 2243
|
(Msg. 9) Posted: Sat Jan 12, 2008 8:21 am
Post subject: Re: SUCCESS! (Was Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons) [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Dave Seaman wrote:
> On Fri, 11 Jan 2008 17:21:53 -0800, Don Bruder wrote:
> > Meanwhile, this is supposed to be a success report!
>
> Great!
>
> > And I'm happy to report that I do indeed have exactly correct
> > functionality! A few tweaks to the code in my previous message in the
> > thread (and *PROPERLY* re-creating the project... I botched something in
> > the first attempt, apparently) got me rolling.
>
> > Now I'm fully able to populate the menus (via the awakeFromNib method in
> > my controller object) and my "convert" action (also in the controller)
> > properly queries the individually.
>
> > One more comment:
> > Back around New Year's Eve, I tried (and failed) with something *VERY*
> > similar to what ended up working. The difference? In IB, I was trying to
> > connect *FROM* the NSPopUpButtons *TO* the "MyController" instance, and
> > failing every time because there was nothing to connect to. No matter
> > what I did, I couldn't figure out how to connect the button to the
> > controller. This time around, I went the other way - Connect *FROM* the
> > controller *TO* the button, and everything works as planned. D'OH!
>
> The rule is, you drag *from* the object that needs to find something,
> *to* the object that it needs to find. You wanted your controller to
> know about the popup, so you needed to drag *from* the controller *to*
> the popup.
Put another way, that may help reinforce the notion:
Messages are going to flow in the same direction you dragged the line.
If you drag a line from a UI element to the controller, at runtime you'd
expect the UI element to be asking the controller for stuff. If you
dragged the other way, at runtime the controller will be injecting stuff
into the UI.
G >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Oct 03, 2004 Posts: 2243
|
(Msg. 10) Posted: Sat Jan 12, 2008 8:39 am
Post subject: Re: SUCCESS! (Was Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons) [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Don Bruder wrote:
> > And, for the distant future, I'll just mention "Cocoa Bindings". This is
> > another way to keep things in sync, and it requires less code than the
> > target/action approach. In fact, in the developer examples you can find
> > a version of the Currency Converter application that uses Cocoa Bindings.
> > One of the visible results of doing it this way is that you no longer
> > need a button marked "Do It". The result field gets automatically
> > updated whenever you change either of the input fields.
>
> I bumbled onto that concept somewhere about New Years Day, took one
> look, and fled screaming in abject terror... As I said above, "Maybe
> I'll get there some day"
On first approach, Bindings can be a bit daunting. The easiest way, I
think, to get your feet wet with them is to put together a preferences
window and the use the NSUserDefaultsController class to actually manage
its controls. It's fairly segregated from the rest of your app and to my
mind gives a good illustration of what's going on without demanding too
much of you up front.
> - (void)awakeFromNib
> {
> CFIndex counter;
> RateSource *rateSource = [RateSource New];
>
> myArray = [NSMutableArray arrayWithCapacity:0];
> // Hmmm... apparently I have to hold on to it via retain
> // If I don't, Convert barfs.
> [myArray retain];
Yep. Barring the case where you're using garbage collection (and you're
not, given the tool versions you're using) there's a memory contract
that's described here.
<http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Con
cepts/ObjectOwnership.html#//apple_ref/doc/uid/20000043>
What it basically boils down to is that if you come into possession of
an object via a method with the word string 'alloc' or 'copy' in its
name, you own it and are responsible for releasing it. If you get the
object by any other method, you aren't responsible for it and can't
assume it's going to continue to be valid past (at most) the end of the
current pass through the event loop. If you need to be able to rely on
such an object, you'll send it a retain message.
Any object for which you are responsible (alloc'd, copied or retained)
should, when you're done with it, be sent a 'release' or 'autorelease'
message. If you send release, you should consider the object immediately
invalid. It may not be technically, but it *is* unreliable at that
point. If you send autorelease, it will (by default) last until the end
of the current event loop pass.
If you're specifically creating an object that you intend to hold onto
for a while, I'd suggest ...
myArray = [[NSMutableArray alloc] init];
.... and eliminating the retain line.
> // Get the data from the website
> dataTimestamp = [rateSource fillArray:myArray];
> converter = [Converter New];
> // Ditto - Convert barfs if I don't explicitly retain. Interesting...
> [converter retain];
Not familiar with a method named 'New'. I'm familiar with 'new' which
should be a shorthand for alloc/init and thus should be implicitly
retained. I should've mentioned it above but it's largely out of favor
as far as I'm aware and I forget it even exists.
G >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Dec 16, 2003 Posts: 327
|
(Msg. 11) Posted: Sat Jan 12, 2008 8:39 am
Post subject: Re: SUCCESS! (Was Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons) [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Gregory Weston wrote:
<snip snip>
> Any object for which you are responsible (alloc'd, copied or retained)
> should, when you're done with it, be sent a 'release' or 'autorelease'
> message. If you send release, you should consider the object immediately
> invalid. It may not be technically, but it *is* unreliable at that
> point. If you send autorelease, it will (by default) last until the end
> of the current event loop pass.
"Event loop pass", not "While the object is in scope"? Apparently what
little I've read on the topic hasn't been properly understood, then.
More reading is in order, I guess.
> If you're specifically creating an object that you intend to hold onto
> for a while, I'd suggest ...
>
> myArray = [[NSMutableArray alloc] init];
>
> ... and eliminating the retain line.
Which gives me back an array object in precisely what state? The way I'm
doing it, I get exactly what I expect - An empty array that isn't going
to vanish out from under me. Your way, I get the array, and it won't
vanish, but I'm not (yet...) clear on what other setup I might need to
do with it. Is it certain that it will be the same as what I get when I
ask for it my way, or do I need to think of it as a chunk of "array
clay" that I need to "pound into the exact shape I want"? My way, it
comes "pre-shaped".
> > // Get the data from the website
> > dataTimestamp = [rateSource fillArray:myArray];
> > converter = [Converter New];
> > // Ditto - Convert barfs if I don't explicitly retain. Interesting...
> > [converter retain];
>
> Not familiar with a method named 'New'. I'm familiar with 'new' which
> should be a shorthand for alloc/init and thus should be implicitly
> retained. I should've mentioned it above but it's largely out of favor
> as far as I'm aware and I forget it even exists.
Probably haven't heard of it 'cause it's my own construct for making a
new Converter instance. As in:
@interface Converter : NSObject
{
}
+ (Converter *)New;
- (float)ConvertInputToDollars:(float)InputAmount Rate:(float)Exchange;
- (float)ConvertDollarsToOutput:(float)Dollars Rate:(float)Exchange;
@end
It just did a "Converter *newItem = [[super alloc] init]; return
newItem;" operation, since there were no instance vars to worry about.
But, having said that, it's already "gone away" in a round of tinkering
and tuning - I've realized that the whole "Converter" class can go
*POOF* - It isn't needed except for illustrative purposes in the
tutorial. I can easily accomplish what it does directly in the convert
action of myController by (very slightly) altering two lines of
already-existing code. As an added bonus, by doing that, I lose the
overhead of sending two messages each pass, along with the one-time
setup overhead - not a huge savings in this case, but not nonexistant -
just non-significant except to someone like myself, who cut his
programming teeth counting machine cycles in 6502 assembly language -
Yeah, yeah, I know - I've got giga-cycles to burn, and RAM is cheap
these days, etc, etc, but <shrug> "waste not, want not", right?
--
Don Bruder - dakidd.RemoveThis@sonic.net - If your "From:" address isn't on my whitelist,
or the subject of the message doesn't contain the exact text "PopperAndShadow"
somewhere, any message sent to this address will go in the garbage without my
ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Oct 03, 2004 Posts: 2243
|
(Msg. 12) Posted: Sat Jan 12, 2008 8:42 am
Post subject: Re: SUCCESS! (Was Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons) [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Don Bruder wrote:
> @interface MyController : NSObject
> {
> IBOutlet Converter *converter;
> IBOutlet NSTextField *input;
> IBOutlet NSPopUpButton *Menu1;
> IBOutlet NSPopUpButton *Menu2;
> IBOutlet NSTextField *output;
>
> NSString *dataTimestamp; // holds the "generated on" timestamp
> NSMutableArray *myArray; // holds currency names and exchange rates
> }
> - (IBAction)Convert:(id)sender;
> - (void)awakeFromNib;
>
> @end
>
> ...
>
> - (void)awakeFromNib
> {
> CFIndex counter;
> RateSource *rateSource = [RateSource New];
>
> myArray = [NSMutableArray arrayWithCapacity:0];
> // Hmmm... apparently I have to hold on to it via retain
> // If I don't, Convert barfs.
> [myArray retain];
> // Get the data from the website
> dataTimestamp = [rateSource fillArray:myArray];
> converter = [Converter New];
> // Ditto - Convert barfs if I don't explicitly retain. Interesting...
> [converter retain];
Sorry. I just noticed something. If you've declared your Converter as an
outlet and it exists for the life of the program, you can (and probably
should) create it in your NIB file and just create the connection there.
Then you don't need to worry about the last two lines above at runtime.
You can create arbitrary objects in the NIB by instantiating NSObject
(or the closest stock ancestor of your class) and then using the
inspector window to set the specific class you want it to be. >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Oct 03, 2004 Posts: 2243
|
(Msg. 13) Posted: Sat Jan 12, 2008 12:54 pm
Post subject: Re: SUCCESS! (Was Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons) [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
In article ,
Don Bruder wrote:
> In article ,
> Gregory Weston wrote:
>
> <snip snip>
>
> > Any object for which you are responsible (alloc'd, copied or retained)
> > should, when you're done with it, be sent a 'release' or 'autorelease'
> > message. If you send release, you should consider the object immediately
> > invalid. It may not be technically, but it *is* unreliable at that
> > point. If you send autorelease, it will (by default) last until the end
> > of the current event loop pass.
>
> "Event loop pass", not "While the object is in scope"? Apparently what
> little I've read on the topic hasn't been properly understood, then.
> More reading is in order, I guess.
Prior to the release of 10.5, Cocoa code relied on manual memory
management. The framework includes some convenience mechanisms and an
standard idiom for their use that can greatly reduce the amount of
*actual* manual intervention, to the point where it's near automatic for
small-to-medium programs.
The core of that mechanism is the NSAutoreleasePool class. Instances of
that class are (automatically) maintained in a stack. When you send
autorelease to something derived from NSObject what happens is that it
gets added to a list in the topmost pool in that stack. When that pool
object is eventually deallocated, it sends a release message to
everything in that list (and is popped off the stack).
The framework creates an autorelease pool at the start of the event loop
and releases it at the end, so anything you didn't retain or create is
effectively gone at the end of the loop. If you need to, you can create
your own pools to help keep memory consumption down if, for example,
you've got loops that create a lot of objects. Save that for later,
though.
> > If you're specifically creating an object that you intend to hold onto
> > for a while, I'd suggest ...
> >
> > myArray = [[NSMutableArray alloc] init];
> >
> > ... and eliminating the retain line.
>
> Which gives me back an array object in precisely what state?
You own it. It will not go away unless you send it release directly or
implicitly as the eventual result of an autorelease.
> The way I'm
> doing it, I get exactly what I expect - An empty array that isn't going
> to vanish out from under me. Your way, I get the array, and it won't
> vanish, but I'm not (yet...) clear on what other setup I might need to
> do with it.
Nothing. It's *exactly* the same result, although as an implementation
detail it will almost certainly have involved fewer instructions to
achieve. (Which, reading further, should appeal to you.)
> But, having said that, it's already "gone away" in a round of tinkering
> and tuning - I've realized that the whole "Converter" class can go
> *POOF* - It isn't needed except for illustrative purposes in the
> tutorial.
I meant to mention in my first response: I'm not fond of that example
code. It's laudable that they try to offer a simple example of what's
going to be a new paradigm for a lot of people, but it's so contrived
that I question how useful it really is. It's one of those: "Noone would
actually do *that* that way" things.
> I can easily accomplish what it does directly in the convert
> action of myController by (very slightly) altering two lines of
> already-existing code. As an added bonus, by doing that, I lose the
> overhead of sending two messages each pass, along with the one-time
> setup overhead - not a huge savings in this case, but not nonexistant -
> just non-significant except to someone like myself, who cut his
> programming teeth counting machine cycles in 6502 assembly language -
> Yeah, yeah, I know - I've got giga-cycles to burn, and RAM is cheap
> these days, etc, etc, but <shrug> "waste not, want not", right?
I started in the same place you did. My advice is "learn to let go." I
know it's hard - it took me years - but it's the right thing to do. And
when you are optimizing, the first step is to know where those cycles
are actually going. >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Feb 27, 2008 Posts: 1
|
(Msg. 14) Posted: Wed Feb 27, 2008 10:04 pm
Post subject: Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
On Jan 11, 7:01 pm, Dave Seaman wrote:
> On Fri, 11 Jan 2008 02:02:45 -0800, Don Bruder wrote:
> > In article ,
> > Dave Seaman wrote:
> >> On Thu, 10 Jan 2008 18:35:27 -0800, Don Bruder wrote:
> ><snip for space>
> > (First whack at some thoughts that you've given me, done at 2 in the AM
> > local time... I'll actually try some of them when daylight comes around
> > again...)
> >> > This is where I hit my "real trouble" -
> >> > How do I set up and use the menus???
> >> If you mean you want to do that programmatically,
>
> [snip comments]
>
> >> you should make each
> >> NSPopUpButton an outlet of your controller class.
> > Doesn't that run into the problem of "The menus need to be populated
> > before the controller gets a chance to run, therefore, the outlets need
> > to be part of some other class - But which one???"
> > Or am I making a rookie mistake? (I suspect I might be - after all, I
> > *AM* a rookie!)
>
> There's no problem. You would populate the menus in your controller's
> awakeFromNib method.
>
> >> Then you can send
> >> appropriate messages to each one. For example, there are methods called
> >> addItemWithTitle: and addItemsWithTitles:, plus methods for removing
> >> items and so on.
> > Right - That part was pretty simple to figure out. Or would have been,
> > if it weren't for the "But where should I be sending the messages???"
>
> To the outlet in your controller class, that you connected to the popup
> in IB.
>
> > concept... My first stab at it was in the form of class methods grafted
> > onto the NSPopUpButton class, but that failed miserably (Well, actually,
> > it worked, but left me with absolutely no clue which menu I had just
> > populated, and seemingly no way to find out - and no way to say
> > "[Menu"X" getIndexOfSelectedItem] so that I could retrieve the data to
> > do the conversion)
> >> You might choose to adopt a scheme like this:
> >> // myController
> >> #import <Cocoa/Cocoa.h>
> >> @interface myController : NSObject {
> >> IBOutlet NSTextField *numberOfCurrencyUnits;
> >> IBOutlet NSPopUpButton *sourceCurrencyMenu;
> >> IBOutlet NSPopUpButton *targetCurrencyMenu;
> >> IBOutlet NSTextField *convertedValue;
> >> // other instance variables here
> >> }
> > OK, that follows reasonably, but leaves me in a bit of a bind - Unless
> > I've missed (or misunderstood) something - all too possible since I'm so
> > completely green when it comes to doing things "The Objective C way" -
> > the myController object doesn't actually "do anything" until it gets an
> > action passed to it.
>
> After the objects in your nib file have been unarchived and all the
> outlets and actions connected as specified by IB, each object receives
> the awakeFromNib message. You should implement that method in your
> controller class and use it to populate your popup menus. You can't do
> that in the controller's init method, because the IB connections haven't
> been set up yet when init runs. That's why we have the awakeFromNib
> method.
>
> > Which means that until sometime after the first
> > pass through the controller (by whatever means that pass is caused to
> > happen...) my menus are both full of the default stuff that IB puts
> > there as placeholders.
>
> Your controller doesn't run all at once. It has a bunch of methods, each
> of which runs when the corresponding message is received. Your
> awakeFromNib method runs before any of your action methods, and it can
> remove whatever IB put in the menu before adding new items.
>
> > I need to get a grip on the menus before the UI even becomes visible,
> > let alone has an action happen that makes the controller run, so I can
> > populate the menus. Or do I? Of COURSE I do... Don't I?
> > I looked at the awakeFromNib method, but that didn't get me anywhere
> > except frustrated. It looked *REALLY* promising at first, but as I dug
> > deeper, <pfffft> that idea went out the window. Or perhaps I need an
> > awakeFromNib method on/in the controller class itself?
>
> Bingo.
>
> >> If you haven't created the
> >> source files from your controller yet, you can do this from Interface
> >> Builder. If you already have generated source files, it may be easier to
> >> edit them to include the IBOutlets and IBActions shown above, and then
> >> drag the icon of the source file from your project window into the nib
> >> file's window, to let Interface Builder know about the new outlets and
> >> actions.
> ><blink blink> Now THERE is something that hadn't dawned on me! I wasn't
> > aware that it was possible to take "code" and cram it into the nib
> > file/IB. This may be the key I've been missing...
> >> Then make the necessary connections.
> > As if my code were something that already exists in IB's "I know how to
> > do this" bag of tricks... Yeah, That definitely puts me on a new way of
> > thinking...
>
> In fact, I never create outlets or actions in IB anymore. I always
> create new class files in Xcode instead of IB. In Xcode 3.0, you don't
> even need to drag the header file to the nib window, because
> synchronization is automatic between Xcode and IB.
>
> >> You can take a passive approach and just query each menu to see what the
> >> current selection is when you need it. If you do that, you probably
> >> won't use the menu actions sourceCurrencyDidChange: and
> >> targetCurrencyDidChange: that I indicated. However, the point of these
> >> action methods is that you can process a change in the state of a menu
> >> immediately when it happens and then preserve that information for the
> >> next time you need to process a conversion, instead of querying each menu
> >> again for each transaction.
> > The passive approach you describe is, or so it seems to me, the only
> > viable way to do anything with this particular "mess" of mine.
>
> You could implement it that way first, and consider putting in action
> methods later in order to learn how to do that.
>
> And, for the distant future, I'll just mention "Cocoa Bindings". This is
> another way to keep things in sync, and it requires less code than the
> target/action approach. In fact, in the developer examples you can find
> a version of the Currency Converter application that uses Cocoa Bindings.
> One of the visible results of doing it this way is that you no longer
> need a button marked "Do It". The result field gets automatically
> updated whenever you change either of the input fields.
>
> --
> Dave Seaman
> Oral Arguments in Mumia Abu-Jamal Case heard May 17
> U.S. Court of Appeals, Third Circuit
> <http://www.abu-jamal-news.com/>
hi how to display the video in the window >> Stay informed about: Objective C, Cocoa, Interface Builder, and NSPopUpButtons |
|
| Back to top |
|
 |  |
External

Since: Sep 09, 2006 Posts: 1943
|
(Msg. 15) Posted: Thu Feb 28, 2008 4:14 am
Post subject: Re: Objective C, Cocoa, Interface Builder, and NSPopUpButtons [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
|
|
| Back to top |
|
 |  |
| Related Topics: | Interface builder 3.0! - Hi, WTF! Interface Builder is completely changed, how do you drive it? I can't even get an AppControler (NSObject) and a CustomView to work. The generated the files were not added to the project and when I added them manually they didn't work anyway...
Interface Builder - Hi Group, I am converting a real-time data acquistion program from an OpenVMS system to Mac OS X. The code is pretty procedural and written in c, so I was planning on using the Carbon interface on Mac OS X. I have hacked together console based version...
Interface builder bugs? - Hi, Is this a known bug that the IB does not allow to set the size of a drawer properly. It seems that the height of the drawer's content (bottom placement) is always recalculated to a value dependent only on the offsets... Any workarounds?
Interface Builder's Symbols? - In Intertface Buider the outline view displays the nested hierarchy of all of the objects in the nib and the data paths for messages and bindings. Most of the data paths are labelled and show either a symbol that looks like an electricians symbol for a....
Populating a NSPopUpButtonCell in Interface Builder - In Interface Builder, how do you populate an NSPopUpButtonCell which is the data cell in an NSTableColumn? -- I am only a mirage. |
|
You can post new topics in this forum You can reply to topics in this forum You can edit your posts in this forum You can delete your posts in this forum You can vote in polls in this forum
|
|
|
|
 |
|
|