OC加强-day03

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

1.分类的作用

作用:讲一个类分为多个模块,将相似功能的方法写在同一个模块中,方便我们后面代码的维护

 

 

"强调

1.分类中只能写方法的声明和实现,你不要直接去写属性,写了立即报错

 

2.在分类的.h中用@property声明的属性,不会生成属性,只会在分类的.h里面生成"所谓的"属性的set/get的声明.

 

3.在分类中到底如何访问本类的属性.

1>分类中是不能直接访问本类中的真私有属性,但是可以通过set/get方法访问

2>分类中可以直接访问本类.h@interface中直接声明的属性

 

 

#program mark - 0_19 非正式协议 [现在先听懂,等学了Foundation框架再回来复习]

为系统自带的类写分类,就叫做非正式协议

 

 

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

 

 

"强调

1.类延展也是类的一种分类,这个分类和本类公用一个.m,所以它是一个只有.h的文件

2.类延展没有没有名字

 

"练习

给一个类YYNetworkTool,添加一个类延展download

 

 

3.和普通分类的区别

1>普通分类直接创建属性,会立即报错,类延展却可以创建属性

2>普通分类用@property生成的属性,不会生成属性,只会在分类的.h里面生成"所谓的"属性的set/get的声明,但是延展,会在主类的.m中生成私有属性和set/get的实现.以及当前类延展的.h中生成属性的set/get方法的声明.

 

 

"注意:由于延展和主类公用一个.m,又由于编译只编译.m文件.所以要在主类中导入类延展的.h,否则延展中的代码没有效果

 

 

 

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

 

 

1.什么叫私有的@property

生成的属性的set/get的声明也在.m里面

 

2.类延展到底有什么用?

就是用来声明不想在类外部使用的属性和方法.当方法或者属性仅限于当前类内部使用的时候

 

 

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

 

1.变量是什么?

变量就是内存中若干个字节,用来存储数据.

int 型变量 里面存储 整型数据

"函数的指针"类型 里面存储 一个函数的地址

block类型的变量 里面存储 一段代码

 

 

2.变量的声明

1>int

数据类型 变量名;

int    num_int;

2>函数的指针

//函数的指针指向一个返回值为void,参数是两个double型的函数

void (*p)(double num1,double num2);

//函数的指针指向一个返回值为void,没有参数的函数

void (*p1)();

3>block

//定义一个block的变量存储一个返回值为void,参数是两个double型代码块

void (^xiaoyueBlock)(double num1,double num2);

//定义一个block的变量存储一个返回值为void,没有参数的代码块

void (^xiaoyue2)();

 

#program mark - 知识点复习

 

1.分类

1>是什么

当一个类中有很多属于不同范畴的方法的时候,通常使用分类来把这些方法进行分类,有一个类叫本类,其他的叫分类.

 

2>有什么特点?

1)和主类在一起共同构成了一个类

2)不能声明属性,只能添加方法

3)可以实现和主类同名的方法,编译的时候会覆盖主类的方法.如果调用此方法,调用分类的.

4)如果两个分类实现的方法名字相同,谁最后编译调用谁的.

5)主类肯定比分类先编译.

 

 

2.延展

 

1>什么是延展

延展也是一个分类,只不过这个分类和主类公用一个.m文件.并且延展是没有名字的

 

 

2)有什么特点

1)可以声明属性,也可以声明方法

2)一般是把类的延展写在主类的.m,延展中声明的方法/属性,只能在当前类的内部使用,在当前类的外部无法访问

"例子

一个ViewController代表一个界面,内部的显示/内存管理由当前控制器类自己管理,外界不需要知道内部做了什么,此时控制器对象的一些属性方法,就可以写在控制器.m中的延展里

 

 

3.非正式协议

1>是什么?

就是给苹果提供的类写分类

 

"例子

NSString 添加分类 --->统计一个字符串对象内部阿拉伯数字个数

 

 

.h

@interface NSString (YYfenlei)

-(int)numOfAlaboSuzi;

@end

 

 

.m

 

-(int)numOfAlaboSuzi

