0

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

简单的基于 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

4

2 回答 2

1

首先,调试器中的“超出范围”仅仅意味着调试器无法弄清楚如何显示变量。本质上是没有意义的。您可以通过单击控制台(其中包含“gdb>”)并键入来打印该值

po image_name

其次,您没有正确使用设置器。你的两个变量都有@property,但你没有使用它们。当你这样做

variable = value;

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

self.variable = value;

将调用属性设置器,因为你有“非原子,保留”将保留你的变量,一切都会膨胀。

在这种情况下,你正在做

image_name = Name;

你想做什么

self.image_name = Name;

或(如 tob 建议的那样)

image_name = [Name retain];

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

巧合的是,很多人也倾向于通过做类似的事情来混淆这一点

self.image_name = [Name retain];

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

于 2010-08-28T10:37:59.577 回答
0

Block 4 使用了一个便利的初始化器,所以你应该使用它,[[NSString stringWithFormat:@"image%d.png",2] retain]否则它会被自动释放。不要忘记在分配后释放它self.image_name = name

于 2010-08-28T10:34:16.310 回答