首页 > 代码库 > OC汇总

OC汇总

(一)

(1)import带预处理,防止重复包含,include需要手写。

(2)import是引入,@class是声明这个类。

(3)Foundation/Foundation.h包含了其他大量的头文件。

(4)类方法无法访问到成员变量,但是好处很多,当不依赖成员变量的时候,多用类方法。

(5)对象new出来后做了三件事。分配空间,初始化成员变量,返回这个对象。初始化的时候,如果成员变量是基本类型,初始化0,字符串初始化null。

   变量是保存在堆区的,对象是保存在代码区的,指针是存放在栈区的 (P,P1)。

技术分享

(6)类方法可以从父类继承而来,然后可以重写。例如descriotion方就是一半子类重写的。且类方法的self就是类,对象方法self就是对象。

7)封装:当一个类把自己的属性暴露给外部的时候,就失去了对属性的控制权。不应该随意被外部修改。@interface就是展示的接口,@implementtation就是具体封装的实现。苹果底层好多c++和c,不容易看懂。

封装原理:实例变量默认只能被当前类的对象方法访问。不允许箭头直接访问。设置变量的值/获取变量的值都需要用方法。

封装实现步骤:设置成员变量的getter和setter。说白了就是@interface@end里面的{}里面定义的_name等是不安全的。set方法给外界提供一个设置变量的方法。get是访问的方法。在set方法里面就可以对一些不合理的值进行过滤。Set是写,Get是读。

技术分享

 

(8)方法重载:方法名一样,参数类型个数不一样,OC是不支持的。swift支持。但是OC可以多个:来做成名字不一样的情况。

(9)static:实例变量不能声明为static静态的。但是局部变量用static修饰后,可以保存方法上一次的值。也可以放在。M。H的外面变成静态的全局变量。这个变量只能在当前文件中应用。

(10)self和super:self在对象方法中就是调用方法的对象,在类方法中就是当前类。

(二)

(1)继承和派生:继承就是父类子类,假如最大的基类是交通工具,那么又有两个互相独立的汽车/飞机类,这俩就算是派生类。

子类不能定义和父类同名的变量,但是可以继承父类的变量。

(2)OC继承是单继承。

(3)方法的重写:子类重新实现父类的方法。会先看当前类,然后再看父类,逐层找。

(4)实例变量修饰符:修饰作用于。分为@public(任意程序) @protected (同一类和派生类)@private(同一类)。默认是受保护的。

技术分享

尤其是@private可以被继承,但是不能访问(能看到加着下划线呢)。

5OC的私有变量/私有方法:在。m中声明的成员变量,此时用@public也没用,因为根本不包含。

6)description描述方法:重写后打印不同的值。

7)多态: 不同的对象以自己的方法响应相同名称方法的能力叫做多态,多态就是某一类事物的多种形态。狗既是狗类,也属于动物。

说白了就是猫,狗,动物都有run方法,自己run的实现方式不同。

在程序里可以选择到底实现哪个run方法。

多态的条件:有继承关系(AB父类子类),有方法重写(run,run)

然后父类指针指向子类对象。

就是动物(父亲) = NEW,这样就用狗的 run了。

多台的好处是简化了编程接口。允许类和类之间重用一些命名,而不是每一次给函数新增名字。

Id obj = [任意 new],这样obj继承NSObject,拥有了任意对象的方法。也算是一种多态的体现。

技术分享

 

8)类的本质:也是一个对象。称类对象。Peron类也是对象,类对象(是Class类型的)、p则是实例对象。类对象在程序运行一直存在,自打第一次导入后一直存在。类对象是一种数据结构,里面是类的基本星系,大小,名字,函数。

9)sel类型:标示方法存储的位置。执行方法的时候,先把方法包装成sel,然后找到方法地址,然后调用方法。

(三)

1)传统get/set/{}下划线写法

技术分享

 

一直需要调用set/get方法,所以需要点语法。点语法也不是直接访问,点语法就是set/get方法。

点语法小心在set/get方法里用self变成死循环。

2@property:一个指令,声明属性的getter/setter。这样就自动生成setter/getter

写在@interface@end中。

3@synchronized:在以前@property只是实现set和get声明,@syn是在.m实现。不过现在都是一句话了。

技术分享

(四)

1)动态类型/静态类型:

动态类型:程序直到执行时才确定所属的类(多态)(Person *p = nan new)这个就是运行时检查。