{

    

//    self 就代表当前字符串对象

    

}

 

 

4.block变量的定义

 

//1.无参数无返回值block变量 xiaoyueblock

void (^xiaoyueBlock)();

 

//2.有一个int型参数返回值bint型的lock变量 xiaoyue2

int (^xiaoyue2)(int opNum);

 

//3.定义一个有三个参数,int,double,char,返回值是double类型的block 变量xiaoyue3

 

double (^xiaoyue3)(int opNum1,char opNum2,double opNum3);

 

 

"变量的赋值

1>int

int num;

num = 10;

 

2>函数的指针

 

int add(int a,int b);

int add(int a,int b)

{

    return a+b;

}

//只是定义了一个函数的指针,还没有和任何函数关联

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

 

//使用函数名给函数的指针赋值

p=add;

 

 

 

3>

//1.无参数无返回值block变量 xiaoyueblock

void (^xiaoyueBlock)();

xiaoyueBlock = ^void (){

 

    代码;

};

 

 

//2.有一个int型参数返回值bint型的lock变量 xiaoyue2

int (^xiaoyue2)(int opNum);

xiaoyue2 = ^int (int opNum){

 

    return opNum + 10;

 

 

};

 

//3.定义一个有三个参数,int,double,char,返回值是double类型的block 变量xiaoyue3

 

double (^xiaoyue3)(int opNum1,char opNum2,double opNum3);

 

xiaoyue3 = ^double(int opNum1,char opNum2,double opNum3){

 

 

    

    return 1.1 + opNum2;

 

 

};

 

 

int main()

{

    

    double dou =  xiaoyue3(2,'a',1.1);

    

    return 0;

 

    

}

 

 

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

此知识点的复习见OC加强03视频笔记/05 block变量的初始化和使用.pdf

 

 

#program mark - 06 block的简写 [听懂]

此知识点的复习见OC加强03视频笔记/06 block的简写.pdf

 

"强调

自己写的时候不要简写,能看懂别人的简写

 

"例子

 

//定义一个有三个参数,int,double,char,返回值是double类型的block 变量xiaoyue3

 

//完整写法

double (^xiaoyue3)(int opNum1,char opNum2,double opNum3)= ^double(int opNum1,char opNum2,double opNum3){

    

    

    

    return 1.1 + opNum2;

    

    

};

//简化写法

double (^xiaoyue3)(int ,char,double )= ^(int opNum1,char opNum2,double opNum3){

    

    return 1.1 + opNum2;

    

    

};

 

 

#program mark - 07 使用typedef简化block定义

此知识点的复习见OC加强03视频笔记/07 使用typedef简化block定义.pdf

 

"复习

//定义一个 Lint别名 代表long int 这种类型

typedef long int Lint;

//定义一个 arr别名 代表 长度是3的整型数组 这种类型

typedef int arr[3];

//定义一个 xiaoyue别名 代表 返回值是int,参数是空的block 这种类型

typedef  int (^xiaoyue)();

 

int main()

{

    Lint num = 1000;

    //定义一个长度是3int型数组brr

    arr brr = {1,2,3};

    //定义一个返回值是int没有参数的变量

    xiaoyue xiaoxiaoyue;

    

    return 0;

}

 

"练习

利用typedef定义一个别名叫做hello的无参无返回值的block类型,定义一个hello类型block变量并调用

利用typedef定义一个别名叫做add的有两个int参数参无返回值的block类型,定义一个add类型block变量并调用

 

typedef  void (^hello)();

typedef  void (^add)(int opNum1,int opNum2);

 

int main()

{

    

    hello xiaoyueblock1;

    xiaoyueblock = ^void(){

    

        NSLog(@"hello world!");

    

    };

    

    add xiaoyueblock2 = ^void(int opNum1,int opNum2){

    

        NSLog(@"和是%d",opNum2+opNum1);

    

    };

    

    return 0;

}

 

 

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

 

1.block类型的变量,可以定义变量的,

 

int main()

