0

新参者で「“自分”って必要?および「自己参照を使用せずにObjective-Cクラスのプロパティを設定する」しかし、私のケースを説明できる明確な答えはまだ得られません。

単純なクラスがあり、UI には 2 つのテキストフィールドと 1 つのボタンがあります。コードは次のとおりです。


@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 は、'alloc' で作成されていない textfield_2.text によって割り当てられるため、ポインターが常に存在する必要があるとします。では、action2 で teststring_B の値が正しくなくなるのはなぜですか ??? (3) dealloc では、teststring_A と teststring_B をリリースする必要がありますよね? (そう思います )

私が知っているのは、「self.teststring_B = textfield_2.text;」のように「self.」を追加するかどうかだけです。それなら問題ないでしょう。値が正しくなります。技術的な理由が知りたいです。

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

[self setTeststring_B:foo];このプロパティは、 withまたは withの 2 つの方法で使用できるようになりましたself.teststring_B = foo;。重要な点は、後者は単に便利な書き方であることです。コンパイラはそれを最初の形式に変換します。つまり、コンパイラはself.foo = bar;行を に変換し[self setFoo:bar];ます。

これについて説明したので、クラッシュに進みます。自動解放される可能性が最も高い文字列値を取得しました。これで、プロパティではなく変数 に割り当てるだけです。teststring_Bそして、値を保持するのを忘れました。プロパティはあなたのためにその価値を保持していたでしょう.

これで、割り当てられた値が自動解放され (変数がまだその値を指していることを知らなかった)、後でまったく同じメモリ位置に新しいオブジェクトが作成されました (運が良ければ)。いずれにせよ、teststring_B変数はあなたが思っていたようにテキストを指しているのではなく、ランダムなオブジェクト (またはガベージ) を指しています。

これを修正するには、次の 2 つの方法があります。

// 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

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

あなたが今していることは単純な割り当てです。teststring_Aオブジェクトまたはteststring_Bポイントの割り当てが解除されると、クラッシュが発生する可能性があります。これはダングリング参照とも呼ばれます。

単純な割り当てのみが行われる理由は、@propertyセマンティクスを通じてセッターにアクセスしていないためです。代わりに行うことretainで、これらのNSStringオブジェクトを取得できます。self.teststring_A = textfield_1.text

copyただし、プロパティで使用する必要がありNSStringます。参照: 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 に答える