静态类型:将一个变量定义为特定的类型,编译的时候就知道类型(Person *p = Person new)这个就是编译时检查。

2)id/instancetype类型:

相同点:都可以作为返回类型

不同点:id返回的是未知类型,可以作为参数,ins只能作为返回类型。

3)iskindoclass/isMemoryofclass

iskindoclass:是这个类

isMemoryofclass:判断对象是否是指定类的实例。

4)响应方法

判断对象能否响应方法:respondsToSelector:有就执行,没有就算了。

判断类是否有这个方法:类方法,instancesRespondToSelector

调用方法:performSelector:

5)构造方法:用来初始化对象的方法。重写的目的就是让对象一出来,成员变量就有一些固定的值。

就是拆new方法变成alloc init。init来构造。构造后,init返回对象本身。

技术分享

 

当子类写了init,父类的init就被覆盖了,所以要先调用一下父类的。

Super init 其实是个地址,就是判断父类是否初始化成功,不为空就成功了。

6)自定义构造方法:减号,返回值id,用With合体。

技术分享

(五)内存管理

(1)分配内存是堆区的。内存由上到下是栈/堆/BSS段/数据/代码。

  堆是运行的时候动态分配的存储空间。

 栈是局部变量。

 BSS是没初始化的全局/静态。

 数据区是已经初始化的全局/静态/字符串。

 代码是编译后的代码段。

(2)管理的就是对象。其他局部变量是在栈中的。代码结束的时候自动释放了。所以管理的就是堆区的内容。

(3)内存管理原则:一个对象都可能有一个或者多个所有者,只要有所有者,就有引用计数就会继续存在。每一个OC对象都有一个8字节的引用计数器存储空间。

(4)野指针:堆空间已经释放后,在调用方法。野指针错误就是访问了一块儿已经回收了的,不可用的内存。

(5)僵尸对象:一个对象已经被销毁了。指向僵尸对象的指针就是野指针。系统默认不开启僵尸对象检测,因为影响效率。

(6)空指针:没有指向任何东西的指针,给空指针发消息不会出错。

   nil:给对象赋值的。 A nill pointer to an OC object。

   Nil:给类对象赋值。

   NULL:是一个泛型指针。给一个值变量付空。

   NSNull:是一个对象,用于不能使用nil的空间。

(7)一个对象已经释放了,就不可能再引用+1复活了。

(六)@property

(1)作用就是定义量,生成set/get。

(2)技术分享

3@class:声明是一个类。 .h @class,在.m import这个类的.h

.h张如果import引入了头文件的内容.h,拷贝在了.h这个位置。

其实就是全部复制粘贴了一个头文件。此时如果很多类都导入了Person。此时当Person头文件发生变化是,所有引入的类都给重新拷贝和编译。所以@class比较好,然后在.m时候引用就是了。这样起码效率提高一半,只是在运行时候检查.h

@class还可以解决循环引入问题A-B互相引用。

(七)NSString内存管理问题:

1)直接@“”或者stringWithString@""或者alloc initWithString :都是在常量区分配,此时如果@的内容一样,那地址就一样的。

2)strigWithFormat:或者alloc initWithFormat是在堆区。

(八)ARC

1)指针分类:强弱。默认都是强。

2ARC自动插入rerain,release,autorelease。

3)判断准则:只要没有强指针指向,就释放。当释放的时候,把指向它的弱指针滞nil。并且是立即释放。

4)在多个对象的话:对象A拥有对象B,用strong。因为弱指针就不是拥有了。此时B要是没了,A也不会有这个属性了。

5)循环引用:

*ARC下循环引用:人有狗,strong。狗有主人,strong。就循环了。所以要设置一个weak。

*ARCset方法内存@property参数:

技术分享

 

(6)super dealoc在arc不能用。

(7)写了一行代码,对象后如果立即释放了,那shuo‘min说明是弱指针了。

(九)分类Catrgory:给一个类拓展方法。构成工具类。在不修改原有类的基础上增加新的方法。

(1)目的:

        *扩展现有类。

        *作为子类的替代,直接弄一个类方法。

        *对类中的方法归类。

(2)注意:

*分类可以增加方法,但是不能增加属性(直接报错了),如果是@property属性编译不报错,运行报错。

*分类的方法可以用 原类的属性。

*分类和原类同名的方法,优先分类的。

