#pragma mark - 00 知识回顾

1.@property + 类型 + 属性名 :执行的结果

1>在类的.m里面生成一个_属性名的属性

2>生成 _属性名 这个属性的set/get方法的声明和实现

注意:如果手动实现了属性的set/和get方法,那么@property不会生成属性

2.OC是弱语言

1>什么是弱语言,编译器的容错性强,有时候代码的逻辑是错的,编译的时候只会警告不会报错

3.动态类型/静态类型

1>是什么?

就是一个概念而已,形容一个指针

2>什么意思?

定义一个指针,指向一个OC对象,若这个指针的类型和这个指针指向对象的类型一致,叫静态类型

定义一个指针,指向一个OC对象,若这个指针的类型和这个指针指向对象的类型不一致,叫动态类型

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

//一个MKPerson类型的指针指向NSStrign类型的对象

//动态类型:这个指针的类型和这个指针指向对象的类型不一致

MKPerson *xiaoyue  = [NSString new];

//静态类型

MKPerson *xiaoyue2  = [MKPerson alloc] init];

return 0;

}

4. 编译检查/运行检查

"问题

int main()

{

double num_double =  1.1;

int *p =  &num_double;

return 0;

}

p是int类型的指针,但是p指向的是double类型的变量

1>是什么

1)编译检查: 程序运行之前的检查,就看这个对象的"类型"是否拥有某个属性/方法

2)运行检查: 程序运行过程中检查,就看这个对象的"真实类型"是否拥有某个属性/方法

"核心代码

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

{

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

//编译不报错的原因:编译检查xiaoyue 这个指针是MKPerson类型的,里面有name属性

//运行报错的原因:运行监测xiaoyue 这个指针是NSString类型的,里面没有有name属性

xiaoyue.name =  @"小明";

return 0;

}

5. id 指针 和 NSObject *  的比较

1>相同点

都是指针,能指向任意的OC的对象

2>不同点

1)id指针能够躲避编译检查,NSObject *不能躲避

"核心代码

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

id xiaoyue_id = [[NSString alloc] init];

NSObject * xiaoyue_obj = [[NSString alloc] init]; //多态

[xiaoyue_id setName:@"小明"];

//编译检测的时候检查NSObject里面有没有name属性,发现没有

[xiaoyue_obj setName:@"小明"];

return 0;

}

2)id指针是不能直接调用点语法的,如果一定要调用,需要强转

"随堂代码/00 知识回顾/5_id不能调用点语法

//下面代码报错

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

id xiaoyue_id = [[MKPerson alloc] init];

xiaoyue_id.name = @"小明";

return 0;

}

//下面代码没有问题如果强转了id类型的指针

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

id xiaoyue_id = [[MKPerson alloc] init];

[xiaoyue_id setName: @"小明"];

//

((MKPerson *)xiaoyue_id).name = @"小红";

NSLog(@"%@",((MKPerson *)xiaoyue_id).name);

return 0;

}

6.构造方法的复习

1>new方法里面做了什么 ---[[XXX alloc] init]

1)调用alloc方法,在堆区开辟空间,

2)调用init方法,初始化这块空间,把对象内所有属性成0或者nil

2>什么是构造方法

init方法就是构造方法

3>什么是重写构造方法

1)子类重写init方法,创建对象的时候调用自己重写之后的init方法

2)为什么要重写init方法

对于一个直接继承自NSObject的类,如果不重写init方法,那么对象创建的时候,对象内所有属性成0或者nil.

如果我希望创建对象的时候,里面的属性有一些事我希望的值,此时就应该重写init方法

MKPerson *xiaoyue = [[MKPerson alloc] init]

"练习

定义一个MKPerson类,有一个NSString _name属性,还有一个int _age属性,

创建一个对象,这个对象一创建出来,姓名就叫@"小明",年龄就是15;

//这样写不行:这块空间没有吧真实的init,没有初始化就用了,不安全

-(instancetype)init

{

_name = @"小明";

_age = 15;

return self;

}

//比较完美的写法

-(instancetype)init

{

self = [super init];

if(self != nil)//用来判断空间是否被初始化成功

{

_name = @"小明";

_age = 15;

}

return self;

}

