Несколько строк кода, которые поражают меня (или NSString дилемма "вне области видимости ... снова) - PullRequest
0 голосов
/ 28 августа 2010

Я полностью запутался с этой маленькой вещью "вне области видимости".Итак, вот некоторый код для описания моей ситуации:

Простое приложение, основанное на iphone.

Просмотр заголовка контроллера:

#import <UIKit/UIKit.h>

@interface global_nsstring_testViewController : UIViewController {
 UIImageView* image_view;
 NSString*  image_name;
}

@property (nonatomic,retain) UIImageView* image_view;
@property (nonatomic,retain) NSString*  image_name;

- (void) fadeView:(UIImageView*)View andThenChangeImageTo:(NSString*)Name;
- (void) switchImageAfterFade;

@end

Просмотр контроллера .m:

#import "global_nsstring_testViewController.h"
@implementation global_nsstring_testViewController
@synthesize image_view, image_name;

- (void) viewDidLoad {
 image_view = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"image1.png" ofType:nil]]];

//  ## Block 1 ## 
// NSString* name = @"image2.png";
// [self fadeView:image_view andThenChangeImageTo:name];

// ## Block 2 ##
// NSString* name = [NSString stringWithFormat:@"image%d.png",2];
// [self fadeView:image_view andThenChangeImageTo:name];

 [self.view addSubview:image_view];
 [super viewDidLoad];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//  ## Block 3 ##
// NSString* name = @"image2.png";
// [self fadeView:image_view andThenChangeImageTo:name];

//  ## Block 4 ##
    NSString* name = [NSString stringWithFormat:@"image%d.png",2];
    [self fadeView:image_view andThenChangeImageTo:name];
}

- (void) fadeView:(UIImageView*)View andThenChangeImageTo:(NSString*)Name {
 image_name = Name;
 image_view = View; // ## Point 1 ##

 [UIView beginAnimations:nil context:nil];
 [UIView setAnimationDuration:1];
 [UIView setAnimationDelegate:self];
 [UIView setAnimationDidStopSelector:@selector(switchImageAfterFade)];
 View.alpha = 0.3;
 [UIView commitAnimations];
}

- (void) switchImageAfterFade {
 UIImage* image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:image_name ofType:nil]]; // ## Point 2 ##
 [image_view setImage:image];
}

- (void) dealloc {
 [image_view removeFromSuperview];
 [image_view release];
    [super dealloc];
}

@end

С некомментированным #Block 4 # я получаю сообщение «out of scope» от отладчика на переменную image_name var в #Point 1 #.И поэтому я получаю EXC_BAD_ACCESS в #Point 2 #.

Однако с некомментированным #Block 3 # или #Block 1 # вместо #Block 4 # все работает нормально, так что я полагаю, что это все о NSString ...

Я пытался использовать NSMutableString, но тоже безуспешно.

Так что, если кто-нибудь скажет мне, что я делаю неправильно или как это исправить, я был бы очень признателен.

Еще одна странная вещь, которую я не получаю:

Если раскомментировать #Block 2 # и не использовать какие-либо точки останова, произойдет сбой, но изображение исчезнет.Но если я установлю точку останова на #Point 2 #, она будет аварийно завершена с EXC_BAD_ACCESS после одного шага.

версия xCode: 3.2.3

Ответы [ 2 ]

1 голос
/ 28 августа 2010

Прежде всего, «вне области» в отладчике просто означает, что отладчик не может понять, как отобразить переменную.Это по сути бессмысленно.Вы можете напечатать значение, нажав на консоль (в которой есть «gdb>») и напечатав

po image_name

Во-вторых, вы неправильно используете сеттеры.У вас есть @ property для ваших двух переменных, но вы не используете их.Когда вы делаете

variable = value;

, это просто установка переменной - методы свойств не вызываются.Тем не менее,

self.variable = value;

вызовет установщик свойств, который, поскольку у вас есть "неатомное значение", сохранит вашу переменную, и все будет разбухать.

В этом случае вывы делаете

image_name = Name;

, где вы хотите сделать

self.image_name = Name;

или (как подсказывает Тоб)

image_name = [Name retain];

Это очень распространенная вещь, когда вы начинаете делатьКодирование Objective-C, в котором вы путаете два способа установки переменной в классе, и очень важно, чтобы вы получили разницу.Ваши свойства не вызываются, когда вы не используете экземпляр точка переменная .

По совпадению, многие люди также склонны путать это еще больше, делая такие вещи, как

self.image_name = [Name retain];

Это абсолютно неверно.В результате вы будете пропускать «Имя» каждый раз, когда устанавливаете имя_изображения, из-за двойного сохранения (один раз для @property (неатомный, retain ) в вашем установщике и один раз для [Name retain]).

0 голосов
/ 28 августа 2010

Блок 4 использует удобный инициализатор, поэтому вы должны использовать [[NSString stringWithFormat:@"image%d.png",2] retain], иначе он будет автоматически освобожден. Не забудьте отпустить его после присвоения self.image_name = name

...