OC加强-day02

#program mark - 01 @class关键字 [掌握]

1.当两个头文件互相引用的时候,如果双方都是用#import来引入对方的头文件,就会造成死循环,编译不通过

解决方案:其中一边不要使用#import去引用对方的头文件,而是用@calss关键字,class作用仅仅是来标识一下这个类

2.当类A使用@class去引用类B的时候,如果类A的内部需要访问类A的属性或方法,则在类A的.m内#import类B的.h

3.对比#import和@class

1).#import是一个预处理命令,将文件的内容拷贝到写指令的地方

2).@class不是一个预处理命令,不会将文件的内容拷贝出来,只是告诉编译器有这么一个类

"强调

1.两个类A和B,如果头文件互相#import,编译和运行没有问题.

2.一旦A中有B这个属性或者B中有A这个属性,直接就报错了.

3.怎么解决,一端用#import引入,另一端用@class

//需求

书提供一个方法给外界,所有者把名子签上去

由于没有真正的导入头文件,所以在Book的.m中无法访问owner对象属性的内容,此时就需要在Book.m中导入MKStudent.h

"重要

#import和@class区别

#import是预处理指令,是防止了重复包含文件的#include,

@class 不是是预处理指令,只是告诉编译器有这么个类,并且不会引入文件

#program mark - 02 循环retain [掌握]

1.对象的销毁不是因为调用了dealloc方法,

2.对象的retainCount-->0--->销毁--->dealloc

3.什么是循环retain

在MRC下,两个对象互相拥有对方做属性,如果都给对方赋值了,就会导致两个对象都无法释放

4.怎么解决循环retain

一端用retain一端用assgin,可以实现其中一个对象调用dealloc方法释放另外一方,最终都能释放

#program mark - 03 自动释放池的使用 [掌握]

1什么是自动释放池

自动释放池就是一对大括号包裹着的作用域,只不过前半部分多了一个@autoreleasepool来修饰

@autoreleasepool{

int num = 10;

}

2.和普通的作用域区别?

自动释放池可以在自动释放池结束的时候,对调用了autorelease的方法的对象,进行一次release

@autoreleasepool{

MKPerson *xiaoyue = [[MKPerson new] autorelease];

}

3.有什么用?

防止对于alloc/new出来的对象忘记手动调用release

#program mark - 04 使用自动释放出的七大注意 [掌握]

1.只有在自动释放池中调用了对象的autorelease方法,这个对象才会被存储到这个自动释放池中,如果只是将对象的创建代码写在自动释放池中,而没有调用这个对象的autorelease方法,是不会将这个对象存储到这个自动释放池中的

2.对象的创建可以在在动释放池的外面,在自动释放池之中,调用对象的autorelease方法,就可以将这个对象存储到这个自动释放池中,将一个对象存储到自动释放池中最重要的步骤是调用这个对象的autorelease方法,这句代码一定要放在自动释放池中

3.当自动释放池结束的时候,仅仅是对存储在自动释放池中的对象放松1条release消息,而不是销毁对象

4.如果在自动释放池中,调用同一个对象的autorelease方法多次,就会将对象储存多次到自动释放池中,在自动释放池结束的时候,会为对象发送多条release消息,这样就会出现僵尸对象错误,所有一个自动释放池中,只autorelease 一次,只将这个对象释放一次,否则就会出现野指针错误

5.如果在自动释放池中,调用了存储到自动释放池的对象的release方法,在自动释放池结束的时候,还会再调用对象的release方法,就会造成野指针操作

6.将对象存储到自动释放池,并不会是对象的引用计数器+1.

所以他的好处是:创建对象将对象存储在自动释放池,就不需要写release了

7.自动释放池可以嵌套

调用对象的autorelease方法会将对象加入到当前的自动释放池中,只有在当前自动释放池结束的时候才会像对象发送release消息

"强调"

1.需要自动释放池帮助完成release操作的对象,不一定是在自动释放池中创建的,只要这个对象在自动释放池中调用autorelease即可

"随堂代码/04 使用自动释放出的七大注意/1_需要协助release的对象不一定在自动释放池中创建

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

MKPerson *xiaoyue = [MKPerson new];

@autoreleasepool {

[xiaoyue autorelease];

NSLog(@"---------------");

}

return 0;

}

2.自动释放池可以嵌套

对象在哪个自动释放池结束的时候release,就看对象在哪个autoreleasepool中调用了autorelease方法

"核心代码

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

MKPerson *xiaoyue1 = [[MKPerson alloc] initWithName:@"A"] ;

@autoreleasepool

