OC知识点碎片

  • #import 有两个用途,第一个用途:与 C 语言中的 include 完全一样。第二个用途:可以自动防止文件内容被 重复拷贝,也就是说多次书写#import <Foundation/NSObjCRuntim.h>就只拷贝一次,相当于只写了一次。
  • OC 与 C 语言完全兼容,其入口也为 main 函数,定义方法与 C 语言完全一样。
  • Object C 的代码中可以混入 C 语言代码,Object C 文 件后缀名为.m,把其后缀名改为.mm 还可以混入 C++代码

  • 1、对象方法

(1) 减号 - 开头
(2)只能由对象来调用 (3)对象方法中能访问当前对象的成员变量(实例变量)

2、类方法
(1) 加号 + 开头
(2) 只能由类(名)来调用
(3) 类方法中不能访问成员变量(实例变量)

3、类方法的好处和使用场合
(1) 不依赖于对象,执行效率高
(2) 能用类方法,尽量用类方法
(3) 场合:当方法内部不需要使用到成员变量时,就可以改为类方法

注:可以允许类方法和对象方法同名,不能使用指针去访问类方法,会报错。类方法和成员(对象)方法可以同名
  • self 的用途:

(1) 谁调用了当前方法,self 就代表谁

* self 出现在对象方法中,self 就代表对象

* self 出现在类方法中,self 就代表类

(2) 在对象方法利用"self->成员变量名"访问当前对象内部的成员变量

(3) [self 方法名]可以调用其他对象方法\类方法

  • 使用 self 与 super 调用方法的区别:

使用 self 调用方法时,self 先从当前类中寻找方法,如果没有寻找到再去父类中寻找。而 super 直接在父类中 寻找方法。

 

注:super指向的是self,比如 [self class] 和 [super class]获取的class是同一个
  • 继承的好处:

(1) 抽取重复代码
(2) 建立了类之间的关系
(3) 子类可以拥有父类中的所有成员变量和方法 2、注意点
注: 基本上所有类的根类是 NSObject

  • 多态

多态就是用父类类型的指针创建子类的对象,比如 Dog 类继承了 Animal 类,下面都是多态: Animal *aa = [Dog new];

Dog *dd = (Dog *)aa;

1.没有继承就没有多态
2.代码的体现:父类类型的指针指向子类对象

3.好处:如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象
4.局限性: 父类类型的变量不能直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法

  • @property 的参数:

(1) set 方法内存管理相关的参数

(a) retain:release 旧值,retain 新值(适用于 OC 对象类型)
(b) assign:直接赋值(默认,适用于非 OC 对象类型),常用在 BOOL、int 等基本数据类型。

(c) copy:release 旧值,copy 新值,常用在 NSString 对象

(2) 是否要生成 set 方法

(a) readwriter:同时生成 set 和 get 方法的声明和实现

(b) readonly:只生成 get 的声明和实现

(3) 多线程管理

(a) nonatomic:性能高(一般都是使用这个)

(b) atomic:性能低(默认)

     (4)  set 和 get 方法的名称

(a) setter:决定了 set 方法的名称,一定要加个冒号“:“

(b) getter:决定了 get 方法的名称,不要加冒号

(5)  strong 和 weak

(a) strong:用于一般对象

(b) weak:用于 UI 控件

  • 内存管理

         在内存中,分为堆和栈,栈中主要存放变量,堆中主要存放对象。栈中的东西是系统自动回收的,当一个变 量使用完毕后,

        存放在栈中的东西会立刻被回收。但堆中存储的东西是不会随便回收的。

         每个 OC 对象里都有一个引用计数器,是一个整数,用来统计正在被引用多少次,每个引用计数器占用 4 个字 节,对象刚刚创建时引用计数器默认为 1。

        如果 OC 对象引用计数器为 0 时,系统就可以回收这个对象了。

      引用计数器的操作:

      (1) 给对象发送一条 retain 消息,可以使引用计数器值+1(retain 方法返回对象本身)

      (2) 给对象发送一条 release 消息,可以使引用计数器值-1
      (3) 给对象发送一条 retainCount 消息,可以获得当前的引用计数器值

     对象的销毁:

     (1) 当一个对象的引用计数器的值为 0 时,那么它将被销毁,其占用的内存会被系统回收。

     (2) 当一个对象被销毁时,系统会自动向对象发送一条 dealloc 消息

     (3) 一般会重写 dealloc 方法,在这里释放相关资源,dealloc 就像对象的遗言。
     (4) 一旦重写了 dealloc 方法,就必须调用[super dealloc],并且放在最后面调用。
     (5) 不要直接调用 dealloc 方法。

   概念:
       僵尸对象:所占用的内存已经被回收的对象,僵尸对象不能再使用