*很多分类同名,那么执行的是最后一个编译的方法。此时需要选中项目,看.m从上到下依次编译的。

(3)分类非正式协议:

*给NSObject(或其子类Foundation框架中的,也就是我们用的系统的)定义分类,称非正式协议。例如统计NSString个数。(Foundation框架就是一个基础框架,提供了OC的数组,字典,日期,时间,NS的各种东西)。例如给NSObject +一个eat吃的方法。

(4)分类的延展(Extension ):

*正常是 @interface NSString (分类名)

*延展是分类的特例,@interface MyClass (),是没有分类名的。

*不但可以增加方法,也可以增加属性。

技术分享

*延展类只有.h  实现还是在原类中实现。

*分类和延展的区别:

技术分享

 

*通过延展实现方法私有,只是头文件独立,把头文件方法声明藏起来罢了。这种方法不能实现真正的方法私有,因为一导入延展头文件,就可以调用私有方法了。

*最常用的.m中添加属性就是这么完成的。方法私有。这种和独立文件,然后原类中实现方法道理是一样的。工作了这么久,原来是这个样子。。

技术分享

 

(十)Block

1Block类型是一个C级别的语法和运行机制。Block包含和一组状态的数据,这些数据在程序执行的时候用于对行为产生影响。说白了就是一个代码段。

2)基本用法:

*格式:

技术分享

 

*typedef定义一个Block类型:

3)访问外部变量:

*栈区是最长的。常量区是前面0多,堆区是后几位才有内容。

*如果外部是全局变量,那Block是直接可以修改这个值的。(全局是在代码块外面定义)。

*假如外部变量是int什么的常量区,存在栈,位置最大。在Block访问的时候,是在堆区。当建立Block的时候,会把外部变量的值以const拷贝放在自己所在的内存区域中。(const就是不能修改的意思)。此时在Block里面修改外部变量是会报错的。

*Block内部定义新的变量:其实就相当于在代码块里定义变量,就会保存在栈区了。哪怕和外部名字一样,也是局部变量屏蔽了外面的变量。

*Block修改外部的值:外部变量 --block修饰。此时,内部访问外部的时候,还是对外面copy了一份在Block自己的内存。只是不在已const的方式拷贝,所以可以修改。不过此时修改后,外部变量再也不是栈区了,会变成堆区空间。但是一般是不会这么修改外部的值的。

4)类型:(了解)

*全局Block:定义在函数外面,或者在内部但是没有引用任何变量。

*Block:看是否引用了外部变量。

*Block:对栈Blockcopy来的。

5Block应用:

*可以当做参数传递,封装好一段完整的代码,在需要的时候执行,避免代码冗余。

*可以当做返回值

(十一)协议:Protocol(正式协议)

1)概念:声明一些必须实现和选择实现的方法。然后一个类遵守协议,就应该实现这个协议中的方法。

2)默认遵守基协议NSObject。用xocde生成协议的之后,是只有.h的。因为实现都是遵守协议的人做的事。

技术分享

 

3)协议之间可以继承。<>初始都是继承NSObject协议(基协议。定义了class。~~isKindOfClass等等)

4)类如果继承了协议,子类也能实现协议方法。

5)协议可以过滤一些要求,遵守了协议的,满足我要求的才可以。此时可以做设置:

技术分享

 

此时就类似泛型,可以筛选出符合要求符合协议的对象。

6)protocol代理设计模式:控制器是爸爸,代理一切。别的控件的代理都是控制器,让控制器来实现各种协议方法。例如tableView本身没有来修改一些属性的资格,但是可以让控制器来成为代理,修改tableView属性。

*顾名思义。手机端控制器很多,控制器正向传值可以直接传递,逆向传值就可以用到代理了。传入的对象,代替当前类完成了某个功能,称为代理模式。

技术分享

 

(十二)Foundation框架(各种NS:

1NSString

*判断字符串是否相等 不能用 ==号。因为如果是@写法,在常量区,那一般是相等的。但是Format都是在堆区的,地址肯定是不一样的。 == 判断的不是内容,是地址。所以用isEqualToString,这个是比较内容,区分大小写的。

*前缀后缀:hasPrefix是前缀。hasSuffix是后缀。

*检查字符串是否包含了另一个字符,包括正向查找和反向查找。

正向是  @“A”rangeOfString"B"

*字符串截取:

技术分享

*字符串替换:

技术分享

 

OC汇总