0

我是新来的,已经搜索过“自己有必要吗?”之类的相关文章。和“在不使用自引用的情况下设置 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;' 那么就不会有问题了。该值将是正确的。所以我想知道技术原因。

4

3 回答 3

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;
}

您现在可以通过两种方式使用该属性: with[self setTeststring_B:foo];或 with 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;
于 2010-11-19T08:28:07.937 回答
0

Accessing the variable directly without using the self will not retain it. So when you accessing it later the variable got auto-released and makes your application crash.

so you can write

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]
于 2010-11-19T08:25:36.377 回答
0

你现在做的是简单的分配。teststring_A如果对象或teststring_B指向被释放,这可能会导致崩溃;这也称为悬空引用。

仅发生简单分配的原因是因为您没有通过@property语义访问设置器;你可以通过做来获得retain这些NSString对象self.teststring_A = textfield_1.text

但是,您应该使用copywithNSString属性。请参阅:NSString 属性:复制还是保留?

换句话说,你想要这个:

@property (nonatomic, copy) NSString *teststring_A;
@property (nonatomic, copy) NSString *teststring_B;

和这个:

self.teststring_A = textfield_1.text ;
self.teststring_B = textfield_1.text ;
于 2010-11-19T08:27:00.120 回答