【Objective-C学习记录】第二十九天

内存管理的规则:

1.alloc创建的必须释放,便利构造器创建的不要释放

2.加入容器中的对象会被执行一次retain操作,引用计数加1

3.容器移除对象,会向对象发送一次release消息,让对象的引用计数减1

4.当容器释放的时候,会向容器中的所有对象发送一次release消息

当进行内存管理时,只要遵循每次增加都对应一次释放就不会出错。下面是一个例子:

定义一个Hero类,添加如下几个属性和初始化方法:

1 @property (nonatomic, copy) NSString *name;
2 @property (nonatomic, assign) NSInteger speed;
3 @property (nonatomic, retain) NSString *ability;
4
5 - (instancetype)initWithName:(NSString *)name speed:(NSInteger)speed ability:(NSString *)ability;
6 + (Hero *)heroWithName:(NSString *)name speed:(NSInteger)speed ability:(NSString *)ability;

在.m文件里一定要设置属性:

1 @synthesize name = _name;
2 @synthesize speed = _speed;
3 @synthesize ability = _ability;

接着实现初始化方法和销毁方法:

 1  - (void)dealloc
 2 {
 3      //因为speed不是对象类型所以不需要释放内存
 4      [_name release];
 5      [_ability release];
 6      [super dealloc];
 7  }
 8
 9  - (instancetype)initWithName:(NSString *)name speed:(NSInteger) speed ability:(NSString *)ability
10  {
11       self = [super init];
12       if (self)
13       {
14            _name = name;
15            _speed = speed;
16            _ability = ability;
17       }
18       return self;
19 }
20
21 + (Hero *)heroWithName:(NSString *)name speed:(NSInteger) speed ability:(NSString *)ability
22 {
23       return [[[Hero alloc] initWithName:name speed:speed ability:ability] autorelease];
24 }

以及setter和getter方法:

 1 - (void)setName:(NSString *)name
 2 {
 3     if(_name != name)
 4     {
 5         [_name release];
 6          _name = [name copy];
 7     }
 8 }
 9 - (NSString *)name
10 {
11     return [[_name retain] autorelease];
12 }
13
14 - (void)setAbility:(NSString *)ability
15 {
16     if(_ability != ability)
17     {
18          [_ability release];
19          _ability = [ability retain];
20     }
21 }
22 - (NSString *)ability
23 {
24     return [[ability retain] autorelease];
25 }

KVC

Key Value Coding,键值编码,是一种间接访问实例变量的方法。

KVC提供了一种使用字符串(key)而不是访问器方法,去访问一个对象实例变量的机制。

常用方法:

- (id)valueForKey:(NSString *)key;通过key(实例变量名)获取实例变量的值。

- (void)setValue:(id)value forKey:(NSString *)key;通过key(实例变量名)给实例变量赋值。

- (id)valueForKeyPath:(NSString *)keyPath;通过keyPath获取实例变量的值。

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;通过keyPath给实例变量赋值。

- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;将一个字典对象的键值对给对象的各个实例变量赋值。

注意!当使用KVC时,如果key值和属性名不一样时,就会崩溃。在解决该情况之前,先看看KVC的内部实现过程:

A.setValue:forKey:(假如给的key是name)

1.去类里面找是否有一个方法叫setName:,有的话赋值,没有的话执行第二步

2.去类里面找是否有一个叫_name的实例变量,有的话赋值,没有的话执行第三步

3.去类里面找是否有一个叫name的实例变量,有的话赋值,没有的话执行第四步

4.查找当前类是否实现了setValue:forUndefinedKey:方法,如果有,走方法内部实现,如果还没有,就会抛出异常,引起崩溃

B.valueForKey:(假设给的key是name)

1.去类里面找是否有一个方法叫getName:,有的话取值,没有的话执行第二步

2.去类里面找是否有一个叫_name的实例变量,有的话取值,没有的话执行第三步

3.去类里面找是否有一个叫name的实例变量,有的话取值,没有的话执行第四步

4.查找当前类是否实现了valueForUndefinedKey:方法,如果有,走方法内部实现,如果还没有,就会抛出异常,引起崩溃

所以为了防止崩溃情况的发生,只需要重新实现以下setValue:forUndefinedKey:和valueForUndefinedKey:这两个方法即可:

1 - (void)setValue:(id)value forUndefinedKey:(NSString *)key
2 {
3
4 }
5
6 - (id)valueForUndefinedKey:(NSString *)key
7 {
8     return nil;
9 }

setValue:forUndefinedKey:方法里可以填充与之相关的操作

时间: 2024-10-25 20:59:14

【Objective-C学习记录】第二十九天的相关文章

【WPF学习】第二十八章 程序集资源

原文:[WPF学习]第二十八章 程序集资源 WPF应用程序中的程序集资源与其他.NET应用程序中的程序集资源在本质上是相同的.基本概念是为项目添加文件,从而Visual studio可将其嵌入到编译过的应用程序的EXE或DLL文件中.WPF程序集资源与其他应用程序中的程序集资源之间的重要区别是引用他们的寻址系统不同. 在前面章节已讨论过程序集资源的工作原理.因为每次编译应用程序时,项目中的每个XAML文件都转换为解析效率更高的BAML文件.这些BAML文件作为独立资源嵌入到程序集中.添加自己的资

