@property中的内存损坏

时间:2012-05-07 14:25:24

标签: iphone objective-c ios ipad

我有下一段代码,一个保留了此属性的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];**
        }
     }
   }
}

但是当循环调用方法更新:时,它会在这行代码中崩溃

[request addPostValue:_idLastMessageFromServer forKey:CONSTANT_XXX];

有EXC_BAD_ACCESS消息,但为什么?

2 个答案:

答案 0 :(得分:5)

这一行:

_idLastMessageFromServer = [array objectAtIndex:0];

应该是

self.idLastMessageFromServer = [array objectAtIndex:0];

这将直接访问属性而不是变量,从而在赋值期间触发保留/释放。否则,指针被指定,但是从数组中取出的对象不会被保留,它可能很快变为无效,并且您将留下指向已释放对象的指针。

答案 1 :(得分:3)

使用_idLastMessageFromServer代替self.idLastMessageFromServer,您不会保留字符串。允许保留计数降至零,从而释放对象。那时你有一个坏内存的引用,因此应用程序崩溃。

除非你有充分的理由(比如-init或-dealloc),否则不要直接使用iVars。请改用该属性。

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

最后一点:确保在-dealloc方法中发布_idLastMessageFromServer。类似的东西:

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

有关属性和iVars的更多详细信息。

属性(如self.idLastMessageFromServer)只是处理getter和setter方法的简单方法。他们无法保存数据,因为它们是方法。 iVars(如_idLastMessageFromServer)是指向内存中某个位置的指针。他们无法控制访问和维护状态,因为它们只是一个指针。

属性和iVars协同工作。

@property(nonatomic, retain) NSString *idLastMessageFromServer;表示在我的实现中的某个地方,我的类将为属性idLastMessageFromServer设置一个getter和setter。

@synthesize idLastMessageFromServer = _idLastMessageFromServer;使用iVar _idLastMessageFromServer自动为idLastMessageFromServer生成getter和setter方法。

简而言之,该物业控制着对iVar的访问; iVar是酒店的存储地点。