{

    //无返回值有一个int参数block变量

    void (^xiaoyuedashiBlock)(int opNum) =  ^void(int num1){

 

        int num2 = 10;

        num2++;

        num1++;

        NSLog(@"%d-----%d",num1,num2);

    };

    

    xiaoyuedashiBlock(22);

    

    return 0;

}

 

2.block里面存代码内部是可以访问外部变量的.

 

 

//定义一个全局变量

int quanju_num = 10;

int main()

{

    //无返回值有一个无参数block变量

    void (^xiaoyuedashiBlock)();

    //定局部变量

    int jubu_num = 20;

    xiaoyuedashiBlock =  ^void(){

        NSLog(@"%d---%d",quanju_num,jubu_num);

    };

    

    xiaoyuedashiBlock();

    

    return 0;

}

 

 

3.block内的代码可以修改全局变量,但是不能修改外部变量

 

 

//定义一个全局变量

int quanju_num = 10;

int main()

{

    //无返回值有一个无参数block变量

    void (^xiaoyuedashiBlock)();

    //定局部变量

    int jubu_num = 20;

    xiaoyuedashiBlock =  ^void(){

        

//        quanju_num++;没问题

//        jubu_num++;编译报错

        NSLog(@"%d---%d",quanju_num,jubu_num);

    };

    

    xiaoyuedashiBlock();

    

    return 0;

}

 

 

4.block内的代码如果一定要"修改"外部变量,可以在定义这个变量的时候添加__block修饰这个变量

//定义一个全局变量

int quanju_num = 10;

int main()

{

    //无返回值有一个无参数block变量

    void (^xiaoyuedashiBlock)();

    //定局部变量

    __block int jubu_num = 20;

    xiaoyuedashiBlock =  ^void(){

        

        quanju_num++;

        jubu_num++;

        NSLog(@"%d---%d",quanju_num,jubu_num);

    };

    

    xiaoyuedashiBlock();

    

    return 0;

}

 

 

 

 

5.为什么block内的代码可以修改全局变量,但是不能修改外部变量??

因为block

 

//定义一个全局变量

int quanju_num = 10;

int main()

{

    //无返回值有一个无参数block变量

    void (^xiaoyuedashiBlock)();

    

        {

        //定局部变量

        __block int jubu_num = 20;

        xiaoyuedashiBlock =  ^void(){

            

            quanju_num++;

            jubu_num++;

            NSLog(@"%d---%d",quanju_num,jubu_num);

        };

    

    }

    xiaoyuedashiBlock();

    return 0;

}

 

 

 

 

 

#program mark - 09 block作为函数的参数

 

 

//定义一个函数无返回值参数是一个int型数据

void test1(int a)

{

    a++;

    printf("%d\n",a+10);

    

}

//定义一个参数是block的函数

void test( void (^xiaoyuedashiBlock)())

{

    xiaoyuedashiBlock();

}

int main()

{

    //把一个没有返回值的没有参数的block当做上面函数的参数

    void (^youse)() =  ^void(){

        

        NSLog(@"block执行了!");

    

    };

    test);

    

}

 

"练习

模拟IOS开发:

写一个无返回值的函数,函数名requestData

函数内有三个顺序执行的功能,发送网络请求,解析请求到的数据,展示数据,这三个功能用NSLog模拟.

函数要求有一个block参数,这个block里面的代码用来播放动画,这段代码必须在函数内解析数据后调用(播放动画也用NSLog模拟).

 

1.先写自己能做

1>定义函数

1)发送请求 NSLog

2)解析数据 NSLog

3)展示数据 NSLog

 

void requestData();

void requestData()

{

    NSLog(@"发送请求");

    NSLog(@"解析数据");

    NSLog(@"展示数据");

}

 

 

 

2.实现函数参数的定义

void requestData(void (^dongHuang)());

void requestData(void (^dongHuang)());

{

    NSLog(@"发送请求");

    NSLog(@"解析数据");

    dongHuang();

    NSLog(@"展示数据");

}

 

 

3.实现调用

int main()

{

    

    void (^donghuablock)() = ^void(){

    

        NSLog(@"播放一个翻转动画");

    

    };

    

    requestData(donghuablock);

    

    return 0;

}

 

 