野指针:指向僵尸对象的指针,给野指针发送消息会报错

空指针:没有指向任何东西的指针(存储的东西是 nil、null、0),给空指针发送消息不会报错。

【备注】nil 与 null 不同,null 是一个宏定义,值为 0,nil 表示无值,任何变量在没有赋值之前都是 nil,对于 真假判断,只有 nil 和 false 表示假,其他均为真。
内存管理原则:
(1)谁创建,谁 release:
如果你通过 alloc、new 或[mutable]copy 来创建一个对象,那么必须调用 release 或 autorelease
(2)谁 retain,谁 release:
只要你调用了 retain,无论这个对象如何生成的,你都要调用 release。 综上:有始有终,有加就有减。曾经让对象计数器+1,就必须在最后让对象计数器-1

  1.  ARC

1、ARC 判断准则: 只要没有强指针指向对象,就会释放对象。就算此时仍有弱指针指向该对象或者该对象还指向其他对象,只 要没有强指针指向它就会释放对象。系统还会根据弱指针的情况及时释放弱指针对象,避免野指针的产生。 指针分两种:

(1)强指针:默认情况下,所有指针都是强指针 (_strong), 也可将 strong 作为参数传给@property

(2)弱指针:定义一个指针是弱指针,只需在定义时用_weak 声明即可,比如:_weak Person *p = [[Person alloc]

init];也可将 weak 作为参数传给@property

2、ARC 特点:

(1) 不允许调用 release、retain、retainCount
(2) 允许重写 dealloc,但是不允许调用[super dealloc]

(3) @property 的参数

* strong :成员变量是强指针(适用于 OC 对象类型)

* weak :成员变量是弱指针(适用于 OC 对象类型)

* assign : 适用于非 OC 对象类型

(4) 以前的 retain 改为用 strong

【备注】在实际项目中有这种需求,某些文件需要用到 release、retain 方法,比如下载的第三方框架中如果 有 release 等方法,放到支持 ARC 的编译环境中肯定会报错。这时我们可以设置这些文件不使用 ARC 而项目中 其他文件继续使用 ARC,方法很简单,选择项目的 Bulild phases,在 Compile Sources 中选择不需要 ARC 的文 件,双击或按回车,在弹出的窗口中输入-fno-objc-arc 即可。同样也可以在非 ARC 的环境中输入-f-objc-arc 使 相关文件支持 ARC。如下图:

  • Block

语法格式如下:

      

 返回值类型 (^Block 名称)()= ^{
          //代码块部分
        };

     比如定义一个无参数、无返回值、名称为 myblock 的 Block:

       

 void (^myblock)()=

            ^{ NSLog(@”-------------”);

        };

      等价于:

      

void (^myblock)(); myblock = ^{

        NSLog(@”-------------”);

      };

        调用代码: myblock();

  • Block 和方法很像,Block 特点:

(1)可以保存代码
(2)可以有返回值
(3)可以有形参
(4)调用方式和调用方法一样
(5)可以像方法一样调用外面的变量
(6)默认条件下,Block 不能修改外面的局部变量,但是在变量名前加上_block 就可以使 Block 可以修改这

个变量。比如:

_block int b = 20;

但是 Block 可以修改全局变量。
(7)实际开发中,常用 typedef 定义 Block 以减少代码量,比如:

typedef int (*MyBlock)(int, int); 以后再定义 Block 就可以:

MyBlock sumBlock = ^(int a,intb){ return a + b;

}

【备注】当 block 用到外面的东西时候,要把用的的外面的那个东西声明为弱指针,否则会发生循环引用的 问题。声明方法:
_weak ViewController *vc = self;//可以避免野指针,推荐使用
或者:

_unsafe_unretained ViewController *vc = self; 以后在代码块里调用的 vc 就以弱指针的方式调用。

 

  • protocol(协议)

    1、基本用途:
    (1) 可以用来声明一大堆方法(不能声明成员变量)

    (2) 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明

    (3) 只要父类遵守了某个协议,就相当于子类也遵守了
    (4) 和 java 中的接口很相似,但比接口功能更丰富
    2、格式

    (1)协议的编写

    @protocol 协议名称

    //方法声明列表

    #end

    (3) 某个类遵守协议
    @interface 类名:父类 <协议名称>
    @end

    3、遵守协议:
    首先要#import “协议文件名.h 或者@protocol 协议名称,但是使用@protocol 协议名称时只是告诉下面代码这 是一个协议,但不知道协议里面有什么东西,一般只在用到协议内容的时候在#import “协议文件名.h。在实际 开发中常用@protocol 协议名称。
    (1) 类遵守协议

    @interface 类名 : 父类名 <协议名称 1, 协议名称 2>

    @end

    (2) 协议遵守协议
    @protocol 协议名称 <其他协议名称 1, 其他协议名称 2>

    @end

    4、协议中方法声明的关键字

    (1) @required (默认)

    要求实现,如果没有实现,会发出警告,但不报错

    (2) @optional

     不要求实现,不实现也不会有警告
    例如:
    

    @require
    - (void)test;

    @optional
    - (void)test2;