第二十九天 月出惊山鸟 —Spring的AOP_AspectJ @annotation

6月14日,阴转雨."四面垂杨十里荷,向云何处最花多, 画楼南畔夕阳和.天气乍凉人寂寞, 光阴须得酒消磨,且来花里听笙歌." 面向切面的框架AspectJ邂逅Spring,不仅造就一种简洁,更带来更多的选择空间. 上篇的切面与代理配置方式,麻烦且繁琐.好在Spring 与 AspectJ 进行了集成,从接口和配置的泥潭爬出,善莫大焉. 下面把上一篇Spring的AOP 的例子改写一下,达到同样的效果. 1-3步骤不变. 4.定义一个 Aspect 切面类BallHandler.java

【WPF学习】第二十四章 基于范围的控件

原文:[WPF学习]第二十四章 基于范围的控件 WPF提供了三个使用范围概念的控件.这些控件使用在特定最小值和最大值之间的数值.这些控件--ScrollBar.ProgressBar以及Slider--都继承自RangeBase类(该类又继承自Control类).尽管它们使用相同的抽象概念(范围),但工作方式却又很大的区别. 下表显示了RangeBase类定义的属性: 表 RangeBase类的属性 通常不比直接使用ScrollBar控件.更高级的ScrollViewer控件(封装了两个Scro

【WPF学习】第二十九章 元素绑定——将元素绑定到一起

原文:[WPF学习]第二十九章 元素绑定--将元素绑定到一起 数据banding的最简单情形是,源对象时WPF元素而且源属性是依赖性属性.前面章节解释过,依赖项属性具有内置的更改通知支持.因此,当在源对象中改变依赖项属性的值时,会立即更新目标对象中的绑定属性.这正是我们所需要的行为--而且不必为此构建任何额外的基础结构. 为理解如何将一个元素绑定到另一个元素,下面创建一个简单的示例.该示例窗口包含了两个控件:一个Slider控件和一个具有单行文本的TextBlock控件.如果向右拖动滑动条上的滑

【WPF学习】第二十六章 Application类——应用程序的生命周期

原文:[WPF学习]第二十六章 Application类--应用程序的生命周期 在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一.创建Application对象 使用Application类的最简单方式是手动创建它.下面的示例演示了最小的程序:在应用程序入口(Main()方法)处创建名为MainWindow的窗口,并启动一个新的应用程序: 在本质

Egret入门学习日记 --- 第二十四篇(书中 9.12~9.15 节 内容)

第二十四篇(书中 9.12~9.15 节 内容) 开始 9.12节 内容. 重点: 1.TextInput的使用,以及如何设置加密属性. 操作: 1.TextInput的使用,以及如何设置加密属性. 创建exml文件,拖入组件,设置好id. 这是显示密码星号处理的属性. 创建绑定类. 实例化,并运行. 但是焦点在密码输入框时,密码是显示的. 暂时不知道怎么设置 “焦点在密码框上时,还是显示为 * 号” 的方法. 至此,9.12节 内容结束. 开始 9.13节 . 这个,和TextInput的使用

Egret入门学习日记 --- 第二十二篇(书中 9.7~9.8 节 内容)

第二十二篇(书中 9.7~9.8 节 内容) 开始 9.7节 内容. 重点: 1.进度条ProgressBar的声明和使用. 操作: 1.进度条ProgressBar的声明和使用. 现在真的轻车熟路了,很简单.无非就是设置一下最大值,当前值的属性. 然后,事件监听的话,也是一样的.只不过事件名字的话,我就选书中这个事件吧. 可惜不能发动图,不然你们就可以看到这个进度条,每帧+1的速度前进. 当然,如果你想换自定义皮肤,还是老规矩,去找默认的 EXML 文件. 然后,怎么换素材,就按照自己喜欢的换

Egret入门学习日记 --- 第二十五篇(书中 9.16~9.17 节 内容)

第二十五篇(书中 9.16~9.17 节 内容) 对于昨天的关于 List 组件使用的问题,我打算到书中提到List之后,再回头补充. 还有就是 Scroller 的 TileLayout 布局方式,也要去研究一下. 好了,开始按照书中内容一步一步走. 开始 9.16节. 重点: 1.设定TabBar皮肤. 2.设置TabBar布局. 操作: 1.设定TabBar皮肤. 第一步,准备素材! 第二步,创建 exml 文件! 第三步,拖入组件!约束大小! 第四步,增加两个状态 down 和 up.

Egret入门学习日记 --- 第二十八篇(书中 9.19 ~ 9.19 节 内容)

第二十八篇(书中 9.19 节 内容) 没想到第九章的组件篇可真是够长的,没事,慢慢来吧. 开始 9.19节. 重点: 1.创建一个Tips提示组件. 操作: 1.创建一个Tips提示组件. 哇!出大问题!这个Tips组件有点牛皮!怎么办? 书中内容这部分,我直接懵逼. 还有这部分也是. 一点一点来分析好吧. 好,开始分析一波. 第一步:查看最终展示效果. 这是最终效果.(我去,我现在才知道,原来博客园的编辑器还可以放Gif图片...) 第二步:这个黑色的弹框组件本质上是由什么构成的? 可见,在