------<a href="http://www.itheima.com"target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流
autorlease注意及错误用法
autorelease的作用:把对象加入到自动释放池中,延迟对象的释放
使用注意:
int main(){
Person *p=[Person new];
//自动释放池
@autoreleasepool{
//1、并不是所有的放到自动释放池中的代码,产生的对象就会自动释放 如果需要释放,必须加入到自动释放池
// Person *p=[[Person new] autorelease];
//如果对象调用了autorelease,但是调用autorelease的时候,没有在任何一个自动释放池中,此时该对象也不会被加入到自动释放池
[p autorelease];
}
//我们只需要在自动释放池代码块中调用autorelease就可以把对象加入到自动释放池中
//Person *p=[[Person new] autorelease];
return 0;
}
@autoreleasepool的嵌套:
自动释放池的栈结构(数据结构)和内存的栈区是不一样的
对象存在位于栈顶位置的自动释放池中(栈区是先进后出式的)
[p autorelease];这样一次其实就是释放了一次,计数器就会减1
自动释放池中不宜放占用内存比较大的对象
千万不要把大量循环操作放到同一个@autorelease中,这样会造成内存峰值的上升
int main(){
@autoreleasepool{
@autoreleasepool{
@autoreleasepool{
[p autorelease];
}
}
}
return 0;
}
autorelease错误用法:
1、连续调用多次autorelease,释放池销毁时执行两次release
2、ALLOC之后调用了autorelease,之后又调用了release。
id instancetype
instancetype可以智能的帮我们判断赋值的指针变量的类型和方法的返回值
类型是否一致,不一致的话给个警告
ARC:
指针的分类
1、强指针:默认的情况下,所以的指针都是强指针,关键字strong
2、弱指针: weak关键字修饰的弱指针
声明一个弱指针如下:
weak Person *p
什么事ARC:
自动引用计数器,即ARC,当ARC开启的时候,编译器将自动在代码合适的地方
插入retain,release和autorelease,而作为开发者就不用考虑编译器会报错了。
ARC:编译器特性:“垃圾回收”运行时特性
ARC工作原理及判断准则:
ARC是Objective-C编译器的特性,而不是运行时特性或者垃圾回收机制,
ARC所做的只不过是在代码编译时为我们自动在核实的位置插入release或
ARC的判断准则:
只要没有强指针指向对象,对象就会被释放。
注意:当使用ARC的时候,暂时忘记“引用计数器”,因为判断标准变了
ARC机制下特点:
1、判断是否是ARC机制
查看项目信息 不能使用retain,release,autorelease,retainCount
在dealloc方法中不能使用[super dealloc];
使用:
正常创建对象,不用手动释放对象
ARC下单对象内存管理:
1、ARC下单对象内存管理
2、强弱指针
在ARC下@property set方法参数
原子性、读写和MRC下是一样的
MRC ARC
assign assign
retain strong(强指针)OC其它对象 weak(弱指针)UI控件
copy copy
ARC使用特点及其注意事项:
1、不允许调用release,retain,retainCount
2、允许重写dealloc但是不允许调用[super dealloc]
ARC中,只要弱指针指向的对象不在了,就直接把弱指针做清空(赋值为nil)
weak Person*p=[[Person alloc] init]//不合理,对象一创建出来就被释放掉
对象释放掉以后,ARC把指针设置为nil
ARC的兼容和转换
1、ARC模式下如何兼容非ARC的类
让程序兼容ARC和非ARC部分。转变为非ARC -fno-objc-arc转变为ARC的,-f-objc-arc.
把ARC兼容MRC的,输入-f-objc-arc
分类(Gategory)的概念
Gategory有很多种翻译:分类、类别、类目(一般叫分类)
Gategory是OC特有的语法,其他语言没有的语法
分类的作用
在不修改原有的类的基础上增加新的方法
一个庞大的类可以分模块开发
一个庞大的类可以由多个人来编写,更有利于团队合作
使用分类的目的
1、对现有类进行扩展:
比如:你可以扩展Cocoa touch框架中的类,你在类别中增加的方法会被子类所
继承,而且在运行时跟其他的方法没有区别
2、作为子类的替代手段
不需要定义和使用一个子类,你可以通过类别直接向已有的类里增加方法
3、对类中的方法归类:
利用category把一个庞大的类划分为小块来分别进行开发,从而更好的对类
中的方法进行更新维护
使用分类的步骤:
先声明分类--->实现分类--->使用分类
注意:分类的命名规则:类名+扩展方法,如“NSString+countNum”。
分类的借口声明与类的定义十分相似,但分类不继承父类,只需要带有一个括号,
表明该分类的主要用途
分类:
一些方法的声明和实现
作用:在不修改源代码的前提下,给类增加新的功能
使用格式:
//此处声明一个类:
@interface Person:NSObject
@end
//类的实现
@implementation Person
@end
声明一个分类:
@interface 待扩展的类名 (分类的名称)
@end
Person+base ---->分类文件的命名规则
eat run
如:
int main(){
@autoreleasepool{
@autoreleasepool{
@autoreleasepool{
[p autorelease];
}
}
}
return 0;
}
实现这个分类:
格式:
@implementation 待扩展的类名 (分类的名称)
@end
如:
@implementation Person (base)
//吃
-(void)eat{
NSLog(@"人会吃");
}
//跑
-(void) run{
NSLog(@"人会跑");
}
使用分类中的方法:
和使用类中原有的对象方法一样
但是需要把头文件包含过来
Person *p=[Person new];
[p xxx];
分类的使用注意事项:
1、分类只能增加方法,不能增加成员变量,@property(可能编译不会报错,但是运行有问题)
2、分类可以访问原来类中的成员变量
3、如果分类和原来类出现同名的方法,优先调用分类中的方法,原来类中的方法会被忽略
4、当在多个类别中有同名的方法的时候,这时候,执行的最后编译的那个类别的方法
分类的非正式协议
非正式协议的概念:
非正式协议通常定义为NSObject类别
所谓非正式协议就是类别,即凡是NSObject或者其子类Foundation框架中的类增加的类别,都是非正式协议
charaterAtIndex取得字符串对应位置的字符
@implementation NSString (countNum)
NSLog(@"self=%@",self);
int count=0
for(int i=0;i<self;i++){
unichar ch=[self charaterAtIndex:i]
if(ch>='0'&&'9'){
count++;
}
}
NSLog(@"%@字符串中有%d个数字"self,count);
@end
分类的延展
概念:延展类别又称为扩展(Extendsion)
扩展是分类的一个特例,括号里面为空就是扩展,新添加的方法一定要予以实现(分类里没有这个限制)
@implementation NSString ()
这种写法的类别叫匿名类别,又叫类扩展,所谓类的扩展,其实就是为一个类添加
额外的原来没有的变量、方法或者属性。
延展的特点:
1、可以在延展中定义实例变量
2、不能使用@implementation 类名() 实现类别的方法
3、可以定义私有的变量和方法
Block:
定义一个无参无返回值的block变量,并且赋值了:
void (^block变量名)()=^(){
代码块语句;
};
//优化:
void (^block变量名)()={
代码块语句;
};
//block变量的使用:
block变量名();
void (^MyBlock4)()=^(){
NSLog(@"xxx");
};
//使用block变量
myBlock4();
return 0;
有参无返回值:
格式:
void(^变量名)(参数类型及个数)=^(形参列表){
代码块语句;
};
实例:
//定义一个变量myblock2同时进行赋值
void (^myblock2)(int ,int )=^(int a,int b){
NSLog(@"a+b",a+b);
}
myblock2(34,12);
myblock2=^(int x,int y){
int m=x>y ?x:y;
NSLog(@"max=%d",m);
};
myblock2(34,12);
有参有返回值:
格式:
返回值类型 (^变量名)(参数类型及个数)=^(形参列表){
代码块语句;
return ;
}
int(^myblock1)(int ,int )=^(int x,int y){
return x+y;
};
int sum =myblock(10,20);
NSLog(@"sum=%d",sum);
//给变量重新赋值
myblock1=^(int x,int y){
reyurn x*y;
}
sum=myblock(10,20);
NSLog(@"sum=%d",sum);