6.理解“属性”这一概念
原子性
- nonatomic:效率高
atomic:默认
读写
- readwrite:默认
- readonly
内存管理
assign:默认
1.简单赋值
2.基础数据类型(NSInteger、CGFloat)和C数据类型(int,float,double,char)
3.不更改引用计数retain:引用计数加1
copy:建立引用计数=1的对象,释放旧对象
strong:拥有关系
设置新值时,先保留新值,释放旧值,再设置新值,类似retainweak:非拥有关系
1.设置新值时,不保留新值,不释放旧值,类似assign
2.对象释放时,属性值会变成nilunsafe_unretained:非拥有关系
1.类似assign,适用对象类型
2.目标对象释放后,属性值不会自动清空,不安全
7.在对象内部尽量直接访问实例变量
- 速度快
- 不会调用“设置方法”
- 不会触发KVO
- 不方便查错
<pre><code>
-(void)example7{
pr_obj(@"start");
for(int i=0 ;i<1000000;i++){
[self example7_set];
[self example7_get];
}
pr_obj(@"end");
pr_obj(@"dotMethod_start");
for(int i=0 ;i<1000000;i++){
[self example7_set_dotMethod];
[self example7_get_dotMethod];
}
pr_obj(@"dotMethod_end");
}
-(void)example7_set_dotMethod{
self.dotMethod_arr = @[@"aaaa"];
}
-(NSArray *)example7_get_dotMethod{
return self.dotMethod_arr;
}
-(void)example7_set{
_arr = @[@"aaaa"];
}
-(NSArray *)example7_get{
return _arr;
}
</pre></code>
结果:
直接访问方式:691-410 = 281ms
点方法访问方式:1017-691 = 326ms
折中方案:写入实例变量时,通过“设置方法”;读取实例变量时,直接访问
提高读取速度
控制对属性的写入操作
8.理解“对象等同性”这一概念
==:比较指针本身
isEqual:比较两个对象
isEqualToString:速度更快
相同的对象有相同的hash码,但hash码相同对象未必相同
<pre><code>
-(void)example8_equal{
NSString *str1 = @"str1:123";
NSString *str2 = [NSString stringWithFormat:@"str1:%i",123];
BOOL equalA = (str1 == str2);
BOOL equalB = [str1 isEqualToString:str2];
BOOL equalC = [str1 isEqual:str2];
pr_int(equalA);
pr_int(equalB);
pr_int(equalC);
pr_int([str1 hash]);
pr_int([str2 hash]);
}
</pre></code>
结果:
<pre><code>
-(void)example8_set{
NSMutableSet *set = [NSMutableSet new];
NSMutableArray *arrayA = [@[@1,@2] mutableCopy];
[set addObject:arrayA];
pr_obj(set);
NSMutableArray *arrayB = [@[@1,@2] mutableCopy];
[set addObject:arrayB];
pr_obj(set);
NSMutableArray *arrayC = [@[@1] mutableCopy];
[set addObject:arrayC];
pr_obj(set);
[arrayC addObject:@2];
pr_obj(set);
NSSet *setB = [set copy];
pr_obj(setB);
}
</pre></code>
结果:
9.以“类族模式”隐藏实现细节
把实现细节隐藏在简单的公共接口后面
Employee:
<pre><code>
import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger,EmployeeType) {
EmployeeTypeDeveloper,
EmployeeTypeProducter,
EmployeeTypeTester
};
@interface Employee : NSObject
+(Employee *)employeeWithType:(EmployeeType)type;
-(void)doWork;
@end
import "Employee.h"
import "EmployeeTester.h"
import "EmployeeDeveloper.h"
import "EmployeeProducter.h"
@implementation Employee
+(Employee *)employeeWithType:(EmployeeType)type{
switch (type) {
case EmployeeTypeTester:
return [EmployeeTester new];
break;
case EmployeeTypeDeveloper:
return [EmployeeDeveloper new];
break;
case EmployeeTypeProducter:
return [EmployeeProducter new];
break;
}
}
-(void)doWork{
}
@end
</pre></code>
EmployeeDeveloper:
<pre><code>
import "Employee.h"
@interface EmployeeDeveloper : Employee
@end
import "EmployeeDeveloper.h"
@implementation EmployeeDeveloper
-(void)doWork{
pr_obj(@"do developer's work");
}
@end
</pre></code>
实现:
<pre><code>
-(void)example9{
Employee *developer = [Employee employeeWithType:EmployeeTypeDeveloper];
[developer doWork];
BOOL isMember = [developer isMemberOfClass:[Employee class]];
pr_int(isMember);
BOOL isKind = [developer isKindOfClass:[Employee class]];
pr_int(isKind);
}
</pre></code>
结果:
10.在既有类中使用关联对象存放自定义数据
可以通过“关联对象”机制来把两个对象连接起来
但不建议使用,也许会产生循环引用
objc_getAssociatedObject
objc_setAssociatedObject
正常方式:
<pre><code>
-(void)alertView{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@""
message:@"message" delegate:self cancelButtonTitle:@"cancle" otherButtonTitles:@"ok",
nil];
[alertView show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:
(NSInteger)buttonIndex{
if(buttonIndex ==0){
pr_obj(@"cancle");
}else if (buttonIndex ==1){
pr_obj(@"ok");
}
}
</pre></code>
关联对象方式:
<pre><code>
-(void)alertViewWithBlock{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@""
message:@"message" delegate:self cancelButtonTitle:@"cancle" otherButtonTitles:@"ok",
nil];
void (^block)(NSInteger) = ^(NSInteger buttonIndex){
if(buttonIndex ==0){
pr_obj(@"cancle");
}else if (buttonIndex ==1){
pr_obj(@"ok");
}
};
objc_setAssociatedObject(alertView, @"alertViewKey", block,
OBJC_ASSOCIATION_COPY);
[alertView show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, @"alertViewKey");
block(buttonIndex);
}
</pre></code>