//完美的写法

-(instancetype)init

{

if(self = [super init])//用来判断空间是否被初始化成功

{

_name = @"小明";

_age = 15;

}

return self;

}

4>什么是自定义构造方法

是一个可以初始化当前对象的方法,可以用来实现init的功能,可以想赋予初始值的属性,通过参数传递进来

"练习

定义一个MKPerson类,有一个NSString _name属性,还有一个int _age属性,

创建一个对象,这个对象一创建出来,姓名就叫什么年龄多大由调用者决定.

#program mark - 01 内存管理的概述 [掌握]

此知识点复习参见OC加强01视频笔记/01 内存管理的概述.pdf

"强调

1.内存分5个区,为什么OC开发只关心堆区?

1>堆区存储的是对象,不要以为对象就是Person/Student对象,一张图片/一段音频都是对象,通常比较大

2>问题不是大,关键是堆区的对象不会自动释放,如果你不手动释放,只有等到应用程序结束

2.什么时候要去释放堆区OC对象?

1>当这个OC对象没有"人"使用的时候,此时应该释放

2>当这个OC对象有"人"使用的时候,此时不应该释放

"人"的含义是这个对象的使用者

view就是一个对象,当需要显示view的时候就创建出来,当关闭的时候,如果以后不再使用,就应该释放

3.怎么判断一个对象有没有"人"在用 (对象什么时候释放)

1>OC中的对象有一个属性叫引用计数器,表示到底有多少"人"在使用这个对象.

2>程序员自己定义一个类创建对象,那么这个对象引用计数器为1

MKPerson *wuse = [MKPerson new];//对象引用计数器为1

3>程序员是可以控制对象的引用计数器/retainCount

1>向对象发送retain retainCount+1

2>向对象发送release retainCount-1

3>向对象发送retainCount 获取引用计数器的值

"注意

当一个对象的retainCount变为0,对象释放,操作系统才会去调用对象的dealloc方法,

4.ARC和MRC

1>MRC : manual reference counting 手动引用计数 "程序员自己去管理对象的retainCount"

2>ARC : automatic reference counting 自动引用计数 "编译器帮助我们管理对象的retainCount"

3>ARC和MRC的关系

1)ARC是基于MRC,本质上是相同的,都是在管理对象的retainCount.

2)ARC2011年ios5,推出的

3)xcode6以后创建的项目默认是ARC

4)学习MRC原因,成为大神,必须能看懂大神的代码,大神都是从MARC走过来的.

#program mark - 02 第1个MRC程序 [掌握]

此知识点复习参见OC加强01视频笔记/02 第1个MRC程序.pdf

"强调

1.写MRC项目,必须关闭ARC

2.为什么重写对象的dealloc方法,要在最后调用[super dealloc]?

[super dealloc]一调用,对象的这块空间,可能就不能用了!

3.注意

1>release是让对象的引用计数器-1,不是释放对象

2>dealloc方法,是对象将要释放的那一刹那调用的,操作系统在对象的retainCount为0的时候自动调用的 ,程序员不要自己手动调用

#program mark - 03 内存管理的原则 [掌握]

此知识点复习参见OC加强01视频笔记/03 内存管理的原则.pdf

"强调

内存管理的原则

1.alloc/new两种方式创建出来的对象,retainCount默认为1.一般要对应一次releae,写在main函数即将结束的地方.

2.retain次数和release次数一定要平衡,对象被retain一次,就要release一次

"核心代码

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

MKPerson *wuse = [[MKPerson alloc] init];//1

[wuse retain];//2

[wuse release];//1

[wuse release];//0

return 0;

}

3,那个指针使用了对象,就用那个指针发送retain消息

4,那个指针retain了对象,就用那个指针release

"核心代码

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

MKPerson *wuse = [[MKPerson alloc] init];//1

MKPerson *dashi = wuse;

[dashi retain];//2

[dashi release];//1

[wuse release];//0

return 0;

}

#program mark - 04 野指针与僵尸对象 [掌握]

此知识点复习参见OC加强01视频笔记/04 野指针与僵尸对象.pdf