"新需求

实现网络解析了多长时间就播放多久的动画

void requestData(void (^dongHuang)(double sec));

void requestData(void (^dongHuang)(double sec))

{

    NSLog(@"发送请求");

    NSLog(@"解析数据");//5s

    dongHuang(9.0);

    

    NSLog(@"展示数据");

}

 

int main()

{

    

    void (^donghuablock)(double sec);

    

    donghuablock = ^void(double sec){

        

        NSLog(@"播放一个旋转动画播放%lf",sec);

        

    };

    

    requestData(donghuablock);

    

    return 0;

}

 

 

 

#program mark -10 block作为方法的参数 [掌握]

此知识点的复习见OC加强03视频笔记/10 block作为方法的参数.pdf

 

 

"强调

block作为参数的理解的要点

block是一种数据类型,block这种数据类型的变量,里面存储的就是代码.

block变量中存储的是代码,这个block变量可以传来传去,只要拿到这个block变量,就能调用变量里面存放的代码.

 

 

 

#program mark -11  block作为方法的参数2 [掌握]

 

 

"复习

1.定义字符串的两种方式

1>数组方式

char str[] = {'a','b','\0'};

2>指针方式

char *str2 = "ab";

 

2.什么是指针数组

是数组,只不过这个数组中存放的是指针.

 

3.指针字符串数组

是数组,里面存的是用指针方式定义的字符串

 

char *str1 = "手机响了";

char *str2 = "她喜欢我";

char *str3 = "我能反杀";

 

char *arr[3] = {

    

    str1,

    str2,

    str3,

    

};

 

4.strcmp(字符串1,字符串2)函数数的使用步骤和原理

 

1>引入<string.h>

2>从两个字符串的第一个字符开始比较,比较对应的ASCII,一旦有结果了就停止

 

字符串1==字符串2时候结果0

字符串1>字符串2时候结果>0

字符串1<字符串2时候结果<0

 

 

#include<string.h>

int main()

{

    

    char *str1 = "ab";

    char *str2 = "cA";

    int result =   strcmp(str1,str2);

    printf("%d\n",result);

    

}

 

"需求

有一个指针字符串数组

char *countries[] =

{

    "Nepal",

    "Cambodia",

    "Afghanistan",

    "China",

    "Singapore",

    "Bangladesh",

    "India",

    "Maldives",

    "South Korea",

    "Bhutan",

    "Japan",

    "Sikkim",

    "Sri Lanka",

    "Burma",

    "North Korea",

    "Laos",

    "Malaysia",

    "Indonesia",

    "Turkey",

    "Mongolia",

    "Pakistan",

    "Philippines",

    "Vietnam",

    "Palestine"

};

 

1.定义函数把字符串按照大小排序

 

void paiXuWithASCII(char * countries[],int length)

{

    

    

    char *temp = nil;

    for (int i = 0; i < length - 1; i++) {

        for (int j = 0; j < length - i -1; j++) {

            if(strcmp(countries[j],countries[j+1])>0)

            {

                temp = countries[j];

                countries[j] = countries[j+1];

                countries[j+1] = temp;

            }

        }

    }

    for (int i  = 0; i < length; i++) {

        printf("%s\n",countries[i]);

    }

}

 

int main()

{

    

    

    paiXuWithASCII(countries,24);

    return 0;

 

}

 

 

2.定义一个函数,按照每个字符串长度排序

void paiXuWithASCII(char * countries[],int length)

{

 

    char *temp = nil;

    for (int i = 0; i < length - 1; i++) {

        for (int j = 0; j < length - i -1; j++) {

            if((int)strlen(countries[j])-(int)strlen(countries[j+1])<0)//strlen

            {

                temp = countries[j];

                countries[j] = countries[j+1];

                countries[j+1] = temp;

            }

        }

    }

    for (int i  = 0; i < length; i++) {

        printf("%s\n",countries[i]);

    }

}

 

int main()

{

    

    

    paiXuWithASCII(countries,24);

    return 0;

    

}

 

