Objective C Declaring a NSDictionary in the correct place.

I have been trying to get some direction over at StackOverFlow on declaring in an Objective C program. So far as I can tell, Obj-C is substantially the same as C++ so I hope it OK posting here.

I have put some effort into developing this question as I have researched but I am still not confident about efficient declarations in Objective C.

I don't want to write code that relies on the Automatic Reference Counter to clear up the mess I leave.

This code is working correctly but I think that I should probably be declaring the dictionary differently in order not to waste memory.

Currently I have no property or static declaration but I know I will only need the immutable Dictionary created once when running the program. Looking at the profile in instruments I can't tel the difference between creating the dictionary and just using it.

Should I be putting a declaration somewhere in a property or something and using a getter to fetch the dictionary when needed perhaps?

Here is the code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    - (NSString *)operatorString:(id)operation {

       NSDictionary *operatorDictionary = [NSDictionary dictionaryWithObjectsAndKeys: 
                                        @"/",[NSNumber numberWithInt:1]
                                        , @"*",[NSNumber numberWithInt:2]
                                        , @"+",[NSNumber numberWithInt:3]
                                        , @"-",[NSNumber numberWithInt:4]
                                         <up to 120 other buttons or meta buttons>  , nil];
    return [operatorDictionary objectForKey:operation];
}

Then I look up the entry like this


    - (id)performOperation:(id)operation;
    {
        //Look up the required operator
        NSString *operationString = [self operatorString:operation];
        
        ...<do stuff with operationString>...
    
    }
nerak99 wrote:
Obj-C is substantially the same as C++ so I hope it OK posting here.

Functionally and conceptually, maybe. Syntactically, not really. To be honest, I think MacRumors may have been a better place for it. Even if it's not iPhone or Mac related, there's a lot of people with good Obj-C experience on there.

nerak99 wrote:
I don't want to write code that relies on the Automatic Reference Counter to clear up the mess I leave.

Why on Earth not?

It's kind of hard to get what you're after here without much context. For example, I can't tell what your class is supposed to be from the example above. The general setup of your dictionary looks like it'd be better suited to an array. The reason I say that is because the keys stored in there are all numbers. Again, it's difficult to tell without really knowing what your code is trying to do.

Wouldn't it be better to create the dictionary as a member of your class, rather than create one when the operatorString message is sent?

If you can give me a bit more context on what you want your code to do then I might be able to answer a little better.
Hey, Thanks for the reply.

I am following the CS193p course on iPhone programming and the guy uses a calculator for much of his examples.
The program uses a View with buttons which are handled by the View controller in which a piece of code runs if any of the "operator" buttons are pressed. (The second method above).
The View controller passes the job of doing the operation to a "Model" which is where my code is

As an exercise I was changing the program to look up the button number tag in a dictionary before using the returned operator in the routine where the calculation is done.

There is a full working example of the calculator here https://github.com/i4-apps/Calculator provided by a very helpful chap called Dave Barton.

My question is almost answered by your post. I think you are right I do want to have dictionary as a member of my model class but I do not understand enough about when to use

a) static data in classes
b) properties and synthesize

Yes I do have to use one of these but I have been searching for a template where I can a) do the thing and b) understand why I am doing it this way.

Thanks again for answering

a) I'm assuming by static you actually mean instance variables, rather than variables declared using the static keyword. Look at it this way: if you create instance variables, they'll exist for as long as the instantiation of that object is in scope. That is, the memory will be allocated for them when an instance is created and deallocated when the object ceases to exist.

What you're currently doing is create a new dictionary any time that function is called. So, within that function, memory is allocated for the dictionary, it is then populated, then at the end of the function, it'll be deallocated.

To me, it'd make more sense to have the dictionary as a instance variable.

b) Properties are just an easier way of implementing getter/setter methods. So instead of writing a [object getMember] and [object setMember: value] functions, you can make the variable a property and synthesize it, which will automatically create these getter/setter methods. Generally, I'd be more inclined to use this on single values, not collection objects (NSArrays, NSDictionarys etc).

