#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,负责下载.