ARC
ARC概念
- Automatic Reference Counting :自动引用计数
ARC的判断准则
- 只要没有强指针指向对象,就会释放对象
- 指针分为两种
1、强指针:默认情况下,所有的指针都是强指针 _ _strong
2、弱指针:_ _weak
在ARC中使用@property,要注意的参数的使用
@property (nonatomic,strong) Dog *dog;
//而不用:@property (nonatomic,retain) Dog *dog;
ARC的特点
- 不允许调用release、retain、retainCount
- 允许重写dealloc,但不允许调用 [super dealloc]
- @property的参数
strong :成员变量是强指针(适用于oc对象类型)
weak :成员变量是弱指针(适用于oc对象类型)
assign :适用于非oc对象类型
ARC和非ARC兼容问题
- ARC兼容非ARC 在Compile Sources 里双击需要兼容的文件,输入:-fno-objc-arc
- 非ARC兼容ARC 在Compile Soueces 里双击需要兼容的文件,输入:-f-objc-arc
当两端循环引用的时候,解决方案
- ARC
一端用strong,另一端用weak - 非ARC
一端用retain,另一端用assign
block代码块
block的使用
- block用来保存一段代码,block的标志: ^
- block跟函数很像:
1、可以保存代码
2、有返回值
3、有形参
4、调用方式一样
//定义block变量
void (^myblock)() = ^(){ //这里因为无参数,所以 ^()可以省略()
NSLog(@"chenfanfang");
};
//利用block变量调用block内部的代码
myblock();
输出结果:
2015-03-24 21:04:20.422 oc知识点[5682:66957] chenfanfang
//定义一个有返回值,有参数的block变量
int (^sumblock)(int,int) = ^(int a,int b){
return a + b;
};
//调用
int sum = sumblock(10,5);
NSLog(@"sum=%d",sum);
输出结果:
2015-03-24 21:03:19.190 oc知识点[5645:66467] sum=15
block访问外面变量
- block内部可以访问外面的变量
- 默认情况下,block内部不能修改外面的局部变量
- 给局部变量加上 _ _block关键字,这个局部变量就可以在block内部修改
int __block a = 6;
// __block int a = 6; 这种写法也行,自己测试出来的
void (^myblock)() = ^(){
a = 5;
NSLog(@"a=%d",a);
};
myblock();
输出结果:
2015-03-24 21:09:25.449 oc知识点[5868:68803] a=5
block指针与函数指针
函数指针
#import <Foundation/Foundation.h>
int sum (int a,int b){
return a + b;
}
int main(int argc, const char * argv[]) {
//明显,这样子定义稍微麻烦,我们可以在开头用typedef,在下一个代码例子中用这种方法
int (*p) (int,int) = sum;
//用函数指针调用函数
int add = p(10,5);
NSLog(@"add=%d",add);
return 0;
}
输出结果:
2015-03-24 21:14:12.982 oc知识点[6027:70628] add=15
#import <Foundation/Foundation.h>
typedef int(*Sump) (int,int);
int sum (int a,int b){
return a + b;
}
int main(int argc, const char * argv[]) {
Sump p = sum;
//用函数指针调用函数
int add = p(10,5);
NSLog(@"add=%d",add);
return 0;
}
输出结果:
2015-03-24 21:19:58.143 oc知识点[6208:72797] add=15
block与函数指针定义类似
#import <Foundation/Foundation.h>
typedef int(^myblock) (int,int);
int main()
{
myblock sumblock = ^(int a,int b){
return a + b;
};
int result = sumblock(10,3);
NSLog(@"result=%d",result);
}
输出结果:
2015-03-25 16:45:23.808 oc知识点[1107:11143] result=13
协议(protocol)
协议与继承
//继承
: 继承父类
//协议
<> 遵守协议
protocol的格式
//协议的编写
@protocol 协议名称
方法申明列表
@end
//某个类遵守协议
@interface 类名 : 父类 <协议名称>
@end
protocol中的参数:@required和@optional
@protocol MyProtocol
@required //默认的参数是required
- (void)test1;
- (void)test2;
@optional
- (void)test3;
@end
//@required:要求实现,不实现就会发出警告(默认是这种方式)
//@optional:不一定要实现
protocol的基本用途
- 可以用来申明一大堆方法(不能申明成员变量)
- 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法申明
- 只要父类遵守了某个协议,就相当于子类也遵守了这个协议
遵守多个协议
一个类可以遵守多个协议,不同协议用逗号隔开
@interface 类名:NSObject <协议1 , 协议2 , 协议3>
@end
协议遵守协议
- 一个协议可以遵守其他多个协议,多个协议之间用逗号隔开
- 一个协议遵守了其他协议,就相当于拥有了其他协议中的方法申明
@protocol 协议名称 <协议1 , 协议2 , 协议3>
@end
基协议
- NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它
- 其实还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议
- NSObject协议中申明很多最基本的方法,比如 description、retain、release等
- 建议每个新的协议都要遵守NSObject协议
对象遵守协议
//要求obj保存的对象必须是遵守MyProtocol这个协议
NSObject <MyProtocol> *obj = [[NSObject alloc] init];
//要求obj保存的对象必须遵守MyProtocol,并且继承了Person这个类
Person <MyProtocol> *obj;
//背景:obj是Person类中的一个成员变量
//要求obj这个对象的类必须遵守MyProtocol这个协议
@property (nonatomic,strong) id<MyProtocol> obj;
//主函数中,类对象的创建
Person *p = [[Person alllc] init];
p.obj = [[Dog alloc] init];
//若Dog这个类没有遵守MyProtocol这个协议,就会警告
用@protocol申明协议的用法和@class类似
若真正需要用到协议中的内容时,则在类的实现文件中(.m文件中)#import “协议”
协议:ptrotocol总结
1、协议的定义
@protocol 协议的名称 <NSObject>
方法申明列表
@end
2、如何遵守协议
- 类遵守协议
@interface 类名 : 父类名 <协议名称1 , 协议名称2>
@end
- 协议遵守协议
@protocol 协议名称 <其他协议名称1 , 其他协议名称2>
@end
3、协议中方法申明的关键字
- @required (默认):要求实现,如果没有实现,会发出警告
- @optional :不要求实现,即不管有没有实现,都不会发出警告
4、定义一个变量的时候,限制这个变量保存的对象遵守某个协议
- 类名 <协议名称> *变量名
- id <协议名称> 变量名
例如:
NSObject <MyProtocol> *obj;
id <MyProtocol> obj2;
5、@property中申明的属性也可用一个遵守协议的限制
- @property (nonatomic,strong) 类名 <协议名称> *属性名
- @property (nonatomic,strong) id <协议名称> 属性名
例如:
@property (nonatomic,strong) Dog <MyProtocol> *dog;
@property (nonatomic,strong) id <MyProtocol> dog2;
6、协议可以定义在单独.h文件中,也可以定义在某个类的文件中
- 如果这个协议只用于某个类中,应该把该协议定义在该类中
- 如果这个协议用在很多类中,就应该定义在单独文件中
7、分类可以定义在单独.h和.m文件中,也可以定义在原来类中
- 一般情况下,都是定义在单独文件中
- 定义在原来类中的分类,只要求能看懂语法