我的progrram中有以下代码。我试图将每个数字追加到NSString。我在第二次附加字符串后收到错误。错误是 消息发送到解除分配的对象。我知道这是一个内存管理问题。我没有发布小计。有人知道小计被解除分配的原因吗?提前谢谢。
-(IBAction)digitPressed:(UIButton *)sender
{
NSString *digit = [[sender titleLabel] text];
subtotal=[subtotal stringByAppendingString:digit];
NSLog(@"appended string is :%@",subtotal);
}
-(void)ViewDidLoad
{
subtotal = [[NSString alloc]init];
}
答案 0 :(得分:5)
您的viewDidLoad
需要以小写v
开头。您还应该为retain
字符串声明subtotal
属性,然后使用setter来分配它,这样您的视图控制器就有了自己的指向字符串的指针,并且它不会被意外释放到自动释放池。
在您的标头文件中:
@property (nonatomic, retain) NSString *subtotal;
在您的实施文件中:
-(IBAction)digitPressed:(UIButton *)sender
{
NSString *digit = [[sender titleLabel] text];
self.subtotal = [subtotal stringByAppendingString:digit];
NSLog(@"appended string is :%@",subtotal);
}
-(void)viewDidLoad
{
self.subtotal = @"";
}
-(void)dealloc
{
[subtotal release];
[super dealloc];
}
但是如果你有一个不断被修改的字符串,那么最好将NSMutableString
用作Jacob Relkin mentions。它是为可修改而设计的,因此您不会继续创建和销毁不可变的NSString
对象。
答案 1 :(得分:4)
两件事:
1 - 您的viewDidLoad
方法错误,名称为viewDidLoad
,您需要通过调用[super viewDidLoad]
调用超类的实现
2 - 这条线错了:
subtotal = [NSString alloc]init];
您错过了领先的[
字符:
subtotal = [[NSString alloc]init];
stringByAppendingString:
的要点是返回的NSString
已自动释放,因此,您应该retain
返回的NSString
或将您的实例变量设为NSMutableString
并调用appendString:
@interface YourViewController : UIViewController {
//...
NSMutableString *subtotal;
}
@property (nonatomic, retain) NSMutableString *subtotal;
@end
@implementation YourViewController
@synthesize subtotal;
- (void) dealloc {
[subtotal release];
//...
[super dealloc];
}
- (void) viewDidLoad {
[super viewDidLoad];
subtotal = [[NSMutableString alloc] init];
}
-(IBAction)digitPressed:(UIButton *)sender {
NSString *digit = [[sender titleLabel] text];
[subtotal appendString: digit];
NSLog(@"appended string is :%@",subtotal);
}
//...
@end
答案 2 :(得分:2)
你没有release
subtotal
,但你也永远不会retain
。您有几个内存管理问题。首先,您应该在为其分配新值之前释放subtotal
的旧值,其次,您应该retain
该新值。现在对您所拥有的内容进行微小更改的示例:
-(IBAction)digitPressed:(UIButton *)sender
{
NSString *digit = [[sender titleLabel] text];
[subtotal autorelease];
subtotal = [[subtotal stringByAppendingString:digit] retain];
NSLog(@"appended string is :%@",subtotal);
}
答案 3 :(得分:0)
你需要阅读Cocoa Memory Management Rules。这一行:
subtotal = [subtotal stringByAppendingString:digit];
有两件事与内存管理规则有关。
它会为您提供您不拥有的字符串,因为该方法不以new
或alloc
开头或包含copy
。这意味着它将在未来的某个时刻消失,而不会问你。如果您想停止此操作,则可以通过保留所有权来声明所有权。
它会覆盖对小计的前一个值的引用。如果您拥有该对象,它现在已泄露。你需要先发布它。
修复代码:
首先删除
subtotal = [[NSString alloc]init];
来自viewDidLoad的。这是毫无意义的,因为它只是设置一个空字符串的小计。请改用:
subtotal = @"";
常量字符串文字永远不会消失,虽然从技术上讲你应该保留它,但你可以忘记它没有任何不良后果。
在digitPressed:
中,您将需要释放字符串的旧值,因为您将要替换它。有两种方法可以做到这一点。将其保存到临时变量并在追加后释放它,或者在追加之前自动释放它。您还需要保留新值。 e.g。
NSString* temp = [subtotal];
subtotal = [subtotal stringByAppendingString: digit];
[subtotal retain];
[temp release];
或
[subtotal autorelease];
subtotal = [subtotal stringByAppendingString: digit];
[subtotal retain];
您还需要确保在dealloc
说了这么多,使用属性尽可能多地执行内存管理要好得多。因此在@interface
中声明属性:
@property (copy) NSString* subtotal; // string properties should normally be copy
在实现中,您需要综合它。然后viewDidLoad包含
[self setSubtotal: @""];
并且您的操作包含
[self setSubtotal: [[self subtotal] stringByAppendingString: digit]];
您仍然需要release
中的dealloc
。