《Programming with Objective-C》第四章 Encapsulating Data
Designated Initializer
合成属性
Properties don’t always have to be backed by their own instance variables.
As an example, the
XYZPersonclass might define a read-only property for a person’s full name:@property (readonly) NSString *fullName;Rather than having to update the
fullNameproperty 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的更多相关文章
- Programming In Scala笔记-第四章、类和对象
类似于Java,Scala中也有类和对象的概念. 一.类.属性和方法 1.类 类是对一类事物的抽象,当一个类被定义后,就可以以该定义为模板,定义该类的一系列对象.比如说有以下一个模板 人类: 有姓名: ...
- The C++ Programming Language 学习笔记 第四章 类型和声明
1.关于main 函数中的 return 0 C99标准中,main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的激活者(如操作系统).如果 main 函数的最后没有写 return ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十四章:曲面细分阶段
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十四章:曲面细分阶段 代码工程地址: https://github. ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化 学习目标 对Direct 3D编程在 ...
- 第四章 跨平台图像显示库——SDL 第一节 与SDL第一次亲密接触
http://blog.csdn.net/visioncat/article/details/1596576 GCC for Win32 开发环境介绍(5) 第四章 跨平台图像显示库——SDL 第一节 ...
- 《Programming WPF》翻译 第8章 2.Timeline
原文:<Programming WPF>翻译 第8章 2.Timeline Timeline代表了时间的延伸.它通常还描述了一个或多个在这段时间所发生的事情.例如,在前面章节描述的动画类型 ...
- 《Programming WPF》翻译 第7章 3.笔刷和钢笔
原文:<Programming WPF>翻译 第7章 3.笔刷和钢笔 为了在屏幕上绘制一个图形,WPF需要知道你想要为图形填充什么颜色以及如何绘制它的边框.WPF提供了一些Brush类型支 ...
- 《Programming WPF》翻译 第7章 2.图形
原文:<Programming WPF>翻译 第7章 2.图形 图形时绘图的基础,代表用户界面树的元素.WPF支持多种不同的形状,并为它们每一个都提供了元素类型. 7.2.1基本图形类 在 ...
- 《Programming WPF》翻译 第5章 5.数据模板和样式
原文:<Programming WPF>翻译 第5章 5.数据模板和样式 让我们想象一下我们想要实现TTT更有娱乐性的一个版本(这是大部分游戏中最重要的特色).例如,TTT的一种变体允许玩 ...
随机推荐
- C++求两个数的最大值
//不使用if,:?等推断语句.求两个数字中最大的那个数字. #include<iostream> using namespace std; int main() { int a = -1 ...
- Python isdecimal() 方法
描述 Python isdecimal() 方法检查字符串是否只包含十进制字符.这种方法只存在于unicode对象. 注意:定义一个十进制字符串,只需要在字符串前添加 'u' 前缀即可. 语法 isd ...
- 文本检测: CTPN
参考: https://zhuanlan.zhihu.com/p/37363942 https://zhuanlan.zhihu.com/p/34757009 https://zhuanlan.zhi ...
- 缓存server设计与实现(五)
上次讲到lru与缓存重建,这次主要讲一下关于过期处理的一些主要问题. 在讨论这个问题之前,有个相关的问题须要大家有所了解. 就是对于一个缓存如期仅仅来说,什么东西应该缓存,什么不应该缓存.这是一个比較 ...
- iOS 关于图片地理位置隐私信息的分析和读取
今天突然想到微信朋友圈发照片,涉及个人隐私的地理位置是否外泄.因为iphone拍照的照片都会带有地理位置等信息,我们先来实现怎么读取里面的安全信息,然后再来分析 #import "ViewC ...
- C++函数默认参数(转)
在代码中使用到了函数的默认参数,在函数的定义和实现中都填写的默认参数,结果出现了错误: 代码: #ifndef FIRSTPAGE_H #define FIRSTPAGE_H #include < ...
- malloc,我误解你了
malloc用于动态申请内存,这个学过C语言的都知道.忘记了在哪本书上看到,malloc申请的内存不一定是连续,于是一直记住了.这句话有错吗?没有!但是当时只是记住了这个知识点,而没有深入的思考.直到 ...
- phan—php语法静态检查在windows下的配置
php7推出了语法树,于是静态语法分析更方便了.(可以直接下载我配置好的,传送门百度网盘) 1.先安装php7,到http://windows.php.net/下载php7带openssl的. 2.修 ...
- 进一步优化SPA的首屏打开速度(模块化与懒载入) by 嗡
前言 单页应用的优点在于一次载入全部页面资源,利用本地计算能力渲染页面.提高页面切换速度与用户体验.但缺点在于全部页面资源将被一次性下载完,此时封装出来的静态资源包体积较大,使得第一次打开SPA页面时 ...
- 数字集成电路设计-14-DPI
引言 在进行IC验证时,尤其是规模较大的时候,单纯用Verilog和SV来构建testbench.可能会稍显吃力. 在这样的情况下,使用C或者C++等软件语言往往会大大加快验证速度,提高验证效率. P ...
