在手动使用的时候有可能会遇到野指针问题,比如下面例子:
************************************************************
/*** DogModel.h ***/
************************************************************
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface DogModel : NSObject
@property(nonatomic,copy)NSString *dogName;
-(void)doing;
@end
NS_ASSUME_NONNULL_END
************************************************************
/*** DogModel.m ***/
************************************************************
#import "DogModel.h"
@implementation DogModel
-(void)doing{
NSLog(@"%@ 会汪汪汪!",self.dogName);
}
-(void)dealloc{
NSLog(@"DogModel = (%@)dealloc method.",self.dogName);
[super dealloc];
}
@end
************************************************************
/*** UserModel.h ***/
************************************************************
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class DogModel;
@interface UserModel : NSObject
@property(nonatomic,copy)NSString *UserName;
- (void)setDog:(DogModel *) dog;
-(DogModel*)Dog;
@end
NS_ASSUME_NONNULL_END
************************************************************
/*** UserModel.m ***/
************************************************************
#import "UserModel.h"
@interface UserModel ()
{
DogModel *_Dog;
}
@end
@implementation UserModel
- (void)setDog:(DogModel *)dog{
_Dog = dog;
}
-(DogModel*)Dog{
return _Dog;
}
-(void)dealloc{
NSLog(@"UserModel = (%@)dealloc method.",self.UserName);
[_Dog release];
_Dog = nil;
[super dealloc];
}
@end
************************************************************
/*** 调用代码 ***/
************************************************************
UserModel *user = [[UserModel alloc]init];
user.UserName = @"struggle";
DogModel *dog=[[DogModel alloc]init];
dog.dogName=@"小黑";
user.Dog=dog;
[dog release];
dog=nil;
[user.Dog doing];
[user release];
user = nil;
抛出异常
Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
经过调试发现是野指针的问题,主要是下面两段代码出的问题。
/*** 调用代码 ***/
UserModel *user = [[UserModel alloc]init];
user.UserName = @"struggle";
DogModel *dog=[[DogModel alloc]init]; //dog retainCount == 1
dog.dogName=@"小黑";
user.Dog=dog; //user.Dog retainCount == 1
[dog release]; //user.Dog、dog retainCount == 1
dog=nil;
[user.Dog doing];
/*** UserModel.m ***/
- (void)setDog:(DogModel *)dog{
_Dog = dog;
}
当创建一个新的DogModel的实例变量 dog直接赋值给了user.Dog其真正目的只是给了user.Dog一个指针,user.Dog跟dog对应的内存空间是一样的。并且retainCount的值时1,当[dog release]后,retainCount = 0,这个对象也就释放掉了,而user.Dog实际上已经是一个野指针了。
解决方案
/*** UserModel.m ***/
- (void)setDog:(DogModel *)dog{
if(_Dog != dog){
[_Dog release];
_Dog = [dog retain];
}
}
这个方法,跟property中的(retain)是一样的
网友评论