A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

#pragma mark - 0_18 分类的使用注意 [掌握]

1.主线任务 - 分类的注意

分类文件的命名:

本类名+分类名.h

本类名+分类名.m



分类的使用注意:

    1.分类中不能添加成员变量,但是可以访问本类中的@interface中定义的成员变量,但是不能访问本类中私有的成员变量

    2.分类中使用@property会有什么效果?

    1.会生成对应的getter和setter的声明

    2.不会生成_开头的成员变量

    3.不会生成对应getter和setter的实现

    3.分类可以通过self调用本类的方法

    4.如果在本类中使用@property声明一个属性,那么在分类中不能访问对应的_成员变量,但是可以调用对应的setter和getter

    5.可以在分类中重写本类中同名的方法

    1.如果重写,编译器会有一个警告,提示在分类中实现了和本类中同名的方法

    2.一旦重写,不管是否引入分类的头文件,都会优先调用分类中该方法的实现

    6.如果在多个分类中同时重写了本类中的方法,那么会优先调用最后参与编译的分类中对该方法实现

    7.方法的调用顺序

    (最后参与编译的)分类 -> 本类 -> 父类


分类的总结:

    1.分类的作用:

        将1个类分成多个模块,方便维护和管理

    2.什么时候需要用到分类

        1.团队合作开发的时候,需要把一个非常庞大的类,分给多个人去写

        2.当1个类过于臃肿庞大的时候,可以拆分成多个小的模块

    3.分类的好处:

        将1个复杂的类,分成多个模块,方便维护


2.支线任务 - 关联对象

使用分类存在的问题:

    1.分类中不能添加成员变量

    2.如果是自定义的类,可以直接在本类中添加成员变量,然后在分类中使用

    3.如果是系统的类,想在分类中添加成员变量,如何做? -> 使用runtime中的关联对象


如何使用:

导入<objc/runtime.h>

// 设置关联对象

// object 说明给哪个对象添加关联对象

// key 说明通过key保存值

// value 保存的值

// policy 对于关联对象的内存管理策略

// 作用:把 self 和 对象 通过 key 关联在一起

void objc_setAssociatedObject(id object, const void *key, idvalue, objc_AssociationPolicy policy);


// 获取关联对象

// object 说明获取哪个对象的关联对象

// key 说明通过key获取值

// 作用:根据 key 获得和 self 相关联的 对象

id objc_getAssociatedObject(id object, const void *key);


4.关联对象的本质

    1.关联对象,并不是给对象真实增加一个成员变量,所以并没有在对象的堆区空间内,定义一个变量

    2.在调用该函数的时候,会在全局区保存关联对象的哈希表中,根据对象的地址,创建一个和该对象关联的哈希表,然后在该表中,根据key存储对指定的对象

    3.当对象释放的时候,系统会自动的处理和他关联的对象,不需要我们管理


#pragma mark - 0_19 非正式协议 [掌握]

非正式协议:给系统的类添加的分类叫做非正式协议

作用:给系统的类扩充新的方法


NSString + test

NSObject + test



#pragma mark - 02 延展的基本使用 [掌握]


1.延展是什么:  Extension

    1.延展是一个匿名的分类

    2.延展只有声明,没有单独的实现,和本类共享同一个实现


2.延展的声明

@interface HMPerson ()


@end


延展没有单独的实现.和本类共享1个实现

将方法声明写在延展中 将方法的实现写在本类的实现中.


3.延展的作用

    1.可以延展中添加成员变量

    2.延展中使用@property定义属性会做几件事情? (和在类的定义中使用@property是一样的)

4.添加1个延展

延展只有1个.h文件. 没有.m文件. 因为延展没有单独的实现.和本类共享1个实现.

100%的情况下,延展不会独占1个头文件. 延展都是写在类的.m文件中.



#pragma mark - 03 延展的使用场景 [掌握]


1.延展可以理解为类的私有声明

    1.在类的声明可以做的事情,在延展中都可以做

    2.写在延展中的成员变量和方法,只能当前类的内部访问,不能在外部访问

2.延展的最常见用法:

    定义私有的@property


3.在就业班以及工作中的使用

    1.给系统的类写分类

        1.分类的作用:在不修改和继承自一个类的基础上,给该类增加新的方法

        2.给系统的类写分类,扩展新的常用的必须的方法

        3.把一些频繁用到的功能,写成分类,多积累

    2.延展(类的私有扩展),在其中定义只希望在当前类的内部访问的成员变量和方法.


#pragma mark -4. 延展的使用注意.

    1).分类中只能新增方法.可以写@property但是只会生成getter setter的声明.

    2).延展中可以写属性.

       也可以写@property. 会自动的生成私有属性,getter setter的声明. getteer setter的实现.

       方法声明肯定也是可以的.

    3).

            延展天生就是来:私有化类的成员的.

        如果类中有成员需要被私有化.

        属性需要被私有化:

        a. 在本类的@interface中@private

        b. 在本类的@implementation中.

        c. 写在延展中.

         必须将其写在延展中.


        方法需要被私有化:只写实现不写声明.

        建议: 私有方法仍然要写声明和实现,只不过声明写在延展中.

        @property需要被私有化.把@property写在延展中.



#pragma mark - 04 block变量的声明 [掌握]


点招会考

就业班会用

找工作面试也会用

在实际开发中频繁用到



1.block是什么

是一个OC中特有的数据类型


2.有什么作用

保存一段代码,在需要的时候执行


3.怎么用