{

MKPerson *xiaoyue2 = [[MKPerson alloc] initWithName:@"B"];

[xiaoyue2 autorelease];

@autoreleasepool

{

MKPerson *xiaoyue3 = [[MKPerson alloc] initWithName:@"C"] ;

@autoreleasepool

{

MKPerson *xiaoyue4 = [[MKPerson alloc] initWithName:@"D"];

[xiaoyue4 autorelease];

[xiaoyue1 autorelease];

[xiaoyue3 autorelease];

}

}

}

return 0;

}

#program mark - 05 自动释放池的规范 [掌握]

"强调

1.定义一个类,一般还要定义一个以类名开头的类方法,用来返回一个实例化对象,这是规范.苹果公司自己就是这么干的.

#program mark - 07 微博练习 [掌握]

设计一个微博app的部分类:

一、微博类 (Microblog)

属性:

* 文字内容

* 图片

* 发表时间 (可以用字符串表示NSString)

* 作者

* 被转发的微博

* 评论数

* 转发数

* 点赞数

二、作者类 (User)

* 名称

* 生日

* 账号

三、账号类 (Account)

* 账号名称

* 账号密码

* 账号注册时间 (使用结构体)

//分析

1.发一条微博-->内容--->作者(直到世界尽头)--->账号(157XXX 12XXX)

//微博类中有个作者属性

//作者类拥有账号属性

结论:定义类的顺序

1.账号类Account

1>@property 属性

* 账号名称 NSString

* 账号密码 int

* 账号注册时间 (使用结构体) struct

2>构造方法

3>dealloc

2.作者类User

1>@property 属性

* 名称  昵称 nickName

* 生日  struct

* 账号  Account

2>构造方法

3>dealloc

3.微博类Microblog

1>@property 属性

* 文字内容  NSString

* 图片     NSString url

* 发表时间 (可以用字符串表示NSString) struct

* 作者  User

* 转发的微博 Microblog

* 评论数 int

* 转发数 int

* 点赞数 int

2>构造方法

3>dealloc

模拟场景:

* 张三在2007-9-8 17:56:34的时候, 注册了一个账号(名称:itcast, 密码:123456)

* 张三的生日是1998-7-4 18:46:24

* 张三在2010-8-8 9:23:44的时候, 发布一条微博

* 文字内容  @“今天心情不错”

* 图片 @“goodDay.png”

* 发表时间

* 作者

* 转发的微博

* 评论数 100

* 转发数 290

* 点赞数 2000

* 李四在2006-9-8 19:26:54的时候, 注册了一个账号(名称:lisiitcast, 密码:654321)

* 李四的生日是1999-9-6 14:16:28

* 李四在2011-8-8 20:47:09的时候, 转发了张三之前发布的微博 ,并且还附带了一句话:@“今天心情确实不错”

* 评论数 10

* 转发数 20

* 点赞数 200

快捷代码块路径

/Users/你的小房子名字/Library/Developer/Xcode/UserData/CodeSnippets

//思路

//一条微博:内容,作者,作者有一个账号

//微博类中有作者属性,作者属性中有账号属性

//1.账号类 Account

* 账号名称 NSString

* 账号密码 int

* 账号注册时间 (使用结构体) struct

//2.作者类 User

* 名称 NSString 昵称

* 生日 struct

* 账号 Account

//3.微博类 Microblog

* 文字内容  NSString

* 图片     NSString URL

* 发表时间 (可以用字符串表示NSString) NSString

* 作者      User

* 转发的微博 Microblog

* 评论数    int

* 转发数    int

* 点赞数    int

"强调

1.类方法返回对象注意添加autorelease

2.自定义构造方法注意对OC对象调用set方法

#program mark - 08 ARC机制的概述 [掌握]

1.指针是什么?

无论指针变量还是指针常量都是表示地址.

2.什么是强指针

ARC环境下,OC对象

用__strong修饰的指针叫做强指针 (默认指针变量前面什么都不加 就是强指针)

3.什么是弱指针

ARC环境下,OC对象

用__weak修饰的指针叫做弱指针

4.ARC机制核心

1>对象内存管理代码不需要程序员写,由编译器实现

2>对象是否释放就看有没有强指针指向自己,如果有就不释放,如果没有立即释放.

"随堂代码/08 ARC机制的概述/1_强指针和弱指针

1.分析

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

{

//    {

MKPerson *per = [[MKPerson alloc] initWithName:@"无色"];

//    }

NSLog(@"\n---------------");

return 0;

}

2.

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

{

__weak MKPerson *xiaoyue2 = nil;

{

MKPerson *xiaoyue = [[MKPerson alloc] initWithName:@"xiaoyue"];

xiaoyue2 = xiaoyue;

}

NSLog(@"---------------");

}

