2

I have an initializer with two arguments:

-(id) initWithSourceFrame:(CGRect)sourceViewFrame  mappedFrame:(CGRect)mappedViewFrame {
  CGRect copy = mappedViewFrame;
  self = [super init];
  if (self) {
    // not able to access mappedViewFrame here..
    // copy is ok
    // doing initialization here...
  }
  return self;
}

It seemed to get wrong values from the second argument (mappedViewFrame). When looking for the error, I found out that mappedViewFrame gets destroyed (overridden in memory?). This can be easily observed in the debugger:

Debugger Screenshot on flickr (I cannot post images yet)

The copy is still holding the original values, so using the copy was a workaround in this case. But of course I want to understand why this could happen. The class is a direct subclass of NSObject, the whole project is a OS X native app. The first argument was never destroyed. The problem does not relate to the values passed in. I switched them and it was always the second which was corrupted.

For example, I called the initializer with these example arguments (different from those in the debugger screenshots), and the error occured in the same way:

Mapper *mapper = [[Mapper alloc] initWithSourceFrame:CGRectMake(0, 0, 100, 100) mappedFrame:CGRectMake(0,0, 200,200)];

The method declaration:

-(id) initWithSourceFrame:(CGRect) sourceViewFrame mappedFrame:(CGRect) mappedViewFrame;

I'm somewhat new to Objective-C, so I am sorry if I missed something obvious. However, it looks strange that an argument does not keep valid during method invocation.

frank
  • 597
  • 4
  • 7

2 Answers2

1

I stumbled upon a possible solution while I tried to reproduce the error using NSLog instead of the debugger.

The funny thing was, the logged values were correct. Just before the call to NSLog the debugger shows still the garbage output as in the screenshots. But after accessing the value (by NSLog or another programmatic access) the debugger shows the correct values.

So it looks more like a problem with the debugger. The wrong display of values is more likely to appear if some objects are allocated.

Remains the question: Why did my program not work? I now removed the 'copy' variable (from line 2) and access mappedViewFrame directly and everything works as expected. So the same code which didn't work before now works, I think this can be of two reasons:

  1. There was another error in my implementation, which caused the wrong computation results. When introducing the 'copy' variable (after seeing the weird debugger output), I fixed the other error without noticing. Afterwards, I credited the fix to my new copying solution.

  2. An unknown factor caused the variable to be distorted when I first encountered the problem and does not do so now. Well, to be shure I left the copy there, and check if the value remains unchanged. If this will happen, I will post it here. Until then, the first theory is much more likely.

This thing teached me not to trust the debugger, and instead use logging when in doubt, which is a pain. If anybody knows what causes the strange debugger output or how to fix it I would greatly appreceate it. If I have time I will do further look into when this does appear, if it happens just in xcode or is a problem of the gnu debugger in general.

frank
  • 597
  • 4
  • 7
0

I have tried this quickly in a few minutes. I've never really tried to create a Mac OS X project, just Foundation and iPhone projects, but the idea seems the same. I created a Cocoa Application project "Stack1". I'm assuming you have done the same, because I don't think a Foundation project would support CGRect structs without manually importing CGGeometry.h or something... Anyway, I set up a new Objective C class called "Mapper" and implemented the initWithSourceFrame:mappedFrame: method you specified.

Mapper.h

#import <Cocoa/Cocoa.h>

@interface Mapper : NSObject {

}

-(id) initWithSourceFrame:(CGRect) sourceViewFrame mappedFrame:(CGRect) mappedViewFrame;

@end

Mapper.m

#import "Mapper.h"

@implementation Mapper

-(id) initWithSourceFrame:(CGRect)sourceViewFrame  mappedFrame:(CGRect)mappedViewFrame {
    NSLog(@"height: %f, width: %f", mappedViewFrame.size.height, mappedViewFrame.size.width);
    self = [super init];
    NSLog(@"height: %f, width: %f", mappedViewFrame.size.height, mappedViewFrame.size.width);
    if (self) {
        NSLog(@"height: %f, width: %f", mappedViewFrame.size.height, mappedViewFrame.size.width);
    }
    return self;
}

@end

I didn't alter Stack1AppDelegate.h.

Stack1AppDelegate.m

#import "Stack1AppDelegate.h"
#import "Mapper.h"

@implementation Stack1AppDelegate

@synthesize window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application 
    Mapper *mapper = [[Mapper alloc] initWithSourceFrame:CGRectMake(0, 0, 100, 100) mappedFrame:CGRectMake(0,0, 200,200)];

}

@end

All my code did was allocate a Mapper instance as yours did and also use NSLog to print the width and height before [super init], after [super init], and also within the if (self) block.

Here's the log:

2011-01-23 16:09:07.167 Stack1[935:a0f] height: 200.000000, width: 200.000000
2011-01-23 16:09:07.170 Stack1[935:a0f] height: 200.000000, width: 200.000000
2011-01-23 16:09:07.170 Stack1[935:a0f] height: 200.000000, width: 200.000000

I've also uploaded the whole project here:

http://ak.net84.net/files/temp/Stack1.zip

Aram Kocharyan
  • 20,165
  • 11
  • 81
  • 96
  • Also, what is the line used to invoke this method? – Aram Kocharyan Jan 22 '11 at 23:13
  • Yes, [super init] just returns self, so line 3 of my code example is not supposed to change anything. Normally I would not put code before [super init], but in my case this was the only way to get the passed in value for the second argument ('mappedViewFrame'), as this is gone later (see screenshot). – frank Jan 22 '11 at 23:16
  • Regarding your question to the invoking code: I already narrowed the problem to the point that the invocation does not affect the problem. Anyway, I will add an example to make that more clear. – frank Jan 22 '11 at 23:23
  • Added the declaration to the question. – frank Jan 22 '11 at 23:51
  • Your example pointed me to a quite likely solution. Looks like I was led to trick myself by a wrong debugger output. I added an answer to describe what may have happened. Thanks again for your support. – frank Jan 23 '11 at 10:28
  • No problem, because this was quite an unusual matter. – Aram Kocharyan Jan 23 '11 at 22:23