"强调

1.僵尸对象和野指针的关系

1)野指针指向的不一定是对象,C语言中没有对象概念,但是有野指针的概念

int main()

{

int *p;

*p = 10;

return 0;

}

2)OC中,指向的是一个僵尸对象的指针叫做野指针.

2.僵尸对象使用注意

僵尸对象就是一块当前应用程序没有资格再去访问的堆区空间,这块空间只能由操作系统访问,访问与否,在于操作系统.

#program mark - 05 单个对象的内存管理 [掌握]

此知识点复习参见OC加强01视频笔记/05 单个对象的内存管理.pdf

"强调

1.什么是内存泄露?

一个对象在没有人使用的情况下,没有释放,始终存在于内存,当程序结束释放

2.什么时候OC对象会内存泄露 --> 违反了内存管理原则

1>new/alloc出来的对象,没有对应的release

2>有retain但是没有对应的release

3>在retainCount变为0之前,指针被改掉了

4>不要在对象当做参数传递的时候,在方法中随意的retain对象.

#program mark - 06 多个对象的内存管理之一 [掌握]

此知识点复习参见OC加强01视频笔记/06 多个对象的内存管理之一.pdf

"强调

"核心代码

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

MKPerson *xiaoyue = [MKPerson personWithName:@"MK"];

MKCar *benz = [MKCar carWithSpeed:110];

xiaoyue.car = benz;

[xiaoyue drive];

[benz release];

[xiaoyue drive];

[xiaoyue release];

return 0;

}

当一个对象A拥有一个属性是另外一个对象B,如果A没有释放,此时B就不应该释放,因为B作为A的一个属性,A随时有可能调用B的方法

解决:调用A中B的set方法的时候,set方法中应该给对象B发送retain消息,在A的dealloc方法中给对象B发送release消息

1>

//车属性的set方法

-(void)setCar:(MKCar *)car

{

_car = car;

[_car retain];

}

-(void)dealloc

{

NSLog(@"名字叫做%@的Person对象释放了",_name);

[_car release];

[super dealloc];

}

#program mark - 07 多个对象的内存管理之二 [掌握] [讲]

一个现象.

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

MKPerson *xiaoyue = [MKPerson personWithName:@"MK"];

MKCar *benz = [MKCar carWithSpeed:110];

xiaoyue.car = benz;

[xiaoyue drive];

benz.speed =  120;

xiaoyue.car = benz;

[benz release];

[xiaoyue release];

return 0;

}

如果重复给人对象里面的车属性赋值,导致车重复的retain

解决:在人的车属性的set方法中,对传进来的车对象进行判断,如果不是之前的车就不进行retain.

"核心代码

-(void)setCar:(MKCar *)car

{

if(car != _car)

{

_car = car;

[_car retain];

}

}

#program mark - 09 多个对象的内存管理之三 [掌握]

现象:下面代码benz车无法释放,给人对象的车属性赋予新的值,老的值没有释放

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

MKPerson *xiaoyue = [MKPerson personWithName:@"MK"];

MKCar *benz = [MKCar carWithSpeed:110];

xiaoyue.car = benz;

[xiaoyue drive];

MKCar *BMW = [MKCar carWithSpeed:111];

xiaoyue.car = BMW;

[xiaoyue drive];

[xiaoyue release];

[benz release];

[BMW release];

return 0;

}

解决:在新的属性修改之前,对老的属性做一次release

//车属性的set/get方法

-(void)setCar:(MKCar *)car

{

if(_car != car)

{

[_car release];

_car = car;

[_car retain];

}

}

#program mark - 10 当属性的类型是OC对象的时候,setter方法的写法 [掌握]

此知识点复习参见OC加强01视频笔记/10 当属性的类型是OC对象的时候,setter方法的写法.pdf

注意点:

1.内存管理的目标是OC中的对象,不是OC对象是不需要进行release/retain的.

2.代码优化,对Person内部的NSString对象属性,也需要内存管理