return 0;

}

3.

int main()

{

__weak  MKPerson *xiaoyue = [[MKPerson alloc] initWithName:@"xiaoyue"];

NSLog(@"---------------");

return 0;

}

#program mark - 09 第一个ARC程序 [掌握]

"强调

在ARC下给类添加@property属性,OC对象统一用strong非OC对象统一使用assgin

@property(nonatomic,strong) 类型 * 属性名

#program mark - 11 ARC机制下的循环引用 [掌握]

1.是什么?

当对象A中有一个对象B属性,对象B中又有一个对象A属性的时候,如果两边都使用strong来互相修饰,并实现双方的赋值,会导致对象A和对象B都无法释放.

"随堂代码/11 ARC机制下的循环引用/1_ARC循环引用

2.例子--ARC

1>需求

人类 Person

{

电脑属性

}

电脑类 Computer

{

人属性(所有者)

}

1)只是新建对象都能释放

2)只是有一边赋值了都能释放

3)两边都赋值了都不能释放

4)解决,一端用strong修饰,一边用weak修饰

3.解决:一端用weak,一端用strong

#program mark - 12 @property参数总结 [掌握]

1.与多线程相关的参数

atomic:

nonatomic:

这两个参数,无论在MRC还是ARC下都可以使用,基本上使用nonatomic

2.retain:只能在MRC模式下,当属性的类型是OC对象是,绝大多数场景下使用retain

assign:在ARC和MRC下,当徐行的类型是非OC对象的时候,一律用assign

在MRC模式下,出现循环引用的时候,1边使用assign一边使用retain

#program mark - 13 弱指针在对象被回收以后自动设置为nil [掌握]

1.什么弱指针

在ARC下用__weak修饰的指针叫做弱指针

"随堂代码/13 弱指针在对象被回收以后自动设置为nil/1_弱指针自动变为nil

2. 弱指针在它指向的对象被回收以后自动设置为nil

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

__weak MKPerson * xiaoyueRou = nil;

NSLog(@"xiaoyueRou=%p",xiaoyueRou);

{

MKPerson *xiaoyue = [[MKPerson alloc] init];

NSLog(@"xiaoyue=%p",xiaoyue);

xiaoyueRou = xiaoyue;

NSLog(@"xiaoyueRou=%p",xiaoyueRou);

}

NSLog(@"xiaoyueRou=%p",xiaoyueRou);

[xiaoyueRou test];//给空指针发送任何消息都是没有效果

return 0;

}

//运行结果

2016-04-15 11:01:04.090 1_弱指针自动变为nil[1072:494299] xiaoyueRou=0x0

2016-04-15 11:01:04.091 1_弱指针自动变为nil[1072:494299] xiaoyue=0x100111490

2016-04-15 11:01:04.092 1_弱指针自动变为nil[1072:494299] xiaoyueRou=0x100111490

2016-04-15 11:01:04.092 1_弱指针自动变为nil[1072:494299] 人对象被释放了!

2016-04-15 11:01:04.092 1_弱指针自动变为nil[1072:494299] xiaoyueRou=0x0

3.补充 ARC下@autoreleasepool用法

1>你就当做一堆花括号用就可以了,内部所有内存管理代码,由编译器帮助实现,包括autorelease

//下面代码执行效果一模一样

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

@autoreleasepool

{

MKPerson *xiaoyue = [[MKPerson alloc] init];

}

{

MKPerson *xiaoyue2 = [[MKPerson alloc] init];

}

return 0;

}

2016-04-15 11:09:23.198 1_弱指针自动变为nil[1132:533415] 人对象被释放了!

2016-04-15 11:09:23.199 1_弱指针自动变为nil[1132:533415] 人对象被释放了!

2.在ARC下创建一个类,类方法生成对象,不需要再添加autorelease.

"随堂代码/13 弱指针在对象被回收以后自动设置为nil/2_ARC@autoreleasepool

//下面代码会报错

+(instancetype)person

{

return [[[self alloc] init] autorelease];

}

#program mark - 14 MRC和ARC的兼容

#program mark - 15 MRC程序转换为ARC程序 [听懂]

转换非常粗暴,极可能会出现问题,不要轻易去转

#program mark - 16 分类的简单使用 [掌握]

"强调

1.分类是干什么的?

当一个类包含了非常多属于不同范畴的方法的时候,此时我们通常将这个类用多个文件来实现.有一个类叫本类,剩余的叫做分类

2.练习:创建一个网络工具本类,YYNetworkTools,给这个类添加分类Download,负责下载.

上一篇:sqlserver函数


下一篇:css3动画由浅入深总结