OC加强-day01
#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的更多相关文章
- day01 python起源 介绍 解释器 变量 流程控制if
day01 python 一.python的起源 1.python简介 java 企业级应用, android, app c 操作系统, 做开发语言的, 游戏的内核 ...
- iOS代码规范(OC和Swift)
下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...
- 用C语言封装OC对象(耐心阅读,非常重要)
用C语言封装OC对象(耐心阅读,非常重要) 本文的主要内容来自这里 前言 做iOS开发的朋友,对OC肯定非常了解,那么大家有没有想过OC中NSInteger,NSObject,NSString这些对象 ...
- 嵌入式&iOS:回调函数(C)与block(OC)传 参/函数 对比
C的回调函数: callBack.h 1).声明一个doSomeThingCount函数,参数为一个(无返回值,1个int参数的)函数. void DSTCount(void(*CallBack)(i ...
- 嵌入式&iOS:回调函数(C)与block(OC)回调对比
学了OC的block,再写C的回调函数有点别扭,对比下区别,回忆记录下. C的回调函数: callBack.h 1).定义一个回调函数的参数数量.类型. typedef void (*CallBack ...
- WebViewJavascriptBridge源码探究--看OC和JS交互过程
今天把实现OC代码和JS代码交互的第三方库WebViewJavascriptBridge源码看了下,oc调用js方法我们是知道的,系统提供了stringByEvaluatingJavaScriptFr ...
- OC泛型
OC泛型 泛型是程序设计语言的一种特性,他主要是为了限制类型的,比如OC中的数组,你可以限制他里面装的是NSString类型,泛型的话JAVA和C++都有的,大家要是对泛型不了解的话可以去百度一下. ...
- iOS学习15之OC集合
1.数组类 1> 回顾C语言数组 数组是一个有序的集合, 来存储相同数据类型的元素. 通过下标访问数组中的元素,下标从 0 开始. 2> 数组 数组是一个有序的集合,OC中的数组只能存储对 ...
- JS 与OC 交互篇
完美记录交互 CSDN博客: (OC调用JS) http://blog.csdn.net/lwjok2007/article/details/47058101 (JS调用OC) http://blog ...
随机推荐
- hive中sql解析出对应表和字段的调查
---恢复内容开始--- .阿里的druid中的sql parser有各种关系数据库sql的解析,但hive的不支持. druid初期的版本中是包含hive的,将以前版本中的hive dialect对 ...
- Git起步--git安装与初次运行git前配置
在你开始使用 Git 前,需要将它安装在你的计算机上. 即便已经安装,最好将它升级到最新的版本. 你可以通过软件包或者其它安装程序来安装,或者下载源码编译安装. 一.Git安装 1. 在linux上安 ...
- HDOJ/HDU 1556 Color the ball(树状数组)
Problem Description N个气球排成一排,从左到右依次编号为1,2,3-.N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电动车从 ...
- Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对
题目:http://codevs.cn/problem/3286/ 3286 火柴排队 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : ...
- 制作静态库文件(.a文件)
制作静态库文件(.a文件) 1.创建静态库工程: 在Xcode中new一个新的project,选择IOS下面的Framework&Library,下面有一个Cocoa Touch Static ...
- html自定义checkbox、radio、select —— checkbox、radio篇
前些日子,所在公司项目的UI做了大改,前端全部改用 Bootstrap 框架,Bootstrap的优缺点在此就不详述了,网上一大堆相关资料. 前端的设计就交给我和另一个同事[LV,大学同班同学,毕业后 ...
- Mysql导出导入乱码问题解决
MySQL从4.1版本开始才提出字符集的概念,所以对于MySQL4.0及其以下的版本,他们的字符集都是Latin1的,所以有时候需要对mysql的字符集进行一下转换,MySQL版本的升级.降级,特别是 ...
- 8-7-Exercise
链接:第二次小练 这次是我们这组出的题目~我出了一道......B-Prison rearrangement,感觉有点复杂~不过其实题目想通了还是很简单的...... @荆红浅醉出的是A.C.D,@从 ...
- CSS 最核心的几个概念
CSS 中最核心的几个概念,包括:盒模型.position.float等. 这些是 CSS 的基础,也是最常用的几个属性,它们之间看似独立却又相辅相成. 元素类型 HTML 的元素可以分为两种: 块级 ...
- 关于list、set、map的几点总结
用法: 1. 如果涉及到堆栈,队列等操作,应该考虑用List, 对于需要快速插入,删除元素,应该使用LinkedList, 如果需要快速随机访问元素,应该使用ArrayList.2. 如果程序在单线程 ...