Arc(Atuomatic Reference Counting)
(自动化的 引用 计数)
1,基本简介
ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入
适当的retain、release、autorelease语句。你不再需要担心内存管理,因为编译器为你处理了一切
ARC 是编译器特性,而不是 iOS 运行时特性,它也不是类似于其它语言中的垃圾收集器。因此 ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化
2,ARC的判断准则:只要没有强指针指向对象,就会释放对象。只要还有一个强指针变量指向对象,对象就会保持在内存中
3. 强指针和弱指针
强指针:默认情况下所有指针都是Strong指针 __strong(两个下划线)
弱指针:指向的对象被回收后,弱指针会自动变为nil指针,不会引发野指针错误 __weak;
4.ARC特点
1> 不允许调用release、retain、retainCount
2> 允许重写dealloc,但是不允许调用[super dealloc]
3> @property的参数
* strong :成员变量是强指针(适用于OC对象类型)想长期拥有某个对象,应该用strong
* weak :成员变量是弱指针(适用于OC对象类型)其他对象用weak。
* assign : 适用于非OC对象类型
4>以前的retain改为用strong,其他一切不变
代码示例:
@interface Person : NSObject
@property (nonatomic, strong) Dog *dog;//strong相当于retain
@property (nonatomic, weak) Dog *dog;//
@end
int main()
{
Person *p = [[Person alloc] init];
Dog *d = [[Dog alloc] init];
p.dog = d;
d = nil;
NSLog(@"%@", p);//当strong的时候狗p还在,weak就消除了
return 0;
}
void test()
{
Person *p = [[Person alloc] init];
/* __weak Person *p = [[Person alloc] init];
弱指针自动释放
NSLog(@"%@", p);//输出是NULL
*/
__weak Person *p2 = p;
p = nil;//这行自动释放对象内存
p2 = nil;
NSLog(@"----");
}
Xcode的ARC转换功能
Edit里面的Refactor(重构)里面的Convert(转换) to Object-C ARC
怎样查看项目是不是ARC呢?
点击项目,Bulid Settings,然后搜索Auto,出现 Object-C ARC后面是Yes
当我们使用第三方框架的时候,非ARC的release报错,怎样既可以有ARC又有非ARC呢
Bulid Phases/Compile Sources/想使用非ARC的项目文件,然后双击或者回车。输入-fno-objc-arc
使用ARC的命令:-f-objc-arc
循环引用
两端互相引用时,
1》 ARC
一端用strong、一端用weak
2》非ARC
一端用retain、一端用assign
@interface Person :NSObject
//@peroperty (nonatomic, strong) Dog *dog;
@peroperty (nonatomic, weak) Dog *dog;
@end
@implementation Person
-(void)dealloc
{
NSLog(@"Person is dealloc");
}
@end
@interface Dog :NSObject
@peroperty (nonatomic, strong) Person *person;
@end
@implementation Dog
-(void)dealloc
{
NSLog(@"Dog is dealloc");
}
@end
int main()
{
Person *p = [[Person alloc] init];
Dog *d = [[Dog alloc] init];
p.dog = d;
d.person = p;
return 0;
}
Block
Block封装了一段代码,可以在任何时候执行(程序运行时进行)
/*
block需要掌握:
1> 如何定义Block变量
int (^sumBlock)(int, int);
void (^myBlock)();
2> 如何利用Block封装代码
^(int a, int b){
return a - b;
}
^() {
NSLog();
}
^ {
NSLog();
}
3> block访问外面变量
*block内部可以访问外面的变量
*默认情况下,block内部不能修改外面的局部变量
*给局部变量加上 __block关键字,这个局部变量就可以在block内部修改
4》利用typedef定义block类型
typedef int (^myBlock)(int,int);
//以后就可以利用MyBlock这种类型来定义block变量
MyBlock b1;
b1 = ^(int a, int b){
return a - b;
}
MyBlock b1,b2;
MyBlock b1 = ^(int a, int b){
return a - b;
};//千万不要忘记写分号,赋值语句后面要写。
*/
//typedef int (*SumP)(int, int);
typedef ^int (^MyBlock)(int, int);
int main()
{
//int (*p)(int, int) = sum;
//int (*p2)(int, int) = sum;
//SumP p = sum;
MyBlock sumblock = ^(int a, int b){
return a + b;
}
MyBlock minusBlock = ^(int a, int b){
return a - b;
}
MyBlock multiplyBlock = ^(int a, int b){
return a * b;
}
// MyBlock() 典型的错误,MyBlock是类型,不是变量
return 0;
}
//没有返回值。没有形参的block
void test()
{
// block 用来保存一段代码,是个数据类型
// block的标志:^
/*
block跟函数很像:
1,可以保存代码
2. 有返回值
3. 有形参
4.调用方式一样
*/
// 定义block变量,如果block没有形参,可以省略后面的()
void (^myblock)() = ^{
NSLog(@"--------");
NSLog(@"--------");
}
//利用block变量调用block内部代码
myblock();
}
//有返回值。有形参的block
void test2()
{
/*
//指向函数的指针
int (*p)(int, int) = sum;
int d = p(10,20);
NSLog(@"%d", d);
*/
int (^sumblock)(int, int) = ^(int a, int b){
return a + b;
}
int c = sumblock(10,11);
NSLog(@"%d",c);
// 用一个block输出N条横线
void (^lineBlock)(int) = ^(int n)
{
for (int i=0; i<n; i++)
{
NSLog(@"--------");
}
}
int d = lineBlock(5);
}
void test3()
{
int a =10;
__block int b =20;
void (^block)();
block = ^{
// block内部可以访问外面的变量
// 默认情况下,block内部不能修改外面的局部变量
// a = 20;
// 给局部变量加上 __block关键字,这个局部变量就可以在block内部修改
b = 25;
}
Protocol(协议)
1.基本用途
可以用来声明一大堆方法(不能声明成员变量)
只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明
只要父类遵守了某个协议,就相当于子类也遵守了
// : 继承
// <> 遵守协议
@protocol MyProtocol2;
@protocol MyProtocol3;
@interface Person : NSObject<Myprotocol,Myprotoco2>
// 继承是单继承,一个协议可以遵守其他多个协议。
@property (nonatomic, strong) id<Myprotocol2> obj;
// @property (nonatomic, strong) Hashiqi *dog;如同这句要有哈士奇狗,必须import头文件。所以要声明个@class Hashiqi,我们用协议也用类似的声明,避免COPY大量头文件
@end
@implementation Person
- (void)test
{
}
- (void)test2
{
}
- (void)haha1
{
}
- (void)hehe
{
}
@end
#import "MyProtocol2"
@interface Dog :NSObject <MyProtocol2>
@end
@implementation Dog
@end
@interface HaShiQi: Dog
@end
@implementation HaShiQi
@end
@protocol Myprotocol <NSObject>
//required ,optional在大多数情况下,用途在于程序员之间的交流
- (void)test3;//默认是required
@required// 要求实现,不实现就会发出警告
- (void)test;
@optional// 可选,不要求必须实现
- (void)test2;
@end
@protocol Myprotocol2 <NSObject>
- (void)haha1;
@optional
- (void)haha2;
@end
#import "MyProtocol.h"
// 一个协议遵守了其他协议,就相当于拥有了其他协议中的方法声明
@protocol MyProtocol3 <MyProtocol>
- (void)hehe;
@end
NSObject是一个基协议,最根本最基本的协议,他声明在Foundation框架里。
NSObject协议中声明很多最基本的方法,比如description、retain、release等。建议每个新的协议都要遵守NSObject协议
#import "MyProtocol.h"
#import "Person.h"
int main()
{
Perosn *p = [[Person alloc]init];
p.obj = [[Dog alloc] init];
p.obj = [[HaShiQi alloc] init];
return 0;
}
void (test)
{
NSObject *obj = @"l564sd";//多态,父类指针指向子类对象
// 要求obj3保存的对象必须是遵守MyProtocol这个协议的
/*NSObject<MyProtocol> *obj2 = [[NSObject alloc] init];这句话是错误的,因为前面是遵守协议的,后面的NSObject对象是不遵守MyProtocol协议的。这是不允许的*/
NSObject<MyProtocol> *obj2 = [[Person alloc] init];
obj2 = nil;
id<MyProtocol> *obj3 = [[Person alloc] init];
obj3 = nil;// 假如没有这句会有一个指针未使用的警告,但是不是上面类型错误了。
// 要求obj4,保存的对象必须遵守MyProtocol3.并且继承了Person
Person<MyProtocol3> *obj4 = [[Person alloc] init];
}
协议的总结
1.协议的定义
@protocol 协议名称 <NSObject>
// 方法声明列表....
@end
2.如何遵守协议
1> 类遵守协议
@interface 类名 : 父类名 <协议名称1, 协议名称2>
@end
2> 协议遵守协议
@protocol 协议名称 <其他协议名称1, 其他协议名称2>
@end
3.协议中方法声明的关键字
1> @required (默认)
要求实现,如果没有实现,会发出警告
2> @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文件中,也可用定义在某个类中
1> 如果这个协议只用在某个类中,应该把协议定义在该类中
2> 如果这个协议用在很多类中,就应该定义在单独文件中
7.分类可用定义在单独.h和.m文件中,也可用定义在原来类中
1> 一般情况下,都是定义在单独文件
2> 定义在原来类中的分类,只要求能看懂语法
代理设计模式
设计原理
有些麻烦的事情不想自己亲自做,就可以找个人帮忙做,即交给代理对象去做
设计原则
首先得拥有某个代理对象属性
其次要很清楚代理有哪些方法
最后要保证能解耦
实现方案
定义一个protocol,在其中声明一些和代理沟通的方法
拥有一个代理属性id<protocol> delegate
让代理遵守protocol
---------------------- ASP.Net+Unity开发、 .Net培训、期待与您交流! ----------------------详细请查看: www.itheima.com