OC加强-day04

时间:2023-03-09 21:41:07
OC加强-day04

#pragma mark 00知识回顾

//定义一个函数 函数没有返回值函数有一个参数:返回值是double 参数是两个int的block

void test(int a);

void test(double (^xiaoyuedashiBlock)(int num1,int num2));

//给下面的Person类添加一个方法,方法没有返回值,但是有一个参数:返回值是double 参数是两个int的block

@interface MKPerson  : NSObject

-(void)test:(int)a;

-(void)test:(double (^)(int num1,int num2))xiaoyuedashiBlock;

@end

#program mark - 0_14 协议可以多遵守 [掌握]

"强调

1.协议就是用来声明方法的,一份协议中存放的就是若干个方法的声明!!

2.一个类遵守了一份协议,就相当于拥有了所有协议中方法的"声明",一旦调用,必须实现!

"练习

"随堂代码/0_14 协议可以多遵守/喝水练习/喝水练习

写一个买水协议和一个喝水协议,买水协议里面是买水方法的声明,喝水协议中是喝水方法的声明

定义一个类,使得人能买水喝水

//思路

//1.创建两个协议分别声明方法

//2.创建Person类遵守协议

//3.实现方法

//4.创建对象调用方法

#program mark - 0_15 @required与@optional [掌握]

"强调

1.类A遵守了协议B,如果没有实现协议中用@required修饰的方法,编译报警告,如果没有实现@optional修饰方法,编译不报任何警告

2.无论是@required修饰的方法还是@optional修饰的方法,只要没有实现就调用了 一定会报错

#program mark - 0_16 NSObject基协议 [掌握]

1.什么叫做协议的继承

1>

协议A继承协议B,协议A叫做协议B的子协议,协议B叫做协议A的父协议

格式:

@protocol 协议A <协议B>

@end

2>

一个类"遵守"了协议A,就相当于拥有了协议A和协议B中所有方法的声明

2.一个现象,创建一个协议文件,发现这个协议默认是继承NSObject协议

"随堂代码/0_16 NSObject基协议/1_创建一个协议就是继承基协议的

3.什么是NSObject协议

1>NSObject协议就是一个协议而已,只不过名字叫做NSObject,和我们学过的一个类NSObject名字相同

2>OC规定所有自定义的协议必须直接或间接继承NSObject协议

3>NSObject协议又叫做基协议,

4>NSObject类是遵守NSObject这个基协议,NSObject这个类中很多方法来自于NSObject协议的声明

4>什么叫做协议的多继承???

一个协议可以继承多个协议

"思考

协议A如果只继承协议B,那么协议A继承NSObject协议了吗

继承了,因为协议B遵守了NSObject协议,而协议A继承协议B,所以协议A间接的继承了协议B

#program mark - 0_17 协议与其他的比较 [掌握]

协议 延展 分类 的比较

分类:将1个分类分为多个模块,来为一个类添加方法

延展:专门来私有化类的成员

协议:定义一份协议,可以让其他的类来遵守这个协议,遵守了之后,类中就拥有了这个协议中的方法的声明

继承:子类继承父类,子类就拥有了父类的缩影成员

#program mark - 0_18 协议的类型限制 [掌握]

0_18 协议的类型限制/1_买水练习

1.写一个买水协议,协议里面有三个方法,问价钱,给钱,拿水离开

2.用id指针指向一个对象,要求这个对象必须会买水

3.调用这个对象的买水方法

"需求

0_18 协议的类型限制/1_买水练习强化

4.写一个老板类,老板里面有一个id类型的属性秘书,这个属性要求必须会买水,老板类里面有一个对象方法口渴,老板一口渴就要秘书买水给他喝

"老板里面有一个id类型的属性秘书-->任何对象都可以给这个属性赋值,前提是遵守了买水协议

#program mark - 0_19 大家一起找女朋友 [掌握]

"需求

用面向对象的思想模拟给小明找女朋友

小明对女朋友的要求1)必须会做饭2)必须会洗衣服3)最好是女的

"分析

