OC+2-ARC-Category-block

来源:互联网 发布:带数据统计的二维码 编辑:程序博客网 时间:2024/05/29 06:56
ARC概念及原理
1、指针分类
     1)强指针:默认下,所有的指针都是强指针,关键字strong
     2)弱指针:__weak关键字修饰的指针 (两个下划线_之间没有空格,看似一条线
2、什么是ARC
     Automatic Reference Counting,自动引用计数。使用ARC,不需要用retain,release和autorelease等关键字,编译器会自动插入这些关键字,所以底层还是MRC实现的
     ARC与其他语言的“垃圾回收”机制不同:1)ARC:编译器特性
                                                                      2)垃圾回收:运行时特性
3、ARC工作原理及判断准则
原理:ARC是OC得编译器特性,不是运行时特性或垃圾回收机制,ARC做的只不过是在代码编译时为你自动在核实的位置插入release或autorelease
ARC的判断准则:只要没有强指针指向对象,对象就会被释放
                     注意:当时使用ARC时,要暂时忘记“引用计数器”(retainCount),因为判断的标准变了

ARC下,循环引用问题:一端使用weak,一端使用strong

在ARC下,@property的set方法参数
没有retain,使用weak和strong
1、原子性和读写,和MRC下一样
2、MRC                ARC
     assign               assign
     retain               strong(强指针)weak(弱指针)
     copy               copy
一般在UI控件使用weak,其他OC对象用strong

ARC特点总结
1、不允许调用release,retain和retainCount
2、允许重写dealloc方法,但不允许调用[super dealloc];
3、@property的set方法参数
     OC对象:strong相当于retain
                    weak相当于assign
     非OC对象(基本类型):assign
ARC注意事项
1、ARC中,只要弱指针指向的对象不在了,就直接把弱指针左清空(赋值为nil)操作
2、__weak Person *p = [Person new];// 不合理,对象一创建就被释放掉,对象释放之后,指针设置为nil

ARC的兼容和转换
1、ARC模式下如何兼容非ARC的类
TARGETS-》Build Phases-》Compile sources-》选择MRC的类,双击-》写入参数-fno-objc-arc
转变为非ARC:-fno-objc-arc
转变为ARC:-f-objc-arc

2、MRC转换ARC
Edit->Refactor->Convert to object-c ARC->choose targets->左边ARC  右边MRC  对比->save

分类(Category)概念及使用流程
1、分类的概念及作用
category有很多翻译:分类、类别、类目
OC特有的语法,其他语言没有的语法
分类的作用:1)在不修改原有类的基础上增加新的方法
                    2)一个庞大的类可以分模块开发
                     3)一个庞大的类可以由多个人来编写,更有利于团队合作
使用分类的目的:1)对现有类进行扩展:
                                   比如,你可以扩展Cocoa touch框架的类,你在类别中增加的方法会被子类多继承,而且在运行时跟
                                    其他的方法没有区别
                              2)作为子类的替代手段:
                                   不需要定义和使用一个子类
                              3)对类中的方法归类:
                                   利用category把一个庞大的类划分为小块来分别进行开发,从而更好地对类的方法进行更新和维护
使用分类的步骤:先声明分类》实现分类》使用分类
注意
1)分类的命名规则:类名+扩展方法
2)分类的接口声明与类的定义十分相似,但分类不继承父类,只需要带一个括号,表明该分类的主要用途

2、分类的声明和实现
使用步骤:
     1)声明一个分类
          格式:@interface  待扩展的类名 (分类的名称)
                     @end
//Person类增加新的方法
@interfacePerson (base)
//
-(void) eat;
//
-(void) run;
@end
     2)实现这个分类
          格式:@implementation 待扩展的类 (分类的名称)
                     @end
//Person类新增方法的实现
@implementationPerson (base)
//
-(void) eat
{
   NSLog(@"");
}
//
-(void) run
{
   NSLog(@"");
}
@end
     3)使用分类中的方法
           和类的一模一样

创建分类category文件,实现多人开发:new File->Object-C File->File:分类名称
                                                                                type:category
                                                                                class:待扩展的类