3.调用这个函数实现排序,按照调用者的要求排序

 

//分析:比较上面两种实现,两种功能之间唯一不同的代码,在排序循环中的if语句的判断条件部分,能否把if判断语句,传到函数中,实现根据不同的需求进行潘旭

 

//1.确定的是传入的肯定是if判断条件中,和下面两句代码类似的

 if(strcmp(countries[j],countries[j+1])>0)

 if(strlen(countries[j])-strlen(countries[j+1])<0)//strlen

//2分析传入的代码

//1>需要返回值吗--->需要 0/1

//2>需要参数吗? -->肯定要参数,countries[j],countries[j+1]

 

BOOL (^xiaoyuedashiBlock)(char * opXing1,char * opXing2) = ^BOOL(char * opXing1,char * opXing2){

 

 

    

     BOOL result = ((int)strlen(opXing1)-(int)strlen(opXing2)<0)

 

     return result;

 

};

 

4.修改函数

 

void paiXuWithUsrBlock(char * countries[],int length,BOOL (^xiaoyuedashiBlock)(char * opXing1,char * opXing2))

{

    

    char *temp = nil;

    for (int i = 0; i < length - 1; i++) {

        for (int j = 0; j < length - i -1; j++) {

            if( xiaoyuedashiBlock(countries[j],countries[j+1]))

            {

                temp = countries[j];

                countries[j] = countries[j+1];

                countries[j+1] = temp;

            }

        }

    }

    for (int i  = 0; i < length; i++) {

        printf("%s\n",countries[i]);

    }

}

 

int main()

{

    BOOL (^xiaoyuedashiBlock)(char * opXing1,char * opXing2) = ^BOOL(char * opXing1,char * opXing2){

        BOOL result = ((int)strlen(opXing1)-(int)strlen(opXing2)<0);

        BOOL result2 = (strcmp(opXing1, opXing2)>0);

        return result;

        

    };

    

    paiXuWithUsrBlock(countries,24,xiaoyuedashiBlock);

    return 0;

    

}

 

 

#pragma mark 12 block与函数的异同 [掌握]

 

1.相同点

都是可以存储一段能够实现特定功能的代码

 

2.不同

1>block是一种数据类型,函数不是数据类型,函数就是一段代码

2>block可以直接做参数传递,函数是不可以的.函数的指针当参数传递本质是间接传递"了解一下

 

void test()

{

    printf("xxx\n");

}

void (*p)() = test;

 

void useTest(void (*p)())

{

    

    p();

}

int main()

{

    

    useTest(p);

    return 0;

}

 

3.block是可以做函数的返回值的.

1>定义一个无返回值,有一个int型参数的block变量

void (^xiaoyuedashiBlock)(int num) = ^void(int num){

 

    NSLog(@"%d",num);

 

};

 

2>定义无返回值无参数的函数

void test()

{

    

    

    

}

 

3>希望上面函数返回一个block

 

typedef void (^xiaoyuedashiBlock)(int num);

 

xiaoyuedashiBlock test()

{

    

    void (^xiaoyuedashiBlock)(int num) = ^void(int num){

        

        NSLog(@"%d",num);

        

    };

    return xiaoyuedashiBlock;

    

}

 

//测试

int main()

{

    

    xiaoyuedashiBlock b1 = test();

    b1(2);

    return 0;

}

 

注意:

1.一般我们不这样写.这样可阅读性太差.

2.当函数的返回值是block类型的时候,返回值类型必须要用typedef的形式给出,否则报错

 

 

//下面代码会报错

typedef void (^)(int num) test()

{

    

    void (^xiaoyuedashiBlock)(int num) = ^void(int num){

        

        NSLog(@"%d",num);

        

    };

    return xiaoyuedashiBlock;

    

}

 

 

 

#pragma mark 13 协议的基本使用 [掌握]

协议:@protocol

协议:专门用来写方法声明的,协议中不能写属性

遵守协议的类,这个类就拥有了这份协议中的所有方法的声明,而不用自己去定义

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/MKxiaoyue/p/5708020.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值