1.小明是一个人对象--->有Person类

Person中有一个属性叫做"女朋友",这个"女朋友"属性必须满足1)必须会做饭2)必须会洗衣服3)最好是女的

2.对Person类的具体分析

1)

Person中有一个属性叫做"女朋友",

这个女朋友属性可以是任何满足1)必须会做饭2)必须会洗衣服3)最好是女的这三个条件的对象

凤姐?--->只要满足条件就可以

范冰冰?-->只要满足条件就可以

母猪?-->只要满足条件就可以

结论:

1'Person中有一个属性叫做女朋友,这个属性要求是具有下面三点功能1)必须会做饭2)必须会洗衣服3)最好是女的.这三个条件的对象

2'这个属性应该是一个id类型对象,任何对象只要具有上面三种技能,就能当小明的女朋友

3'写一个女朋友协议,任何遵守这个协议的类创建的对象就可以赋值给小明的女朋友属性

2)

Person类中有一个对象方法谈恋爱,调用这个对象方法可以实现请自己的女朋友洗衣做饭表达自己是女性.

"实现

"随堂代码/0_19 大家一起找女朋友/1_大家一起找女朋友

1.创建女朋友协议-->1)必须会做饭2)必须会洗衣服3)最好是女的

2.创建Person类 -->

id<女朋友协议> 女朋友属性

-(void)talkLove;

3.创建其他类,遵守女朋友协议实现女朋友的3个方法,创建对象,赋值给小明的女朋友属性赋值 /Pig/Woman

"增加需求

女朋友每个月能给100块零花钱

思路

1.给协议增加一个方法,实现给小明每个月1000元

2.这个方法有返回值,返回值int

#program mark - 02 代理设计模式 [掌握]

1.什么叫代理设计模式

是一种设计模式

简单的说,对象A中有对象B做属性,对象B是要求遵守协议C的,对象A通过调用对象B的协议方法,完成需求.甚至是返回数据.

"开发实例

tableView ---> 是一种表格视图,可以分组(section)显示数据,每一组有若干行(row)

"实现效果

2016-04-18 15:07:36.893 模拟tableView[2284:1195213] 这是第0组的第0行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第1组的第0行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第1组的第1行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第2组的第0行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第2组的第1行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第2组的第2行

"分析

1>有一个类,这个类有一个方法,可以完成上面的打印

@interface tableView : NSObject

-(void)showData;

@end

@implementation tableView

-(void)showData

{

for (int i = 0; i < 组数; i++)

{

for (int j = 0; j < 每组有多上行; j++)

{

NSLog(@"%@",第i组第j行打印的数据)

}

}

}

@end

2>这个showData方法如何确定打印多少组,每一组打印多少行,某一行打印什么数据

2016-04-18 15:07:36.893 模拟tableView[2284:1195213] 这是第0组的第0行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第1组的第0行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第1组的第1行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第2组的第0行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第2组的第1行

2016-04-18 15:07:36.894 模拟tableView[2284:1195213] 这是第2组的第2行

1)参数

@implementation tableView

"随堂代码/02 代理设计模式/2_深入tableView代理模式_参数

-(void)showDataWithSections:(int)sections andRowsInEachSection:(int [])arr

{

for (int i = 0; i < 3; i++)

{

// arr[3] = {1,2,3}

for (int j = 0; j < arr[i]; j++)

{

NSLog(@"%@",[NSString stringWithFormat:@"这个是%d组的%d行",i,j]);

}

}

}

@end

2)代理

"随堂代码/02 代理设计模式/2_深入tableView代理模式_代理

"假设当前tableView对象内部有一个id类型的属性delegate,遵守了某个协议,实现了协议方法.

-(void)showData

{

for (int i = 0; i <[self.delegate 某个方法就能返回多少组]; i++)

{

for (int j = 0; j <[self.delegate 某个方法,可以根据我传给他的组数就能返回给我这组有多少行]; j++)

{

NSLog("%@",[self.delegate 某个方法传给这个方法第几组第几行,就会返回要打印的数据])

}

}

}