3、分类的注意事项
     1)分类只能增加方法,不能增加成员变量、@property
     2)分类的方法中可以访问原来的成员变量
     3)在分类中存在和类中同名的方法,优先访问分类
     4)在多个类别中,有同名的方法时,执行的是最后编译的哪个类别的同名方法(在Compile sources里面看,可以改变编译顺序
          分类 > 原类
          最后编译的 >  分类

分类(category)非正式协议
非正式协议:通常定义为Foundation中NSObject类或它的子类的类别,本质上是类别
characterAtIndex方法: 取得字符串对应位置的字符,返回的是unichar类型
1、传一个字符串
-(void)countNum:(NSString*) str {
   
//计数
   
int count = 0;
   
//循环控制
   
for (int i = 0; i < str.length; i++) {
       
//取得字符串的每一个字符  unichar类型
       
unichar ch = [str characterAtIndex:i];
       
//使用‘’,判断是否是阿拉伯数字
       
if (ch >= '0' && ch <= '9') {
           
            count++;
        }
    }
   
NSLog(@"字符串%@%d个数字", str, count);
}
2、使用self,更简洁
-(void)countNum {
   
//计数
   
int count = 0;
   
//循环控制
   
for (int i = 0; i <self.length; i++) {
       
//取得字符串的每一个字符  unichar类型
       
unichar ch = [self characterAtIndex:i];
       
//使用‘’,判断是否是阿拉伯数字
       
if (ch >= '0' && ch <= '9') {
           
            count++;
        }
    }
   
NSLog(@"字符串%@%d个数字",self, count);
}

分类(category)的延展
延展类别又称为扩展(Extendsion),Extendsion是category的一个特例
其名字为匿名(为空),并且新添加的方法一定要予以实现(category没有这个限制)。
@interface XXX ()
{
     //增加的变量等
}
@end
这种写法的类别叫匿名类别,又叫扩展。所为扩展,就是为一个类增加原来没有的比那两、方法或者合成属性。
//类的延展/扩展/延展分类
//特点:
//1)可以在延展中,增加变量
//2)不可以在@implementation类名() --->实现匿名类别的方法,在类的实现中去实现
//3)可以直接将匿名类别放在.m文件中,实现新增方法的相对私有化,但是引入头文件,依旧可以使用
//4)可以在new File->Object-C File->File:新增的方法名
//                                typeExtendsion
//                                class:待扩展的类
//以后不管是实现还是使用直接调用头文件,相对私有化(在自身类,不在子类或其它类)
@interfacePerson ()//匿名,匿名类别
{
   
float _weight;
}
-(
void)run;
@end

类别和类扩展的区别
1、类扩展不仅可以增加方法,还可以增加实例变量,只是默认为私有类型的
2、新增的方法如不实现,类扩展会报警,而类别不会警告。类扩展是在编译阶段被加入到类中,而类别是运行时添加类中
3、不可以在@implementation类名() --->实现匿名类别的方法,在类的实现中去实现
4、在.m中的类扩展为私有的,在.h中的为共有的。类扩展是在.m文件中声明私有方法的一种非常好的方式


block的概念及基本使用
1、block的基本概念
用^操作符来声明一个block变量
block同函数一样,分为有参无返回值,有参有返回值,无参无返回值,无参有返回值
block定义格式:返回类型  (^block名)(参数类型及个数) = ^(形参列表){
                                                                                                   代码块
                                                                                                    // 当有返回值时,必须写return语句
                                                                                               };
                   参数类型及个数:可只声明类型
                    形参列表:必须写类型+参数名,当没有参数时,可省略此括号。
block使用格式:block名( );

block的typedef
1、函数指针
返回值类型 (*指针名)(形参列表)
技巧:1)把函数的声明拷贝过来
          2)把函数名替换为(*函数指针变量名)
          3)形参名可写可不写
用法:指针名 = 函数名;
函数指针别名:typedef  返回值类型(*别名)(形参列表);
                         别名    f1,f2;//f1,f2的实际类型就是 类型(*f1)(形参列表);

2、block的typedef
格式:typedef  返回值类型 (^新别名)(形参列表);
//block别名
       
typedef void (^myBlock)();
       
myBlock b1;
        b1 = ^{
           
NSLog(@"phantom");
        };
        b1();

3、block访问外部变量
1)可以访问,但是地址不一样
intm = 10;
       NSLog(@"m = %d", m);
       NSLog(@"m->addr = %p", &m);//栈区,高地址
       
       //当定义block的时候,block会把外部变量的值复制一份存放到block所在的内存中
       void (^block1)() = ^{
           NSLog(@"in block m = %d", m);//可以访问m的值
       NSLog(@"in block m->addr = %p", &m);//堆区,后六位改变;常量区,后四位
        };
       
        block1();
2)m的值不能被修改(m = 100;),以const的方式拷贝过去的。但是可以在代码块里,重新定义int m = 100;//栈区
3)block块内部变量是只读的,若加__block int m = 10;则可以在block块里重新赋值(m = 100;),然后不管在块内还是外部m的值都是100

注意:1)全局block:定义在函数外面的block是global;另外如果函数内部的block,但是没有捕获任何自动变量,那么也是全局的
     2)栈block:是否引用了外部变量
     3)堆block:则是对栈block copy而来。对全局block copy不会起任何作用,返回的依然是全局block

4、block应用
1)block可以作为函数参数,block类型的变量workBlock,则传递形式void (^workBlock)()
2)block作为函数返回值:1、使用typedef给block定义新的类型
                    2、用新定义的类型作为函数返回值
                    3、定义block变量接受函数返回的结果
                    4、执行block
#import<Foundation/Foundation.h>

typedefvoid (^newBlock)();//重新定义新的类型

newBlock test() {
   
newBlock w1 = ^{
       
NSLog(@"XXX");
    };
   return w1;//返回w1
}
int main(int argc, const char * argv[]) {
   @autoreleasepool {
       newBlock n1 = test();//n1接收得w1
        n1();   //执行w1 
    }
   
return 0;
}

5、block的使用技巧
1)助记符:inlineBlock
2)创建自己的助记符,{},<##>,删除delete
3)可以在形参部分,加上参数名称,方便下面调用
0 0
原创粉丝点击