9、基协议
(1)NSObject 是一个基类,是最根本最基本的类,任何其他类最终都要继承它 (2)其实还有一个协议,名字也叫 NSObject,它是一个基协议,最根本最基本的协议
(3)NSObject 中声明了很多最基本的方法,比如 description、retain、release 等 (4)建议每个新协议都要遵守 NSObject 协议

  • Category(分类)

    Category 又叫分类、类别、类目。
    分类的作用: 在不改变原来类内容的基础上,可以为类增加一些方法 使用方法:

    //声明
    @interface 类名(分类名称)

    @end
    //实现
    @implementation 类名(分类名称)

    @end

    使用注意:
    1.分类只能增加方法,不能增加成员变量
    2.分类方法实现中可以访问原来类中声明的成员变量

    3.分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法没法再使用

    4.当分类、原来类、原来类的父类中有相同方法时,方法调用的优先级:分类(最后参与编译的分类优先) --> 原

    来类 --> 父类,即先去调用分类中的方法,分类中没这个方法再去原来类中找,原来类中没有再去父类中找。

  • Foundation 之 NSRange

        

NSRange 原型:

typedef struct _NSRange{

unsigned int location;

unsigned int length;

}NSRange;

NSRange 含义:

(1)一个结构体,表示相关事物的范围

(2)location 字段为该范围的起始位置

(3)length 字段为该范围内所含元素的个数

创建方式:

1)直接给字段赋值
(2)应用 C 语言的聚合结构赋值机制

(3)使用 cocoa 提供的快捷函数 NSMakeRange()

比如,从一段字符串中截取 LFF 并输出:

NSString *test = @”My name is LFF”;
NSRange range = NSMakeRange(12,3);
NSLog(@”截取的字符为:%@”,
[test substringWithRange:range]);

上述代码 NSRange range = NSMakeRange(12,3)还有很多等价写法: 常用等价写法 1—直接给字段赋值:

NSRange range; range.location = 12;

range.length = 3;

(4)常用等价写法 2—C 语言的聚合结构赋值机制:

NSRange range = {12,3};

【备注】 NSStringFromRange 可以将上面的结构体转化成字符串,例如:

NSString *test2 = NSStringFromRange(range);

  • Foundation 之 NSPoint/NSRect/NSSize

NSPoint/NSRect/NSSize 的用法和 NSRange 都一样。

NSPoint 实际上就是 CGPoint

NSRect 实际上就是 CGRect

NSSize 实际上就是 CGSize

  • 程序启动的完整过程:
  • (1)main 函数

(2)UIApplicationMain
* 创建 UIApplication 对象
* 创建 UIApplication 的 delegate 对象
(3)delegate 对象开始处理(监听)系统事件(没有 storyboard)
* 程序启动完毕的时候, 就会调用代理的 application:didFinishLaunchingWithOptions:方法
* 在 application:didFinishLaunchingWithOptions:中创建 UIWindow
* 创建和设置 UIWindow 的 rootViewController
* 显示窗口

(3)根据 Info.plist 获得最主要 storyboard 的文件名,加载最主要的 storyboard(有 storyboard) * 创建 UIWindow
* 创建和设置 UIWindow 的 rootViewController
* 显示窗口
(4)UIApplicationMain
main 函数中执行了一个 UIApplicationMain 这个函数:
int UIApplicationMain(int argc, char *argv[], NSString

*principalClassName, NSString *delegateClassName);
各参数含义:
argc、argv:直接传递给 UIApplicationMain 进行相关处理即可。 principalClassName:指定应用程序类名(app 的象征),该类必须是 UIApplication(或子类)。如果为 nil,则用 UIApplication 类作为默认值。

delegateClassName:指定应用程序的代理类,该类必须遵守 UIApplicationDelegate 协议。

UIApplicationMain 函数会根据 principalClassName 创建 UIApplication 对象,根据 delegateClassName 创建一个 delegate 对象,并将该 delegate 对象赋值给 UIApplication 对象中的 delegate 属性。
接着会建立应用程序的 Main Runloop(事件循环),进行事件的处理(首先会在程序完毕后调用 delegate 对象的 application:didFinishLaunchingWithOptions:方法)。

程序正常退出时 UIApplicationMain 函数才返回。

 

猜你喜欢

转载自www.cnblogs.com/cindyli/p/9078616.html