Почему этот аргумент инициализатора уничтожен? - PullRequest
2 голосов
/ 23 января 2011

У меня есть инициализатор с двумя аргументами:

-(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;
}

Кажется, он получил неправильные значения из второго аргумента (mappedViewFrame). При поиске ошибки я обнаружил, что mappedViewFrame уничтожается (переопределяется в памяти?). Это легко увидеть в отладчике:

Снимок экрана отладчика на flickr (я пока не могу опубликовать изображения)

В копии все еще содержатся исходные значения, поэтому использование копии в этом случае было обходным путем. Но, конечно, я хочу понять, почему это могло произойти. Класс является прямым подклассом NSObject, весь проект является родным приложением OS X. Первый аргумент никогда не был уничтожен. Проблема не связана с передаваемыми значениями. Я переключал их, и это всегда было вторым повреждением.

Например, я вызвал инициализатор с этими примерами аргументов (отличных от приведенных на скриншотах отладчика), и ошибка произошла таким же образом:

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

Объявление метода:

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

Я немного новичок в Objective-C, поэтому мне жаль, если я пропустил что-то очевидное. Тем не менее, выглядит странным, что аргумент не остается действительным во время вызова метода.

Ответы [ 2 ]

1 голос
/ 23 января 2011

Я наткнулся на возможное решение, пытаясь воспроизвести ошибку, используя NSLog вместо отладчика.

Самое смешное, что зарегистрированные значения были правильными. Непосредственно перед вызовом NSLog отладчик покажет вывод мусора, как на скриншотах. Но после доступа к значению (с помощью NSLog или другого программного доступа) отладчик показывает правильные значения.

Так что это больше похоже на проблему с отладчиком. Неправильное отображение значений более вероятно, если некоторые объекты выделены.

Остается вопрос: почему моя программа не работала? Теперь я удалил переменную 'copy' (из строки 2) и получил прямой доступ к mappedViewFrame, и все работает как положено. Так что тот же код, который не работал раньше, теперь работает, я думаю, это может быть по двум причинам:

  1. В моей реализации произошла другая ошибка, которая вызвала неверные результаты вычислений. При введении переменной «copy» (после просмотра странного вывода отладчика) я исправил другую ошибку, не замечая этого. После этого я внес исправление в свое новое решение для копирования.

  2. Неизвестный фактор вызвал искажение переменной, когда я впервые столкнулся с проблемой, и не делает это сейчас. Ну, чтобы быть уверенным, я оставил копию там, и проверил, остается ли значение неизменным. Если это произойдет, я опубликую это здесь. До тех пор первая теория гораздо более вероятна.

Это научило меня не доверять отладчику, а вместо этого использовать ведение журнала, когда сомневаешься, что является болью. Если кто-нибудь знает, что вызывает странный вывод отладчика или как его исправить, я бы очень его оценил. Если у меня будет время, я в дальнейшем посмотрю, когда это появится, если это происходит только в xcode или это проблема отладчика gnu в целом.

0 голосов
/ 23 января 2011

Я попробовал это быстро через несколько минут.Я никогда не пытался создать проект Mac OS X, только проекты Foundation и iPhone, но идея кажется одинаковой.Я создал проект приложения какао "Stack1".Я предполагаю, что вы сделали то же самое, потому что я не думаю, что проект Foundation будет поддерживать структуры CGRect без ручного импорта CGGeometry.h или чего-то еще ... В любом случае, я установил новый класс Objective C под названием "Mapper" и реализовалinitWithSourceFrame: mappedFrame: указанный вами метод.

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

Я не изменял 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

Весь мой код выделил экземпляр Mapper, как ваш, и также использовал NSLogраспечатать ширину и высоту до [super init], после [super init], а также внутри блока if (self).

Вот журнал:

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

У меня естьтакже загрузил весь проект здесь:

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

...