我是新来的,已经搜索了相关文章,如“是”自我“必要吗?”和“在不使用自引用的情况下设置Objective-C类属性”但是我仍然无法得到一个可以解释我的案例的明确答案。
我有一个简单的类,我的UI有两个文本字段和一个按钮,这里是代码:
@interface testViewController : UIViewController {
NSString *teststring_A;
NSString *teststring_B;
IBOutlet UITextField *textfield_1;
IBOutlet UITextField *textfield_2;
}
@property (nonatomic, retain) NSString *teststring_A;
@property (nonatomic, retain) NSString *teststring_B;
- (IBAction)action1:(id)sender;
- (IBAction)action2:(id)sender;
@end
@implementation testViewController
@synthesize teststring_A;
@synthesize teststring_B;
- (void)dealloc {
[super dealloc];
}
- (IBAction)action1:sender
{
teststring_A = textfield_1.text ;
NSLog(@"teststring_A in action 1 is : %@\n", teststring_A);
teststring_B = textfield_2.text ;
NSLog(@"teststring_B in action 1 is : %@\n", teststring_B);
}
- (IBAction)action2:(id)sender
{
NSLog(@"teststring_A in action 2 is : %@\n", teststring_A);
NSLog(@"teststring_B in action 2 is : %@\n", teststring_B);
}
输出是:
2010-11-19 15:32:14.827 test[419:207] teststring_A in action 1 is : 123
2010-11-19 15:32:14.829 test[419:207] teststring_B in action 1 is : 456
2010-11-19 15:32:14.927 test[419:207] teststring_A in action 2 is : 123
2010-11-19 15:32:14.929 test[419:207] teststring_B in action 2 is : {(
>
)}
当点击按钮时,它首先触发action1然后触发action2。我的问题是...在action2中,teststring_B的值变得不正确,有时应用程序甚至崩溃。令我困惑的是(1)为什么teststring_A的值正确??? (2)teststring_B是由textfield_2.text分配的,它不是用'alloc'创建的,所以假设指针应该一直存在。那么为什么teststring_B的值在action2中变得不正确??? (3)在dealloc中,我应该释放teststring_A和teststring_B,对吧? (我想是的)
我所知道的是,如果我添加'self。',就像'self.teststring_B = textfield_2.text;'那就不会有问题了。价值是正确的。所以我想知道技术原因。
答案 0 :(得分:1)
您会混淆变量和属性。属性由变量支持,但实际上它们是方法。
在这里,您定义了一个名为teststring_B
的属性,该属性保留了分配给它的任何内容(并释放旧值)。等效方法看起来像这样(简化):
- (NSString *)teststring_B {
// Return the content of the variable teststring_B.
return teststring_B;
}
- (void)setTeststring_B:(NSString *)val {
// Retain new value.
[val retain];
// Release old value in variable teststring_B
[teststring_B release];
// Assign the new, retained value to variable teststring_B
teststring_B = val;
}
您现在可以通过两种方式使用该属性:[self setTeststring_B:foo];
或self.teststring_B = foo;
。重要的是,后者只是一种方便的编写方式,编译器会将其转换为第一种形式,即编译器会将self.foo = bar;
行转换为[self setFoo:bar];
。
现在我们已经解释了你的崩溃:你有一个很可能是自动释放的字符串值。现在你只需将它分配给变量 teststring_B
,而不是属性。你忘了保留价值。该物业将为您保留该价值。
现在指定的值是自动释放的(它不知道你有一个仍然指向它的变量),后来一个新的对象在完全相同的内存位置生活(如果你很幸运)。在任何情况下,teststring_B
变量现在都没有像您想象的那样指向文本,而是指向某个随机对象(或垃圾)。
有两种方法可以解决这个问题:
// First retain, then release; it might be the same object
// and if you would release it first its retain count might
// drop to 0 and get cleaned up before you can retain it again.
NSString *tmp = [textfield_2.text retain];
[teststring_B release];
teststring_B = tmp;
// Better !
self.teststring_B = textfield_2.text;
答案 1 :(得分:0)
不使用self直接访问变量将不会保留它。因此,当您稍后访问它时,变量会自动释放并使您的应用程序崩溃。
所以你可以写
1) [self setTeststring_B:textfield_2.text]; or
2) the dot syntax self.teststring_B = textfield_2.text; or
3) teststring_b = [textfield_2.text retain]
答案 2 :(得分:0)
你现在正在做的是简单的任务。如果对象teststring_A
或teststring_B
指向解除分配,则可能导致崩溃;这也被称为悬挂参考。
仅发生简单赋值的原因是因为您没有通过@property
语义访问setter;您可以通过retain
来获取NSString
个self.teststring_A = textfield_1.text
个对象。
但是,您应该将copy
与NSString
属性一起使用。请参阅:NSString property: copy or retain?
换句话说,你想要这个:
@property (nonatomic, copy) NSString *teststring_A;
@property (nonatomic, copy) NSString *teststring_B;
和此:
self.teststring_A = textfield_1.text ;
self.teststring_B = textfield_1.text ;