这是我第一次使用这个网站,我对Objective-c很新。我确信这是一个简单的问题,但由于某种原因,我遇到了很多问题。该应用程序旨在让用户通过文本字段输入字符串,然后它将选择句子的其余部分并显示它。问题似乎是我的*名称将在键盘方法后保留,并在changelabel方法中工作一次。然后,如果我再次按下该按钮,调用changelabel方法,该名称似乎已被释放并使应用程序崩溃。 #进口 #import“Array.h”
@interface RandomBoredViewController : UIViewController {
UILabel *label;
UIButton *button;
UITextField *textField;
Array *array;
NSString *name;
NSString *description;
NSMutableString *whole;
}
@property (nonatomic, retain) IBOutlet UILabel *label;
@property (nonatomic, retain) IBOutlet UIButton *button;
@property (nonatomic, retain) IBOutlet UITextField *textField;
@property (nonatomic, retain) Array *array;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *description;
@property (nonatomic, retain) NSMutableString *whole;
-(IBAction) keyBoard;
-(IBAction) changeLabel;
@end
和我的.m
#import "RandomBoredViewController.h"
@implementation RandomBoredViewController
@synthesize label;
@synthesize checker;
@synthesize button;
@synthesize textField;
@synthesize array;
@synthesize name;
@synthesize description;
@synthesize whole;
-(IBAction) changeLabel {
NSLog(@"Button being pushed");
description = [array getString];
NSLog(@"%@",description);
NSLog(@"%@",name);
name = [NSString stringWithString:name];
whole = [NSMutableString stringWithString:name];
NSLog(@"%@",name);
NSLog(@"%@",whole);
[whole appendString:description];
NSLog(@"%@",name);
NSLog(@"%@",whole);
label.text = whole;
NSLog(@"%@",name);
}
-(IBAction) keyBoard {
name = [NSString stringWithString:textField.text];
NSLog(@"%@",name);
label.text = [NSString stringWithString: name];
[textField resignFirstResponder];
}
- (void)viewDidLoad {
[super viewDidLoad];
array = [[Array alloc]init];
[array createArray];
NSLog(@"%i",[array arrayCount]);
whole = [[NSMutableString alloc]init];
name = [[NSString alloc]init];
}
- (void)dealloc {
[super dealloc];
[label release];
[button release];
[textField release];
[array release];
//[name release];
[description release];
}
@end
答案 0 :(得分:3)
您正在为自动释放的NSString实例设置名称,这可能是导致您的应用崩溃的原因。
使用
self.name = [NSString stringWithString:textField.text];
您的合成mutator将保留NSString并防止其被释放。
答案 1 :(得分:1)
在微观世界中,你发布的代码创建了两个名为name
的东西 - 一个实例变量和一个属性。
实例变量是直接访问的存储。他们没有行为。
属性是通过getter和setter访问的命名属性。所以他们可能有任意行为。它们可以报告实例变量的值或从实例变量计算的值或通过任何其他方式计算或获得的值。相关地,制定者可以retain
,assign
或以任何其他方式行事。
实例变量只能由它们所属的类的实例访问。通常,任何人都可以访问属性。
由于保留是一种行为,并且您已将其归因于您的name
媒体资源,因此对其进行设置会产生retain
。实例变量不能具有行为,因此为其设置值不会产生retain
或其他任何内容。
结果,这一行:
name = [NSString stringWithString:name];
创建一个新字符串并返回一个非拥有引用。这意味着它肯定会持续这个自动释放池的持续时间(即,您明确地可以将其作为参数传递或安全返回,假设您没有手动控制自动释放池)。
您将该引用存储到您的实例变量中。实例变量没有行为,因此存储了引用但您仍然不拥有该对象。在自动释放池的持续时间内使用它仍然是安全的。
因此,当您使用该方法访问它时,它是安全的。当你以后访问它时,它是不安全的。
相反,如果你选择了:
self.name = [NSString stringWithString:name];
然后,您已将该字符串设置为属性的新值。由于您的属性具有retain
行为,因此您可以完全安全地访问字符串对象,直到您另有说法为止。
因为您有一个与实例变量名称完全相同的属性,您可以随后以name
或self.name
的身份访问它。类似地,如果您确保手动拥有拥有引用,则可以直接存储到实例变量而不是通过属性。
如上所述,使用ARC是一种让编译器为您解决所有这些问题的方法。
该问题导致您的代码崩溃 - 您最终尝试访问已停止有效的引用。如果你取得了它的所有权,那么至少只要你保留所有权就会继续存在。
答案 2 :(得分:0)
尝试使用self.name 有时候这个东西也会让我感到困惑,为此你可能会考虑使用arc,在这种情况下大多数东西都可以避免。
使用属性时,应始终使用self.propertyName vs propertyName(仅限),它使用访问器(get propertyName,set propertyName),而不是直接访问该指针值。
请注意,规则有两个例外,init和dealloc不应该使用self。
self.name = [NSString stringWithString:name];
你在技术上也应该有一个init方法 初始化你的变量,我相信你应该在你的dealloc方法中最后调用[super dealloc],但这不是你的问题,可能并不重要(就像我不使用arc时那样做)
答案 3 :(得分:0)
在changeLabel
中更改实例变量时,应释放先前的值并保留新值。您可以使用访问器为您执行内存管理。另外,我认为您应该在{/ 1}}的实施中释放实例变量之后调用[super dealloc]
。
如果你不熟悉Cocoa内存管理(即使你是),最好是启用ARC(自动引用计数)并让编译器处理它。