几行代码,这让我大吃一惊(或NSString“超出范围”困境......再次)

时间:2010-08-28 10:22:36

标签: iphone nsstring scope out

我对这个小的“超出范围”的事情感到困惑。 所以这里有一些代码来描述我的情况:

简单的基于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#,我会在#Point 1#的image_name var上从调试器获得“超出范围”消息。因此,我在#Point 2#。

获得EXC_BAD_ACCESS

然而,使用未注释的#Block 3#或#Block 1#而不是#Block 4#一切正常,所以我想这都是关于NSString ......

我尝试过使用NSMutableString,但也没有任何成功。

所以如果有人能告诉我,我做错了什么或如何解决它,我将非常感激。

另一个奇怪的事情,我没有得到:

如果取消注释#Block 2#并且不使用任何断点,它将不会崩溃,但图像将消失。但是如果我在#Point 2#设置一个断点,只需一步就会崩溃EXC_BAD_ACCESS。

xCode版本:3.2.3

2 个答案:

答案 0 :(得分:1)

首先,调试器中的“超出范围”仅意味着调试器无法弄清楚如何显示变量。这基本上毫无意义。您可以通过单击控制台(其中包含“gdb&gt;”)并键入

来打印该值
po image_name

其次,您没有正确使用setter。你的两个变量有@ property属性,但你不是使用它们。当你这样做

variable = value;

它只是设置变量 - 没有调用属性方法。然而,

self.variable = value;

会调用属性setter,因为你已经“unatomic,retain”会保留你的变量,而且所有变量都会膨胀。

在这种情况下,你正在做

image_name = Name;

你想去哪里

self.image_name = Name;

或(如建议的那样)

image_name = [Name retain];

当你开始进行Objective-C编码时,你会混淆两种在类中设置变量的方法,这是很常见的事情,而且你获得差异至关重要。如果不使用实例 dot 变量,则不会调用您的属性。

巧合的是,很多人也倾向于通过做像

这样的事情来混淆这一点
self.image_name = [Name retain];

这绝对不正确。每次设置image_name时最终都会泄漏“名称”,因为你的setter中有一次双重保留(一次为@property(非原子,保留),一次为[Name retain]

答案 1 :(得分:0)

第4块使用便利初始化程序,因此您应该使用[[NSString stringWithFormat:@"image%d.png",2] retain],否则它将自动释放。 在使用self.image_name = name

进行分配后,请不要忘记将其释放