1.堆空间里的内存是系统自己管理与回收,栈区的数据一般不用自己去管,系统会自动回收
1>每个OC对象内部有4个字节的存储空间来存储引用计数器
2>main函数有一个循环
3>retain 调用返回对象本身
4>野指针和空指针:指向不可用内存的指针的指针是野指针
5>EXC_BAD_ACCESS:访问了一块坏的内存(已经被回收,已经不可用的内存)
p = nil :清空指针
OC中不存在空指针操作
原则:
1>你想使用某个对象,就应该让计数器(对象+1)(让对象做一次retain操作)
2>你不想在使用(占用)某个对象,就应该让对象的计数器-1(让对象做一次release)
3>谁retain,谁release
4>谁alloc,谁release
内存管理代码规范:
1>只要调用了alloc,必须release(aoturelease)
2>如果对象不是通过alloc创建的,就不必须要有release
set方法的代码规范
1>基本数据类型:直接复制
- (void)setAge:(int)age
{
_age = age;
}
2>OC对象类型
-(void)setCar:(Car *)car
{
1.先判断是不是新传进来对象
if (car!=_car)
{
2.//对旧的对象做一次release
[_car release];
3.//对新对象做一次retain
[car retain];
}
}
dealloc方法的代码规范
1>一定要[super dealloc],而且放到最后面
2>对self(当前)所有的其他对象做一次release
-(void)dealloc{
[_car release];
[super dealloc];
}
基本数据类型是不需要管理内存的
retain:生成的set方法里面,release旧值,retain新值
Property参数:
1.内存管理相关的参数
*retain:release旧值,retain新值
*assign:
*copy:
2.是否要生成set方法
3.多线程管理
4.sette和getter方法的名称
@class的作用:仅仅告诉 编译器,声明一个类,类里的东西不知道
开发中引用一个类的规范:
1>在.h文件中用@class来声明类
2>在.m文件中用#import来包含类的所有东西
两端循环引用解决方案:
1>一端用retain----strong
2>一端用assign---weak
@class和import的区别:
#import方式会包含被引用类的所有信息,包含被引用类的变量和方法,@class方式只是告诉编译器在A.h文件中B *b只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息
如果有上百个头文件都#Import 了同一个文件,或者这些文件一次被#import,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来讲,使用@class方式就不会出现这种问题了。
在.m实现文件中,如果需要引用到被引用类的实例变量或者方法时,还需要使用#import方式引入被引用类.
aoturelease:半自动释放,不会改变对象的引用计数器
1>aoturelease方法会返回对象本身
基本用法:
1>会将对象放到一个自动释放池中
2>当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
3>会返回对象本身
4>调用完autorelease方法后,对象的计数器不变
好处:
1>不用再关心对象释放的时间
2>不用再关心什么时候调用release
autorelease使用注意:
1>占用内存较大的对象不要随便使用autorelease
2>占用内存较小的对象使用autorelease,没有太大影响
错误写法:
1>alloc之后调用了autorelease,又调用release
2>连续多次调用autorelease
自动释放池
1>在ios程序运行过程中,会创建无数个池子,这些池子都是以栈结构存在(先进后出)
2>当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池
1、系统自带的方法里面没有包含alloc/new/copy,说明返回的对象都是aoturelease的
2、开发中经常会提供一些类方法,快速创建一个已经aoturelease过的对象
1>创建对象时不要直接用类名,一般用self
总结:dealoc不要直接调用,这个一般要系统自己调用
ARC:
1.ARC是编译器特性:有alloc,就会自动在合适的地方插入release,进行内存管理
2.ARC判断准则
1>只要没有强指针指向对象,就会释放对象
2>指针分两种:没有强指针指向的对象,会马上释放
强指针:默认情况下是所有指针都是强指针__strong
弱指针:弱指针是不能决定对象要不要释放。只要弱指针指向对象不存在,就会直接销毁对象。__weak
当弱指针指向的对象被销毁时,指针会自动被置为nil
ARC特点:
1>不允许调用release.retain,retainCount
2>允许重写dealloc,但是不允许调用[super dealloc]
3>property的参数
*strong:成员变量是强指针(适用于OC对象类型)
*weak:成员变量是弱指针(适用于OC对象)
*assign:适用于非OC对象类型
4>以前的retain,改为strong
MRC 与 ARC 互转:
-fno-objc-arc,不使用ARC
-f-objc-arc,使用ARC
两端循环引用的时候,解决方案:
1>ARC
1端用strong,另一端用weak
2>非ARC
1端用retain,另一端用assign
OC程序完全兼容C语言
NSLog输出内容会自动换行
#include 与 import对比
1>import的用途:
1.跟include用途一样,拷贝文件内容
2.可以自动防止文件的内容被重复拷贝
2>include:会重复拷贝内容
NSObjcRuntime.h 中有NSLog函数的声明
包含主头文件就可以使用这个框架的东西
运行过程:
1>编写OC源文件:.m、.c
2>编译:cc -c xxx.m xxx.c
3>链接:cc xxx.o xxx.o -framework Foundation
(只有用到了Foundation框架才需要加上 -framework Founfation)
4>运行:./a.out
链接应该是将所有的可执行文件+函数库联系在一起,生成一个可执行文件
主头文件:
1>主头文件:最主要的头文件,名字一般跟框架名称一样,包含了框架中的所有其他文件
2>Foundation框架的主头文件名称就是Foundation.h
3>只需要包含Foundation框架主头文件,就可以使用整个框架的东西
思想
1.面向对象和面向过程的区别
常用术语:
1>面向过程:Procedure Oriented
2>面向对象:Object Oriented,简称OO.解决问题的核心就是对象
3>面向对象过程:Object Oriented Programming,简称 OOP
类与对象
类是抽象的,对所有相同属性的一个概括
类就相当于是图纸 — 制作汽车架构的图纸
对象是类的具体存在
开发步骤:
1>先分析项目中需要什么,再设计相应的类:类中包括属性和相应的行为
类的设计只关心三件事
1>事物名称(类名):人
2>属性:age,name
3>行为:eat,run
set方法:
1.作用:提供一个方法给外界设置成员变量值,可以在方法里面对参数进行相应过滤
2.命名规范:
1>方法名必须以set开头
2>set后面跟上成员变量的名称,成员变量的首字母必须大写
3>返回值一定是void
4>一定要接收一个参数,而且参数类型跟成员变量类型 一致
5>形参的名称不能跟成员变量名一样
get方法:
1.作用是返回对象内部的成员变量
2.命名规范:
1>肯定有返回值,返回值类型肯定与成员变量类型一致
2>方法名跟成员变量名一样
3>不需要接收任何参数
面向对象三大特性
成员变量的封装,继承,多态
封装好处
1.把不想被别人了解的代码细节封装起来,为了保证代码的安全性
类方法与对象方法 的区别:
类方法只能用类来调用
1>对象方法
1.减号 -开头
2.只能由对象来调用
3.对象方法中能访问当前对象的成员变量
2>类方法
1.加号 +开头
2.只能由类来调用
3.类方法中不可访问成员变量
类方法的好处与使用场合
1>不依赖与对象,执行效率高
2>能用类方法尽量使用类方法
3>场合:当方法内部不需要使用成员变量时,就可以改为类方法
可以允许类方法和对象方法同名
继承的好处
1>抽取重复代码
2>建立了类之间的关系
子类可以拥有父类的所有的成员变量和方法
注意点
1>基本上所有的根类是NSObject
2>OC中不允许子类和父类有相同的成员变量
3>调用某个方法时,优先在类中找,找不到再去父类中找
重写:子类重写实现父类的某个方法,就是覆盖掉父类以前的方法
集成耦合性太强
继承的使用场合:
1>当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中。
2>当A类中拥有B类中的部分属性和方法时,可以考虑让B类继承A类
继承与组合:
继承:xx是xx
组合:xxx拥有xxx,当继承不合理的时候,通过组合也可以拥有继承的功能
super的作用
1>直接调用父类中的某一个方法
2>如果super处在对象方法中,那么就调用父类的对象方法
如果处在类方法中,那就调用父类的类方法
super使用场景:子类重写父类的方法时想保留父类的一些行为
多态:多种形态,父类指针指向子类对象
1>想实现多态就必须有继承
多态的好处:
1>可以将多个方法整合成一个函数
2>可以用一个父类类型指向多个多个对象
多态的局限性:
1>父类类型的变量,不能用来调用子类的方法。如果想要调用子类的方法,必须要进行相应类型的强转
2>通过强制转换
多态:
1>没有继承就没有多态
2>代码的体现:父类类型的指针指向子类对象
3>好处:如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象
init方法:
构造方法:用来初始化对象的方法,是个对象方法,-开头
重写构造方法的目的:为了让对象创建出来,成员变量就会有一些固定的值
重写构造方法的注意点:
1.先调用父类的构造方法[super init]
2.再进行子类内部成员变量的初始化
+load(当加载类到内存中的时候,开始调用)
+initial(当第一次使用这个类的时候开始调用)
类也是类对象[NSObject class];[p class]
_cmd代表当前方法
SEL其实就是对方法一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法。
description
有-方法和+方法-方法,描述实例的属性
+方法,描述类的属性