如何声明int类型的变量

int a;


如何使用block类型声明一个变量

注意点:在使用block类型声明变量的时候,需要说明block变量中保存的代码段的类型

代码段的类型:是否有参数,是否返回值


    1.声明一个 能够保存无参数无返回值的代码段 的block类型变量

    // block的变量名:myBlock

    // block变量中保存的代码段类型:void (^)()

    void (^myBlock)();


    2.声明一个 能够保存无参数有返回值的代码段 的block类型变量

    // block的变量名:myBlock

    // block变量中保存的代码段类型:int (^)()

    int (^myBlock)();


    3.声明一个 能够保存有参数无返回值的代码段 的block类型变量

    // block的变量名:myBlock

    // block变量中保存的代码段类型:void (^)(int a)

    void (^myBlock)(int a);


    4.声明一个 能够保存有参数有返回值的代码段 的block类型变量

    // block的变量名:myBlock

    // block变量中保存的代码段类型:int (^)(int a)

    int (^myBlock)(int a);


4.OC中的block类似于C语言中的函数指针

回顾:声明一个能够指向有参数有返回值函数的函数指针

int (*p)(int a, int b);


#pragma mark - 05 block变量的初始化和使用 [掌握]


1.block类型的变量有什么作用?

保存一段代码,这段代码可以有参数也可以返回值.


注意点:这段代码需要和声明block变量时指定的 能够保存的代码段类型 匹配


2.定义代码段

1.定义一个 无参数无返回值 代码段

^void () {

    NSLog(@"hello world...");

};


2.定义一个 无参数有返回值 代码段

^int () {

    NSLog(@"hello world...");

    return 10;

};


3.定义一个 有参数无返回值 代码段

^void (int a) {

    NSLog(@"a = %d", a);

};


4.定义一个 有参数有返回值 代码段

^int (int a) {

    return a+1;

};


3.如何把代码段赋值给block变量

void (^myBlock)() = ^void () {

    NSLog(@"hello world...");

};

格式规范:

返回值类型 (^block变量名称)(参数列表) = ^返回值类型 (参数列表) { ///执行的代码 };

   

4.声明一个block类型的变量之后,其中保存的代码段会立刻执行吗?

不会

在手动调用的时候执行

与参传参, 有返回值就接.


#pragma mark - 06 block的简写 [掌握]

返回值类型 (^block变量名称)(参数列表) = ^返回值类型 (参数列表) { ///执行的代码 };

   

1.针对定义代码段的简写

    1.如果一个代码段没有参数,可以省略小括号

    2.代码的返回值类型可以直接省略,编译器会自动检测

   

2.针对声明block变量的简写

    参数列表中只需要说明参数的类型和参数的数量,不需要说明参数的名称

   

3.建议:使用完整的规范的格式

   

#pragma mark - 07 使用typedef简化block定义 [掌握]

1.typedef的作用:给一个类型起别名

2.使用typedef给int类型起别名

    typedef int MyInt;

    typedef 原类型名 新类型名;

    3.使用typedef给block类型起别名:

   


// block的名称:myBlock

// block的类型:int (^)(int a) -> 有一个int类型参数并且返回值是int类型的block

int (^myBlock)(int a);

   

// 给具有一个参数一个返回值的block类型起别名

// 类型的别名: myBlock

// block类型: int (^)(int) -> 有一个int类型参数并且返回值是int类型的block

typedef int (^myBlock)(int a);

myBlock block1;

myBlock block2;

   

和使用typedef给函数指针起别名写法相同

   

3.建议:

    1.在初学block的时候,可以使用typedef简化block的定义

    2.在公司实际开发中,很少使用typedef

    3.不建议使用,尽量自己写,多练习

   

#pragma mark - 08 block访问外部变量的问题 [掌握]

1.在block内部可以访问并直接修改全局变量的值

2.在block内部可以访问但是不能直接修改局部变量的值

    如果在block内部想修改局部变量的值,需要对该变量使用__block进行修饰


1.在Block内部访问外部的全局变量

    1.变量的地址没有任何改变;

    2.变量的值可以在Block内部直接修改;

2.在Block内部访问外部的局部变量

    1.外部的局部变量地址是栈区的

    2.在block中访问的时候,会把该变量拷贝到堆区,以常量的形式进行拷贝,所以不能直接修改该变量的值

    3.在Block内部不能直接修改外部局部变量的值

3.如果想在block内部修改外部局部变量的值,需要使用__block对该变量进行修饰

    1.在block内部访问该变量之前,该变量地址是栈区的

    2.在block内部访问改变量的时候,会把它拷贝到堆区,以指针的形式进行拷贝,可以修改该变量的值

    3.在block内部访问之后,该变量地址仍然是堆区的

4.如果在block内部定义了一个和外部变量同名的局部变量

    1.会屏蔽对外部变量的访问

    2.会在栈区创建一个新的局部变量

5.Block变量到底存在哪个区域

    OC对象是存在堆区的

    局部变量是存在栈区的

    在MRC中

        1.如果在block内部没有访问外部的局部变量,那么block是存储在全局区的

        2.如果在block内部访问了外部的局部变量,那么block是存储在栈区的

    在ARC中

        1.如果在block内部没有访问外部的局部变量,那么block是存储在全局区的(__NSGlobalBlock__)

        2.如果在block内部访问了外部的局部变量,那么block是存储在堆区的(__NSMallocBlock__)




   











2 个回复

倒序浏览
马上考试,很详细,
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马