My best advice is to create the dictionary as an instance variable and create a method that takes the key as a parameter and returns the corresponding value.
Well this is progress.
I have tried this.
1) Create and initialise a static NSDictionary and then I should be able to access this from an instance method shouldn't I?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@implementation HP11Brain
@synthesize programStack = _programStack;

static NSDictionary *dictionaryOfOperators;


+(void) initialize {
    if (self == [HP11Brain class])
    {
        dictionaryOfOperators = [NSDictionary dictionaryWithObjectsAndKeys: 
                                 @"/",[NSNumber numberWithInt:1]
                                 , @"*",[NSNumber numberWithInt:2]
                                 , @"-",[NSNumber numberWithInt:3]
                                 , @"+",[NSNumber numberWithInt:4]
                                 , nil];
 
    }
}

// I am trying (within an instance method) to access the dictionary objects with things like


    NSString *stringOfOperator = [self.class dictionaryOfOperators objectForKey:operation];


Which I would have thought I could do but I can't get the syntax right. As the above line stands, the objectForKey is not recognised by the compiler.
You'll have to excuse me because I'm not at an Obj-C compiler right now, so I cannot test this (furthermore, Obj-C isn't my primary language), but does this do what you're after?

I'll post it in code tags but the syntax highlighting won't work for obvious reasons.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Header File  ( HP11Brain.h )

@interface HP11Brain : NSObject
{
   NSDictionary *dictionaryOfOperators;
}

- (id) init;
- (NSString *) getOperatorWithKey: (NSNumber) key;
@end


// Source File  ( HP11Brain.m )
#import "HP11Brain.h"

@implementation HP11Brain

- (id) init
{
   self = [super init];
   
   if ( self != nil )
   {
      dictionaryOfOperators = [NSDictionary dictionaryWithObjectsAndKeys: 
                                      @"/",[NSNumber numberWithInt:1]
                                    , @"*",[NSNumber numberWithInt:2]
                                    , @"-",[NSNumber numberWithInt:3]
                                    , @"+",[NSNumber numberWithInt:4]
                                    , nil];
   }
   
   return self;
}

- (NSString *) getOperatorWithKey: (NSNumber) key
{
   return [dictionaryOfOperators objectForKey:key];
}
@end
Last edited on
Yes it did thank you very much for your help.

I only needed the declaration of the NSDictionary in the interface of the .m file and did not appear to need either of these two lines
- (id) init;
- (NSString *) operatorString:(id)operation;

I have two working methods but I am interested in that they are instance Methods, would something like this not be a class method?

Am I right that .h file declarations need only be for public methods?

Without putting anything in the .h file I can also do this I have found.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// in the interface
@property (nonatomic, weak) NSDictionary *dictionaryOfOperators;
@end

@implementation HP11Brain
@synthesize dictionaryOfOperators = _dictionaryOfOperators;

- (NSDictionary *)dictionaryOfOperators{
    if (!_dictionaryOfOperators) {
        self.dictionaryOfOperators = [NSDictionary dictionaryWithObjectsAndKeys: 
                                      @"/",[NSNumber numberWithInt:1]
                                      , @"*",[NSNumber numberWithInt:2]
                                      , @"-",[NSNumber numberWithInt:3]
                                      , @"+",[NSNumber numberWithInt:4]
                                      , nil];
        
        
    }
    return _dictionaryOfOperators;
}

With the call being the same for both the method you wrote and the one above.
Last edited on
Yeah, you don't need the class definitions in the header file; it's just usually good coding practice to do so. Ideally, for all methods; public, private, class or instance.

Yep, your code will work fine. However, you're returning a whole dictionary there, rather than just a value of that dictionary. I'm not sure whether or not that's what you wanted. You're code looks like a standard accessor function to me. I'd wager that it'd still work without that function explicitly written providing that everything is synthesized and the dictionary is populated in the init method.

Yeah, I made it an instance method because I need an instance of that class to exist for it to work (the init method called during instantiation populates the dictionary).

Interestingly (well maybe!) if I left the declaration out of the header, the dictionary died after one call. i.e. the first call worked but the second call returned null.

Thanks for all your help. I am still a little at sea so far as persistence of objects is concerned but I am further forwards.

Thanks.

Topic archived. No new replies allowed.