0

次のコードがあります。このプロパティを持つ 1 つの iVar は、クラスdeallocメソッドで保持および解放されます。iVar は 2 つのメソッドで使用され、値を継続的に変更しますが、使用すると値が壊れることがあります。何故ですか?

.h

@interface ChatController : NSObject <ASIHTTPRequestDelegate>{
NSTimer *timer;
NSString *_idLastMessageFromServer;
}

@property(nonatomic, retain)NSString *idLastMessageFromServer;
@end

.m

@implementation ChatController

@synthesize idLastMessageFromServer = _idLastMessageFromServer;

- (void)initLoopTimer{
timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(update:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}

- (void)update:(id)sender{
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:CONSTANT_YYYY];
[request setDelegate:self];
[request addPostValue:_idLastMessageFromServer forKey:CONSTANT_XXX];
[request setDidFinishSelector:@selector(requestUpdateFinish:)];
[request startAsynchronous];
}

- (void)requestUpdateFinish:(ASIHTTPRequest *)request{
NSString *response = [request responseString];
if(response && response.length){
    if(![response isEqualToString:CHAT_RESPONSE_NO_MESSAGES]){
        NSArray *array = [response componentsSeparatedByString:CHAT_PARSE_RESPONSE];
        if(array && [array count] == 2){
            **_idLastMessageFromServer = [array objectAtIndex:0];**
        }
     }
   }
}

しかし、ループがメソッドupdate:を呼び出すと、このコード行でクラッシュします

[request addPostValue:_idLastMessageFromServer forKey:CONSTANT_XXX];

EXC_BAD_ACCESS メッセージが表示されますが、なぜですか?

4

2 に答える 2

5

この行:

_idLastMessageFromServer = [array objectAtIndex:0];

おそらく

self.idLastMessageFromServer = [array objectAtIndex:0];

これにより、変数ではなくプロパティに直接アクセスするため、割り当て中に保持/解放がトリガーされます。それ以外の場合、ポインタは割り当てられますが、配列から取得されたオブジェクトは保持されず、すぐに無効になり、解放されたオブジェクトを指すポインタが残ります。

于 2012-05-07T14:29:20.310 に答える
3

_idLastMessageFromServerの代わりに使用するとself.idLastMessageFromServer、文字列が保持されません。を使用すると、オブジェクトの割り当てを解除する保持カウントをゼロにすることができます。その時点で、不良メモリへの参照があるため、アプリがクラッシュします。

正当な理由 (-init や -dealloc など) がない限り、iVar を直接使用しないでください。代わりにプロパティを使用してください。

 [request addPostValue:self.idLastMessageFromServer forKey:CONSTANT_XXX];

self.idLastMessageFromServer = [array objectAtIndex:0];

プロパティについてもう少し詳細な説明を追加します。

self.idLastMessageFromServerプロパティの値を読み取るために使用されると、自動生成されたメソッドが呼び出されます-idLastMessageFromServer。このメソッドは次のようになります。

- (NSString *)idLastMessageFromServer
{
    return _idLastMessageFromServer;
}

self.idLastMessageFromServerプロパティの値を設定するために使用すると、自動生成されたメソッドが呼び出されます-setIdLastMessageFromServer:。このメソッドは次のようになります。

- (void)setIdLastMessageFromServer:(NSString *)idLastMessageFromServer
{
    if (_idLastMessageFromServer != idLastMessageFromServer) {
        [_idLastMessageFromServer release];
        _idLastMessageFromServer = idLastMessageFromServer;
        [_idLastMessageFromServer retain];
    }
}

最後に 1 つ: メソッドで _idLastMessageFromServer を必ず解放してください-dealloc。何かのようなもの:

- (void)dealloc
{
    [_idLastMessageFromServer release];
    [super dealloc];
}

プロパティと iVar の詳細。

プロパティ (self.idLastMessageFromServer など) は、getter メソッドと setter メソッドを処理する簡単な方法です。メソッドであるため、データを保持できません。iVar (_idLastMessageFromServer など) は、メモリ内の場所へのポインタです。それらは単なるポインターであるため、アクセスを制御したり状態を維持したりすることはできません。

プロパティと iVar は連携して機能します。

この行@property(nonatomic, retain) NSString *idLastMessageFromServer;は、私の実装のどこかで、私のクラスがプロパティ idLastMessageFromServer のゲッターとセッターを持つことを示しています。

この行@synthesize idLastMessageFromServer = _idLastMessageFromServer;は、iVar _idLastMessageFromServer を使用して、idLastMessageFromServer の getter メソッドと setter メソッドを自動生成します。

つまり、プロパティは iVar へのアクセスを制御します。iVar はプロパティの保存場所です。

于 2012-05-07T14:34:46.960 に答える