Designated Initializer

不稳定的传送门

合成属性

Properties don’t always have to be backed by their own instance variables.

As an example, the XYZPerson class might define a read-only property for a person’s full name:

@property (readonly) NSString *fullName;

Rather than having to update the fullName property every time the first or last name changed, it would be easier just to write a custom accessor method to build the full name string on request:

- (NSString *)fullName
{
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

  假如一个属性是另外2个属性的复合体,那么可以重写该属性的getter方法,在方法中返回2个属性的结合,就不用每次更新2个属性的时候去更新这个复合属性啦

Lazy Factory

(1)Using a factory method to get instances of a class (factory method pattern)【还不是很了解,Todo:继续查找资料】

(2)Store the instances in a map, so you get the same instance the next time you ask for an instance with same parameter (multiton pattern)【项目里搜索模块将多个viewController存在一个dictionary里,当从dictionary读不到的时候就创建一个并写入】

(3)Using lazy initialization to instantiate the object the first time it is requested (lazy initialization pattern)【按需创建】

关于Strong属性

Strong Reference Cycles

Memory for Objective-C objects is allocated dynamically (on the heap), which means you need to use pointers to keep track of an object’s address.

In Objective-C, an object is kept alive as long as it has at least one strong reference to it from another object.

  如图,如果XYZPerson没有被释放,则firstName和lastName也永远不会被释放。

  

  UITableView.h中,对delegate和dataSource的声明方式如下  

@property (nonatomic, weak, nullable) id <UITableViewDataSource> dataSource;
@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;

  注意到,delegate和dataSource都是weak而不是strong,为什么呢?

  比如,现在我们创建一个具有UITableView的Controller,则该Controller中声明UITableView如下:

@property UITableView *tableView;

  注意,@property默认是strong的,回到刚刚那个问题,如果delegate是strong会发生什么事情呢?当我们为该tableView设置delegate的时候,即

tableView.delegate = self;

  此时Controller和TableView的关系如下:

  这2个Object相互之间是strong关系,就是说已经产生了Strong Reference Cycle,我们知道"An object is kept alive as long as it has at least one strong reference to it from another object.",那么这2个冤家就永远你中有我,我中有你,谁也不释放谁了。死锁!

  解决方法就是将其中一个关系改为weak,明显将delegate属性声明为weak是合理的,UITableView也是这样做的。dataSource属性同理。所以结论就是,任何delegate的属性都不应该为strong。

局部变量,默认是__strong

  为什么默认是__strong而不是__weak呢?因为方便!所有默认值的设置就是为了方便。

NSDate *originalDate = self.lastModificationDate;
self.lastModificationDate = [NSDate date];
NSLog(@"Last modification date changed from %@ to %@",
originalDate, self.lastModificationDate); NSDate *__weak originalDate = self.lastModificationDate;
self.lastModificationDate = [NSDate date];
NSLog(@"Last modification date changed from %@ to %@",
originalDate, self.lastModificationDate);

  以上2段代码的区别就是,第一段没问题,第二段,当self.lastModificationDate重新被赋值之后,它原本所指向的内存已经没有strong指针指向了,只有一个weak的originalDate指着,此时这块内存极有可能被系统释放掉。originalDate就成了悬浮指针。

  所以大部分情况下还是要使用__strong的,自然默认值为__strong也就合情合理了。

多线程中的strong与weak

In situations like this, you might want to cache the weak property in a strong variable to ensure that it is kept in memory as long as you need to use it:

- (void)someMethod
{
NSObject *cachedObject = self.weakProperty;
[cachedObject doSomething];
...
[cachedObject doSomethingElse];
}

  

  要时刻测试weak属性是否还存在啊,如下:

if (self.someWeakProperty)
{
[someObject doSomethingImportantWith:self.someWeakProperty];
}

  但是这就够了吗?并不是,多线程下,应该这样

 NSObject *cachedObject = self.someWeakProperty;              //
if (cachedObject) { //
[someObject doSomethingImportantWith:cachedObject]; //
} //
cachedObject = nil; //

  Todo:多线程的知识还是得补补,这里不是很懂

关于Copy属性

copy属性与NSMutableString

假如当前Controller有以下属性:

@property NSString *firstName;

在某个地方

NSMutableString *nameString = [NSMutableString stringWithString:@"John"];
self.firstName = nameString;  //此时指向了NSMutableString
[nameString appendString:@"ny"];

self.firstName的值为"Johnny",一个应为NSString*的值却莫名其妙被修改了?因为它指向了一个它不该指向的地方。

解决方案如下,为firstName添加copy属性

@property (copy) NSString *firstName;

在某个地方

NSMutableString *nameString = [NSMutableString stringWithString:@"John"];
self.firstName = nameString;  //此时self.firstName指向的是nameString的copy版本,该版本是NSSting类型,且对这个版本的String对象持strong指针
[nameString appendString:@"ny"];

self.firstName的值为"John",它与nameString指向的是两个完全不同的地方。

将传入的参数copy一份复制给成员变量

- (id)initWithSomeOriginalString:(NSString *)aString {
self = [super init];
if (self) {
_instanceVariableForCopyProperty = [aString copy];
}
return self;
}

假如不想让成员变量与传入的参数共同指向一个地方,那么只要copy一份就可以啦

Any object that you wish to set for a copy property must support NSCopying

Nothing

《Programming with Objective-C》第四章 Encapsulating Data的更多相关文章

  1. Programming In Scala笔记-第四章、类和对象

    类似于Java,Scala中也有类和对象的概念. 一.类.属性和方法 1.类 类是对一类事物的抽象,当一个类被定义后,就可以以该定义为模板,定义该类的一系列对象.比如说有以下一个模板 人类: 有姓名: ...

  2. The C++ Programming Language 学习笔记 第四章 类型和声明

    1.关于main 函数中的 return 0 C99标准中,main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的激活者(如操作系统).如果 main 函数的最后没有写 return ...

  3. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十四章:曲面细分阶段

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十四章:曲面细分阶段 代码工程地址: https://github. ...

  4. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化 学习目标 对Direct 3D编程在 ...

  5. 第四章 跨平台图像显示库——SDL 第一节 与SDL第一次亲密接触

    http://blog.csdn.net/visioncat/article/details/1596576 GCC for Win32 开发环境介绍(5) 第四章 跨平台图像显示库——SDL 第一节 ...

  6. 《Programming WPF》翻译 第8章 2.Timeline

    原文:<Programming WPF>翻译 第8章 2.Timeline Timeline代表了时间的延伸.它通常还描述了一个或多个在这段时间所发生的事情.例如,在前面章节描述的动画类型 ...

  7. 《Programming WPF》翻译 第7章 3.笔刷和钢笔

    原文:<Programming WPF>翻译 第7章 3.笔刷和钢笔 为了在屏幕上绘制一个图形,WPF需要知道你想要为图形填充什么颜色以及如何绘制它的边框.WPF提供了一些Brush类型支 ...

  8. 《Programming WPF》翻译 第7章 2.图形

    原文:<Programming WPF>翻译 第7章 2.图形 图形时绘图的基础,代表用户界面树的元素.WPF支持多种不同的形状,并为它们每一个都提供了元素类型. 7.2.1基本图形类 在 ...

  9. 《Programming WPF》翻译 第5章 5.数据模板和样式

    原文:<Programming WPF>翻译 第5章 5.数据模板和样式 让我们想象一下我们想要实现TTT更有娱乐性的一个版本(这是大部分游戏中最重要的特色).例如,TTT的一种变体允许玩 ...

随机推荐

  1. 30、Arrays工具类

    1.查询元素 int binarySearch(type[] a,type key):使用二分法查询key元素值在a数组中出现的索引:如果a数组不包含key元素,则返回负数.调用该方法时要求数组中元素 ...

  2. 【APP接口开发】php输出json格式数据

    请一定配合使用null转空字符的方法一起使用:(_unsetNull() 和 _json() 配合使用) 在一些接口的调用中,直接查询数据库出来的字段可能为null字段,但是为了简便前端的判断,需要把 ...

  3. 【JS】jQuery设置定时器,访问服务器(PHP示例)配合微信、支付宝原生支付,跳转web网页

    废话不多说,直接上代码: 把下面的js放在html的</body>即可 <!-- 设置页面定时器,3秒查询一次数据库该订单状态,ok就跳走 --xzz1115> <scr ...

  4. xtrabackup备份方式搭建一个mysql slave

    以前mysql搭建新备库都是在现在业务较小的备库上停止同步或停止数据库,然后拷贝数据库到新备库,配置好新备库后,再开启同步或数据库.然而,这次没有空闲备库用来搭新备库.需要从一个业务繁忙的数据库中搭建 ...

  5. 超级干货,python常用函数大总结

    我们在学习python的时候,接触最多的往往则是那些函数,对于python函数,在这里为大家总结归纳了这些,如果有缺漏,还请及时留言指正哦! 话不多说,干货来袭! 1.常用内置函数:(不用import ...

  6. SQL Server 错误(待补充)

    1.问题:在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. 解决方法: 打开“ ...

  7. Django模版中的过滤器详细解析 Django filter大全

    就象本章前面提到的一样,模板过滤器是在变量被显示前修改它的值的一个简单方法. 过滤器看起来是这样的: {{ name|lower }} 显示的内容是变量 {{ name }} 被过滤器 lower 处 ...

  8. C++ 类中有虚函数(虚函数表)时 内存分布

    虚函数表 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的.简称为V-Table.在这个表中,主是要一个类的虚函数的地址表 ...

  9. 通过CLR API实现C++调用C#代码交互

    对于某些跨平台程序,这也就意味着只能在windows下使用了 不过最近.Net开源或许以后可以跨平台 之前花了一些时间研究COM方式调用,太繁琐不推荐. COM方式调用总结 后来尝试使用CLR C++ ...

  10. i2c 协议解析

    1.基本概念 主机            初始化发送,产生时钟信号和终止发送的器件 从机            被主机寻址的器件 发送器        发送数据到总线的器件 接收器        从总 ...