"实现

1.写一个tableView类,这个类有一个方法showData方法

2.定义一个协议,有三个方法

1>返回多上组

2>根据传入的组数返回这一组有多少行

3>根据传入的组数和行数返回这一行应该打印什么数据

3.定义其他类遵守协议,实现方法

4.创建对象,赋值给tableView的id属性

#program mark - 03 框架的概要介绍 [听懂]

此知识

1.什么事框架

就是一个文件夹,里面是各种各样的类的实现和声明.

2.什么是Foundation框架

基础框架,OC中许多其他框架实现功能需要依赖于Foundation框架中的类

#program mark - 04 NSString是1个类 [听懂]

1.用%@打印类的"实例对象"打印结果是什么

1>

int main(int argc, const char * argv[]) {

MKPerson *xiaoyue = [MKPerson new];

NSLog(@"%@",xiaoyue);//<类名:对象的地址>

NSLog(@"%p",xiaoyue);//对象的地址

return 0;

}

2016-04-18 16:29:58.061 实例对象[2668:1551094] <MKPerson: 0x100205e40>

2016-04-18 16:29:58.062 实例对象[2668:1551094] 0x100205e40

2>用%@打印对象,本质是调用了对象的description方法

//下面代码打印结果和预测的不一样,说明NSString类重写了description方法

#import <Foundation/Foundation.h>

#import "MKPerson.h"

int main(int argc, const char * argv[]) {

NSString *str =  @"123";

NSLog(@"%@",str);//<NSString:0X12344>

return 0;

}

2016-04-18 16:37:35.245 实例对象[2732:1592990] 123

Program ended with exit code: 0

#program mark - 05 NSString的恒定性 [听懂]

"强调

1.用@""创建的字符串存储在常量区--->@"无色";

2.用类方法创建的对象存储在堆区.--->[NSString stringWithFormat:@"无色"];

3.字符串的复用问题

1>在常量区创建字符串对象的时候,先看看常量区有没有相同的字符串可以直接用,如果有就直接拿来用,如果没有就重新创建

2>在堆区创建字符串对象的时候,先看看堆区有没有相同的字符串可以直接用,如果有就直接拿来用,如果没有就重新创建

3>常量字符串是不会被回收的//字符串在任何编程语言中都认为复用的可能性极大,重复创建浪费性能,索性就不回收了

1)验证1.

int main()

{

NSString *str=  @"无色";

NSLog(@"%p",str);

str = nil;

NSString *str2 = @"无色";

NSLog(@"%p",str2);

return 0;

}

2)验证2

在MRC下打印常量去字符的retainCount

int main()

{

NSString *str=  @"无色";

NSLog(@"%p",str);

NSLog(@"%lu",str.retainCount);

str = nil;

NSString *str2 = @"无色";

NSLog(@"%p",str2);

[str2 retain ];//发送retain不管用,记住不要自己去管理@""方式创建的字符串,因为你管理也没有用

NSLog(@"%lu",str2.retainCount);

return 0;

}

3)

在MRC下打印堆区字符的retainCount

int main()

{

NSString *str = [NSString stringWithFormat:@"12色"];

NSLog(@"%lu",str.retainCount);//1

[str retain];

NSLog(@"%lu",str.retainCount);//2

[str release];

NSLog(@"%lu",str.retainCount);//1

return 0;

}

"结论:MRC下不要管理常量字符串的retainCount,或者管理堆区创建的字符串对象的retainCount

#pragma mark - 00 知识回顾

一.NSString表示OC中的字符串,创建字符串最常见方式

1.@""

1>存储在常量区(数据段)

2>不会被销毁,MRC测试retainCount非常大,开发中不需要管理内存

3>@""方式创建的字符串,首先到常量区检查有没有相同,有就直接用,没有就在常量区创建

2.[NSString stringWithFormat:]

1>存储在堆区

2>用这种方式创建的字符串,首先到堆区去寻找还有没相同的,有就直接用,没有就在堆区创建

3>MRC下不需要内存管理

