object-C 类属性应添加“self”同时分配它的值?

发布于 2024-10-02 23:21:39 字数 1796 浏览 9 评论 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;”那么就不会有问题了。该值将是正确的。所以我想知道技术原因。

I am new here, and already searched related articles like "Is “self” necessary?" and "Setting an Objective-C class property without using a self reference" However i still can't get a clear answer which can explain my case.

I have a simple class and my UI has two textfield and one button, here is the code:


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

the output is :


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 : {(
    >
)}

 

And when click button, it triggers action1 first then action2. My problem is... in action2, the value of teststring_B becomes incorrect, sometimes the application even crashes. What confuses me is (1) why is the value of teststring_A correct??? (2) teststring_B is assigned by textfield_2.text which is not created with 'alloc', so suppose the pointer should exist all the time. then why teststring_B's value becomes incorrect in action2 ??? (3) in dealloc, I should release teststring_A and teststring_B, right? (i think so )

All I know is if I add 'self.', like 'self.teststring_B = textfield_2.text;' then there won't be problem. the value will be correct. So I would like to know the technical reason.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

↘紸啶 2024-10-09 23:21:39

您混淆了变量属性。属性由变量支持,但实际上它们是方法。

在这里,您定义一个名为 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;

You are confusing variables and properties. Properties are backed by variables, but in reality they are methods.

Here, you define a property named teststring_B which retains anything that gets assigned to it (and releases the old value). The equivalent methods would look like this (simplified):

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

You can now use the property in two ways: either with [self setTeststring_B:foo]; or with self.teststring_B = foo;. The important point is that the later is just a convenient way of writing, the compiler will translate it into the first form, that is the compiler will turn the self.foo = bar; lines into [self setFoo:bar];.

Now that we have this explained, on to your crash: you've got a string value which is most likely autoreleased. Now you just plain assign it to the variable teststring_B, not the property. And you forgot to retain the value. The property would have retained that value for you.

Now the assigned value was autoreleased (it didn't know you've got a variable still pointing to it) and later a new object came to life at the exact same memory location (if you're lucky). In any case, the teststring_B variable is now not pointing to the text as you thought it would, but to some random object (or to garbage).

There are two ways to fix this:

// 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;
月野兔 2024-10-09 23:21:39

不使用 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]

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]
池予 2024-10-09 23:21:39

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

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

但是,您应该将 copyNSString 属性一起使用。请参阅: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 ;

What you are doing now is simple assignment. That can cause a crash if the object teststring_A or teststring_B point to is deallocated; this is also called a dangling reference.

The reason only simple assignment is happening is because you aren't accessing the setters through the @property semantics; you could get a retain on those NSString objects by doing self.teststring_A = textfield_1.text instead.

However, you should be using copy with NSString properties. See: NSString property: copy or retain?

In other words, you want this:

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

and this:

self.teststring_A = textfield_1.text ;
self.teststring_B = textfield_1.text ;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文