OC加强-day01的更多相关文章

  1. day01 python起源 介绍 解释器 变量 流程控制if

    day01 python   一.python的起源     1.python简介     java 企业级应用, android, app     c 操作系统, 做开发语言的, 游戏的内核     ...

  2. iOS代码规范(OC和Swift)

    下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...

  3. 用C语言封装OC对象(耐心阅读,非常重要)

    用C语言封装OC对象(耐心阅读,非常重要) 本文的主要内容来自这里 前言 做iOS开发的朋友,对OC肯定非常了解,那么大家有没有想过OC中NSInteger,NSObject,NSString这些对象 ...

  4. 嵌入式&iOS:回调函数(C)与block(OC)传 参/函数 对比

    C的回调函数: callBack.h 1).声明一个doSomeThingCount函数,参数为一个(无返回值,1个int参数的)函数. void DSTCount(void(*CallBack)(i ...

  5. 嵌入式&iOS:回调函数(C)与block(OC)回调对比

    学了OC的block,再写C的回调函数有点别扭,对比下区别,回忆记录下. C的回调函数: callBack.h 1).定义一个回调函数的参数数量.类型. typedef void (*CallBack ...

  6. WebViewJavascriptBridge源码探究--看OC和JS交互过程

    今天把实现OC代码和JS代码交互的第三方库WebViewJavascriptBridge源码看了下,oc调用js方法我们是知道的,系统提供了stringByEvaluatingJavaScriptFr ...

  7. OC泛型

    OC泛型 泛型是程序设计语言的一种特性,他主要是为了限制类型的,比如OC中的数组,你可以限制他里面装的是NSString类型,泛型的话JAVA和C++都有的,大家要是对泛型不了解的话可以去百度一下. ...

  8. iOS学习15之OC集合

    1.数组类 1> 回顾C语言数组 数组是一个有序的集合, 来存储相同数据类型的元素. 通过下标访问数组中的元素,下标从 0 开始. 2> 数组 数组是一个有序的集合,OC中的数组只能存储对 ...

  9. JS 与OC 交互篇

    完美记录交互 CSDN博客: (OC调用JS) http://blog.csdn.net/lwjok2007/article/details/47058101 (JS调用OC) http://blog ...

随机推荐

  1. 最短路(数据处理):HDU 5817 Ice Walls

    Have you ever played DOTA? If so, you may know the hero, Invoker. As one of the few intelligence car ...

  2. Java如何将Exception.printStackTrace()转换为String输出

    package com.test1; import java.io.PrintWriter; import java.io.StringWriter; public class T010 { /** ...

  3. Toad for Oracle 使用文档

    Toad®for Oracle 版本 12.0.1 发行说明 30 July 2013 目录 欢迎使用 Toad for Oracle 版本更新 解决的问题和改进 已知问题 第三方已知问题 升级和兼容 ...

  4. Oracle错误

    System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本 这个是我页面报的错误,请帮解答 在错误出现的时候我第一时间现在了一个oracle客户端软件,然 ...

  5. 2D游戏编程5—锁定频率

    核心利用win心跳函数GetTickCount利用差量锁定fps,如下代码锁定30fps,缺点为如果计算机不能以30fps运行,程序将低于30fps #define WIN32_LEAN_AND_ME ...

  6. bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4637  Solved: 1726[Submit][Status ...

  7. Log接口的重新封装

    闲来没事,看见当前的项目的日志形式有点冗余,每个类都需要声明确实有点繁琐, 因此重新将logback重新封装一下,供整个工程共享使用,版本是1.0.9. 代码如下: import java.lang. ...

  8. Git 版本控制工具(学习笔记)

    GIT(分布式) 一.Git 初始版本控制工具 1. 安装Git Ubuntu系统下,打开shell界面,输入: sudo apt-get install git-core  之后回车输入密码,即可完 ...

  9. DataGridView减少闪烁的解决办法

    Reducing flicker, blinking in DataGridView http://www.codeproject.com/Tips/390496/Reducing-flicker-b ...

  10. shell查找文件并删除

    -mtime 0 表示文件改动时间距离当前为0天的文件.即距离当前时间不到1天(24小时)以内的文件. -mtime 1 表示文件改动时间距离当前为1天的文件,即距离当前时间1天(24小时-48小时) ...