二.NSString常用方法

"随堂代码/06NSString常用方法/06NSString常用方法

"练习

//以拼接的方式创建字符串@"这个月是2016年4月"

//用常量区方式创建字符串@"这个月是2016年4月"

//如果这个两个字符串内容相等就把第一个字符串长度打印出来

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {

NSString *str1 = [NSString stringWithFormat:@"这个月是%d年%d月",2016,4];

NSString *str2 = @"这个月是2016年4月";

if([str1 isEqualToString:str2])

{

NSLog(@"%lu",str1.length);

}

return 0;

}

#program mark - 07 字符串读写数据的方法 [听懂]

/**

*  将字符串的内容写到指定的文件中

*

*  @param path             路径,要将字符写入到哪一个文件中

*  @param useAuxiliaryFile 保证原子性,若为YES,就会创建一个临时文件,将内容写到临时文件中,如果成功,再将临时文件拷贝到指定的目录,这样好处是安全不容易出错,但是效率低,若为NO,则将字符串直接写入到文件中

*  @param enc              以哪种字符编码将字符串写入到文件中

*  @param error            二级指针,传入一个NSError的一个二级指针,如果成功,方法完毕后,张这个二级指针设置为nil,如果失败,执行完毕后NSError指针指向一个错误对象,可以打印这个错误对象的到的发生错误的详细信息,调用NSError对象的localizedDescription方法,可以拿到错误的简要原因

*

*  @return 返回值为BOOL代表是否写入成功

*/

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error;

//从指定的文件中读取字符串数据

+ (nullable instancetype)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error;

#program mark - 08 使用NSURL读写数据 [听懂]

//往URL中写入数据

- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error;

//获取URL

+ (nullable instancetype)stringWithContentsOfURL:(NSURL *)url usedEncoding:(nullable NSStringEncoding *)enc error:(NSError **)error;

#program mark - 09 字符串的比较 [听懂]

- (NSComparisonResult)compare:(NSNumber *)decimalNumber;

"强调

1.方法名

- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask;

2.调用格式

long(NSInteger) result =  [str1 compare:str2 options:xxxx];

3.返回值

NSComparisonResult 是一个枚举 // -1 str1比str2小    0 str1和str2相等   1 str1比str2大

4.参数

NSCaseInsensitiveSearch = 1, // 忽略大小写比较

NSLiteralSearch = 2, //完全严格比较 ---> [str1 compare:str2]

NSNumericSearch = 64 //比较数字,从左往右比较,一有结果就停止,比价的字符串格式需要相等.

"随堂代码/09 字符串的比较/09 字符串的比较

5.测试

int main(int argc, const char * argv[]) {

NSString *str1 = [NSString stringWithFormat:@",20今天是%d",4];//和str2格式不一样,所以比较会失败

NSString *str2 =  @"10今天是99";

NSInteger result = [str1 compare:str2 options:64];

NSLog(@"%ld",result);

return 0;

}

#program mark - 10 字符串的搜索 [听懂]

"练习

*公民身份证号码组成规则是前4位是代表省份和地区(例如4201代表湖北省武汉市),最后一位代表性别(1或3代表男性),

编写一个程序,通过身份证号码判断某人是否是武汉人以及其性别。

#import <Foundation/Foundation.h>

int main()

{

char shenFenZhengID[100] = "0";

NSLog(@"输入大于4位的身份证号!!!");

scanf("%s",shenFenZhengID);

//转换成OC字符串

NSString *shenFenZhengID_str = [NSString stringWithFormat:@"%s",shenFenZhengID];

//看前缀

BOOL qianZhui =  [shenFenZhengID_str hasPrefix:@"4201"];

if(qianZhui)

{

NSLog(@"我乃武汉人");

}

else

{

NSLog(@"我是非武汉人");

}

//看后缀

if([shenFenZhengID_str hasSuffix:@"1"]||[shenFenZhengID_str hasSuffix:@"3"])

{

NSLog(@"MAN");

}

else

{

NSLog(@"WOMAN");

}

return 0;

}