3

I am new to iOS and passing parameters by value or reference ( I am from a Java/.NEt background ) is confusing to me. you see I have a sort of utility / Helper method that I pass to it an NSMutableDictionary, and then a file location, and ask for it yo unrchive data form the file to the dictionary I sent it. this is the helper method :

 - (void)loadData:(NSMutableDictionary *)dictionary fromFile:(NSString *)fname  {
     dictionary = [ NSKeyedUnarchiver unarchiveObjectWithFile : [ self getFilePath:fname ] ] ;
    if ( [dictionary.allKeys count] < 1 ) {
       NSLog(@"Couldn't load file %@ ", fname);
    }  else  {
      NSLog(@"Loaded data from file %@ successfully", fname );
  }
}

now I call this method in the following line of code

      [ loadData: dataDict fromFile:@"data.archive"];

Now the problem is that by the end of the helper method , I have a variable called dictionary that does have values, but its not the original dictionary I passed from my calling line. What Am I Doing wrong?

Kalamantina
  • 303
  • 4
  • 10

3 Answers3

2

As explained here - Passing arguments by value or by reference in objective C - in objective c parameters are passed by value and so a modification made to the parameter is modifying a value and not the actual value of the reference being passed in.

If you want to modify your dictionary you should prefix it with an ** to pass the value of the reference and then access with *.

- (void)loadData:(NSMutableDictionary**)dictionary fromFile:(NSString*)fname  {
{
    *dictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:[self getFilePath:fname]];
    if ([*dictionary.allKeys count] < 1) {
        NSLog(@"Couldn't load file %@ ", fname);
    }  
    else  {
        NSLog(@"Loaded data from file %@ successfully", fname);
    }
}

Note: This sort of pointer dereferencing is a little funky and should probably restricted to **Error passing. It would probably make more sense to create a new dictionary copy content and return it.

Community
  • 1
  • 1
rogermushroom
  • 5,486
  • 4
  • 42
  • 68
1

I am guessing the problem is that data.archive is not a valid file format to load dictionary values. If you want to store values into a file then load them into a dictionary I would create a .Plist file in the main bundle of your app and you can load the values into a dictionary like so:

NSString *dataFile = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"];
NSDictionary *dataDictionary = [[NSDictionary alloc] initWithContentsOfFile:dataFile];
dana0550
  • 1,125
  • 1
  • 9
  • 16
1

dictionary and fname are both pointers, which are passed by value. as far as C constructs go, you would call that a reference. however, the language allows you to reassign that parameter to a new pointer.

so if we look at this in more detail:

- (void)loadData:(NSMutableDictionary *)dictionary << a pointer variable local to the method
        fromFile:(NSString *)fname
{
  dictionary = << oops! assigned that pointer parameter to a different instance
      [NSKeyedUnarchiver unarchiveObjectWithFile:[self getFilePath:fname]];
  if ([dictionary.allKeys count] < 1 ) { << new instance will be messaged, NOT the object originally passed by parameter

and to cover how to accomplish what you intend:

[dictionary setDictionary:[NSKeyedUnarchiver unarchiveObjectWithFile:[self getFilePath:fname]]];
justin
  • 104,054
  • 14
  • 179
  • 226