您的位置:首页 > 移动开发 > Objective-C

iOS-Effective Objective-C 2.0 读书笔记(二)

2016-04-24 15:52 411 查看
哈哈,上一篇可以参考iOS-Effective Objective-C 2.0 读书笔记(一)。这一章主要是涉及对象、消息和运行期的一些相关特性。

第7条 在对象的内部尽量直接访问实例变量

  我们都知道使用了属性之后,可以通过存取方法来访问相关实例变量,也可以直接访问实例变量。如下所示:

@property (noatnomic, copy) NSString *userName

//直接访问
_userName = @"lysongzi";

//存取方法访问
self.userName = @"lysongzi";


然而这两种方式是有区别的。

由于不经过OC的“消息分发”步骤,所以直接访问实例变量的速度当然比较快。在这种情况下,编译器所生成的代码会直接访问保存对象实例变量的那块内存。

直接访问实例变量时,不会调用其setter方法,这就绕过了为属性定义的和“内存管理”相关的语义设置。比如说,如果在ARC下直接访问一个声明为copy的属性,那么并不会拷贝该属性,只会保留新值并释放旧值。

如果直接访问实例变量,那么不会触发KVO通知(这个KVO实现机制有关,参考iOS-KVC-KVO学习).这样做可能会产生安全问题,这还是要取决于具体的对象行为。

通过属性来访问有助于排查与之相关的错误,因为可以给setter或getter方法中添加断电,监控该属性的调用者及其调用时间。

  然后以下是作者给出的合适选择何种方式访问实例变量。大家参考参考就好,主要还是要取决与具体的需要把我觉得。

读取实例变量值,采用直接访问实例变量的方式。

设置实例变量值,采用
setter
方式设置新值。

一般情况下,在
init
方法中采用直接访问实例变量的方式。

在特殊情况下,比如说待初始化的实例变量声明在超类中,而我们又无法在子类中直接访问该实例变量时,就需要调用
setter
方法来设置新值了。

使用了
lazy initialization
的对象,使用getter/setter方式访问属性。

第9条 以”类族模式”隐藏实现的细节

  “类族模式”(class cluster)是一种很有用的模式,可以隐藏“抽象基类”背后的实现细节。比如iOS中UIKit库中的UIButton,提供了一个类方法,通过传入一个代表按钮类型的参数,已返回特定的UIButton对象实例。

  然而实际上一个类族是由多个从共同基类派生出来的子类组成的,由于他们派生自一个共同的抽象基类,所以他们都实现了同一套接口。

  在创建类族的方式中,最常用的方式就是使用“工厂方法”。(好吧这个问题面试时候被问过了,还好当时还记得工厂模式,非常幸运的蒙对了哈哈哈哈哈哈哈哈哈哈)下面我们举个简单的例子进行说明。

1.首先定义个抽象基类。

typedef NS_ENUM(NSUInteger, LYSEmployeeType)
{
LYSEmployeeTypeDeveloper,
LYSEmployeeTypeManager,
LYSEmployeeTypeDesigner
};

@interface LYSEmployee : NSObject
@property (copy) NSString *name;
@property NSInteger salary;

+ (LYSEmployee *)employeeWithType:(LYSEmployeeType)type;

- (void)doWork;

@end

@implementation LYSEmployee

+ (LYSEmployee *)employeeWithType:(LYSEmployeeType)type
{
switch (type)
{
case LYSEmployeeTypeDeveloper:
return [LYSEmployeeDeveloper new];
break;
case LYSEmployeeTypeDeveloper:
return [LYSEmployeeManager new];
break;
case LYSEmployeeTypeDeveloper:
return [LYSEmployeeDesigner new];
break;
}
}

- (void)doWork
{
//由子类来实现具体的接口操作
}

@end


2.然后每一个子类都继承自该基类,并实现其中定义的一些接口。

@interface LYSEmployeeDeveloper : NSObject
@end

@implementation LYSEmployeeDeveloper
- (void)doWork
{
[self writeCode];
}
@end


  OC中没办法指明某个基类是“抽象的”。于是,开发者通常会在文档中写明类的用法。(= =,我突然在想可不可以结合协议来模拟一个抽象基类,这样子可以把接口都放到协议中,然所有子类都遵循这个协议)。

第10条 在既有类中使用关联对象存放自定义数据

  额,这个的应用场景不好说明。这里主要就是简单介绍一下iOS中运行时的一个重要特性,就是关联对象。这个机制使得我们可以给某个对象关联许多其他对象,这些对象通过“键(key)”来区分。

  存取对象值时,可以指明“存取策略”,用以维护相应的“内存管理语义”。

OBJC_ASSOCIATION_ASSIGN             //assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC   //nonatomic, retain
OBJC_ASSOCIATION_COPY_NONATOMIC     //nonatomic, copy
OBJC_ASSOCIATION_RETAIN             //retain
OBJC_ASSOCIATION_COPY               //assign


iOS的运行时库中提供一下方法来管理关联对象。

//通过给定的键,给某对象关联一个对象值
//此方法可以通过给某个键设置一个nil的关联,可以看做是移除一个关联对象
void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy);

//通过给定的键,从某对象中获取关联对象值
id objc_getAssociatedObject(id object, void *key);

//移除指定对象的全部关联对象
void objc_removeAssociatedObjects(id object);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息