IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【setter方法内存管理之三 Objective-C语言】 -> 正文阅读

[移动开发]【setter方法内存管理之三 Objective-C语言】

前言

例如,有如下代码:
Person对象的定义如下:
@interface Person : NSObject
{
Car *_car;
}
– (void)setCar:(Car *)car;
– (Car *)car;
– (void)drive;
– (void)dealloc;
@end
@implementation Person
– (void)setCar:(Car *)car
{
[_car release];
_car = [car retain];
}
– (Car *)car
{
return _car;
}
– (void)drive
{
NSLog(@"走,去拉萨。。。);
[_car run];
}
– (void)dealloc
{
[_car release];
NSLog(@“人挂了。。。”);
[super dealloc];
}
@end

Car类的定义如下:
@interface Car : NSObject
{
int _speed;
}
– (void)setSpeed:(int)speed;
– (int)speed;
– (void)run;
– (void)dealloc;
@end
@implementation Car
– (void)setSpeed:(int)speed
{
_speed = speed;
}
– (int)speed
{
return _speed;
}
– (void)run
{
NSLog(@“时速为%d的车,在行驶”,_speed);
}
– (void)dealloc
{
NSLog(@“车挂了。。。”);
[super dealloc];
}
@end

main.h文件中:
#import <Foundtaion/Foundtaion.h>
#import “Person.h”
int main()
{
Person *p1 = [[Person alloc] init];
Car *bmw = [Car new]
bmw.speed = 100;
p1.car = bmw;
[p1 drive];
[bmw release];
bmw.speed = 200;
p1.car = bmw;
[p1 release];

return 0;
}

这时候,会报这句话发生僵尸对象错误:
– (void)setCar:(Car *)car
{
[_car release];
_car = [car retain];//这句话,会报僵尸对象错误

一、出现僵尸对象错误的原因

1)一开始,有一个Person对象p1,然后,有一个Car对象bmw,把bmw的speed属性,赋值为100,然后,把bmw作为p1对象的car属性,赋值给p1对象的car属性,这时候,怎么赋值的:
a 先把_car指向的对象release,这时候,_car为nil,release方法没有反应
b 再把bmw对象retain,再赋值给p1对象的_car属性。这时候,bmw对象的引用计数器的值为2
2)bmw对象,调用release方法,这时候,bmw对象的引用计数器的值为1
3)bmw对象的speed属性变为200
4)bmw对象,作为p1对象的_car属性,赋值给p1对象的_car属性,这时候,怎么赋值的:
a _car 指向的对象先release,_car现在指向bmw对象,bmw对象的引用计数器的值是1,release之后,bmw对象的引用计数器变为0
b bmw对象再retain,这时候,retain的了吗,retain不了,因为bmw对象已经被销毁了。
5)出现僵尸对象错误的原因:
在于, 新旧对象是同一个对象

二、解决方案

1.当发现新旧对象是同一个对象的时候,setter方法什么都不用做,只有当新旧对象不是同一个对象的时候,才release旧的,retain新的

– (void)setCar:(Car *)
{
if(_car != car)
{
[_car release];
_car = [car retain];
}
}

(_car != car)这个条件如果成立,说明什么问题啊,是不新旧对象不是同一个对象,不是同一个对象,我才去干嘛呢,才去release旧的,retain新的。
如果是同一个对象呢,什么都不做。

2.最终完美的setter方法的写法:

– (void)setCar:(Car *)car
{
if(_car != car)
{
[_car release];
_car = [car retain];
}
}

dealloc方法最终完美版怎么写:

– (void)dealloc
{
[_car release];
[super dealloc];
}

特别注意,我们内存管理的范围,是OC对象,所以,只有属性的类型是OC对象,这个属性的setter方法,才要像上面那样写,如果属性不是OC对象类型的,setter方法直接赋值就可以了,例如Person 对象的age属性

特别注意,NSString *类型的属性,需要像上面那样写setter方法,例如Person 对象的name属性,因为NSString 是一个OC类

– (void) setName:(NSString *)name
{
if(_name != name)
{
[_name release];
_name = [ name retain];
}
}
– (void)dealloc
{
[_name release];
[super dealloc];
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 19:17:25  更:2022-08-19 19:21:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 4:30:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码