Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

blackenedheart

macrumors newbie
Original poster
Sep 3, 2013
6
0
Hi,

I am new to this forum and I am asking my first question after searching for a solution and not finding an answer. Can anybody explain to me how they would set up a NSPopUpButton so that when a value is chosen from the dropdown list, and floating point variable is represented and chosen?

For example, let say I had an NSPopUpButton with 3 choices. The three items to choose from are Wine, Beer, and Vodka.

If I wanted Wine = 2.75, and Beer = 3.75, and Vodka = 4.75, how would most people set this up?

I am more familiar with iOS development and I am getting lost with the NSPopUpButton class.

Thanks in advance for any help I may recieve.
 

Peter Maurer

macrumors member
Oct 9, 2008
71
25
Two ideas come to mind: You could associate NSNumber instances to the popup button's menu items via objc_setAssociatedObject, or you could simply set tags (275, 375, and 475) and divide those by 100 when you do any calculations based on those numbers.

EDIT: Forgot the most obvious option, namely NSMenuItem's -setRepresentedObject: and -representedObject methods. Again, you could store NSNumbers that way.
 

blackenedheart

macrumors newbie
Original poster
Sep 3, 2013
6
0
setRepresentedObject: is deprecated on OSX Lion. Can you give me an example of some code that might work instead?
 

chown33

Moderator
Staff member
Aug 9, 2009
10,758
8,451
A sea of green
Use tags. Then apply the general concept of mapping.

The input value is a tag (an integer). The output value is a float (or double). Here's an example mapping:
Code:
[B]In -> Out[/B]
 0 -> 2.75
 1 -> 3.75
 2 -> 4.75
The key concept is that the outputs can be anything you want. The input numbers are simply arbitrary tags attached to menu-items. Each menu-item's tag maps to a float or double value by going through a mapping object.

What class would make a suitable mapping object? Read this Apple article, then think it through:
http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Collections/Collections.html

If you aren't sure what to use, or you want further discussion, or confirmation of how to do the mapping, then post again.

I'm deliberately not posting code or an exact answer because you need to understand how mapping works in general, how to think about it, and how to use it to solve problems. You also have to know how the concept works in order to choose a suitable class. Not every mapping problem can be solved the same way.

EDIT
Also see:
https://developer.apple.com/library....html#//apple_ref/doc/uid/TP40008195-CH10-SW1
 
Last edited:

ArtOfWarfare

macrumors G3
Nov 26, 2007
9,567
6,073
setRepresentedObject: is deprecated on OSX Lion. Can you give me an example of some code that might work instead?

Deprecated code still works - there's just no promise that it shouldn't break during an OS update.

Also, I personally stay away from tags - it seems to me that using them is a violation of MVC.
 

chown33

Moderator
Staff member
Aug 9, 2009
10,758
8,451
A sea of green
Also, I personally stay away from tags - it seems to me that using them is a violation of MVC.

It depends on how tags are used.

In the "divide by 100" usage, there's clearly Model or Controller data (the actual numbers scaled by 100) in the View. If different values were needed, then the View would need to change.

Using tags as keys to a mapping, and having the mapping belong to the Model or the Controller, then the View is just using an Adapter. That is, the mapping is a simplified Adapter pattern. The need for an Adapter is driven by the limited representational capability of tags, i.e. they're ints, not objects.
 

mfram

Contributor
Jan 23, 2010
1,311
353
San Diego, CA USA
I would just get the index of the selection out of the View and let the Controller figure out how to map the index of the selection to some useful value.
 

ArtOfWarfare

macrumors G3
Nov 26, 2007
9,567
6,073
I would just get the index of the selection out of the View and let the Controller figure out how to map the index of the selection to some useful value.

This sounds better than tags, but still like a poor idea on account of the fact that shuffling the items in the list will mess this up.

I think I'd make a new class that stores the strings and values. I'd made several instances and stick them in an array. The method that displays the list queries the array and returns the string. The method that displays the value for the selected item queries the array and returns the value. Rearranging the data only has to take place in one spot, it allows for the potential to change your model to include more data later, and it doesn't make you rely on tags (which I honestly have no idea why exist...)
 

Peter Maurer

macrumors member
Oct 9, 2008
71
25
setRepresentedObject: is deprecated on OSX Lion. Can you give me an example of some code that might work instead?

Here you go:

Code:
#import "BeverageAppDelegate.h"
#import <objc/runtime.h>


@interface NSMenuItem (BeverageMenu)

	- (void)BM_setAssociatedDouble: (double)theDouble;
	- (double)BM_associatedDouble;

@end

@implementation NSMenuItem (BeverageMenu)

	static const void *BMAssociatedDoubleKey = (void*)&BMAssociatedDoubleKey;

	- (void)BM_setAssociatedDouble: (double)theDouble {
		objc_setAssociatedObject(self, BMAssociatedDoubleKey, [NSNumber numberWithDouble: theDouble], OBJC_ASSOCIATION_RETAIN);
	}

	- (double)BM_associatedDouble {
		return [objc_getAssociatedObject(self, BMAssociatedDoubleKey) doubleValue];
	}

@end


@implementation BeverageAppDelegate

	- (void)applicationDidFinishLaunching: (NSNotification*)theNotification {
		NSPopUpButton *thePopUpButton = self.popUpButton;
		NSMenu *theMenu = [thePopUpButton menu];
		[theMenu removeAllItems];
		[[theMenu addItemWithTitle: @"Beer" action: NULL keyEquivalent: @""] BM_setAssociatedDouble: 2.75];
		[[theMenu addItemWithTitle: @"Wine" action: NULL keyEquivalent: @""] BM_setAssociatedDouble: 3.75];
		[[theMenu addItemWithTitle: @"Vodka" action: NULL keyEquivalent: @""] BM_setAssociatedDouble: 4.75];
		[thePopUpButton selectItemAtIndex: 0];
		[thePopUpButton setAction: @selector(changeBeverage:)];
		[thePopUpButton setTarget: self];
	}

	- (void)changeBeverage: (id)sender {
		NSLog(@"associated double: %f", [[sender selectedItem] BM_associatedDouble]);
	}

@end
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.