由于比较空闲,近期打算把之前看过的书一本本重读一下。这一小节主要说的是《精通Objective-C》的前六章。
1.为什么选择objective-c
面向对象的编程语言,对象消息传递,动态的运行时环境,内存管理,内部检查和获取消息,对C语言的支持,苹果公司的技术。
2.OOP:面向对象设计
面向对象编程是一种计算机程序设计方式,其重点是创建和使用软件对象编写程序。软件对象提供了被建模事物/概念的特点或属性的一种表现形式,以及他们可以做的事情。
3.设置访问实例变量的方式
@private:只能在声明他的类以及该类型相同的其他实例中访问
@protexted:只能在声明他的类及其子类的实例方法中访问
@public:可被任意代码访问
@package:可被其他类实例和函数访问,但在其所属的程序包外部被视为私有变量
4.属性和实例变量(不太清楚,具体在查一查)
属性可在累的外部调用,可以看做是在.h文件中声明的
实例变量一般是在.m中声明的,外部不可以调用访问
5.属性的特性
nonatomic 非原子性 可以在多线程并发的情况下,将访问器设置为非原子性的,因而可以提供不同的结果
atomic 原子性
assign 可以在不使用copy和retain的情况下,使属性的设置器方法执行简单的赋值操作 默认设置
retain 在赋值时,输入值会发送一条保留消息,而上一个值会被发送一条释放消息
copy 在赋值时,输入值会发送一条新消息的副本,而上一个值会被发送一条释放消息
strong ARC内存管理下相当于retain
weak ARC内存管理下与assign类似,但如果引用对象被释放了,属性的值为nil
readwrite 可读可写 必须实现getter和setter方法 默认
readonly 只读 必需实现getter
getter==getterName getter方法重命名
setter== setterName setter方法重命名
6.nonatomic和atomic两者区别:
Atomic 是默认的 会保证CPU能在背的线程访问这个属性之前 先执行当前流程 速度不快
nonatomic 非默认 更快 线程不安全 如果有两个线程访问同一个属性,会出现无法预料的结果
参考链接:https://www.jianshu.com/p/7288eacbb1a2
设有一个 atomic 的属性 "name",如果线程 A 调[self setName:@"A"],线程 B 调[self setName:@"B"],线程 C 调[self name],那么所有这些不同线程上的操作都将依次顺序执行——也就是说,如果一个线程正在执行 getter/setter,其他线程就得等待。因此,属性 name 是读/写安全的。
但是,如果有另一个线程 D 同时在调[name release],那可能就会crash,因为 release 不受 getter/setter 操作的限制。也就是说,这个属性只能说是读/写安全的,但并不是线程安全的,因为别的线程还能进行读写之外的其他操作。线程安全需要开发者自己来保证。
如果 name 属性是 nonatomic 的,那么上面例子里的所有线程 A、B、C、D 都可以同时执行,可能导致无法预料的结果。如果是 atomic 的,那么 A、B、C 会串行,而 D 还是并行的。
7.assign、copy、retain三者区别
Assign: 简单赋值,不改变索引计数
Copy:建立一个索引计数为1的对象,然后释放旧对象
Retain:释放旧的对象,将对象的值赋予输入对象,在提高输入对象的索引计数
参考链接:https://www.jianshu.com/p/158c979f9b30
8.协议
协议的声明以@protocol开头,后跟协议的名称,以@end结束。协议有必选方法和可选方法(以@required和@optional区分,不写默认必选方法)
9.objective-c提供了两类消息转发选项
快速转发:NSObject的子类可以通过重写NSObject类的forwardingTargetForSelector:方法,将该方法转发给其他对象,从而实现快速转发。
标准转发:NSObject的子类可以通过重写NSObject类的forwardingInvocation:方法,实现标准转发。
10.内存泄露——程序没有释放不再使用的对象
悬挂指针——程序释放了仍在使用的对象
11.ARC的生命周期限定符
__strong:表明任何使用alloc/init消息创建的对象都会在其作用范围内保留
__weak:表明对象随时可以被释放。只有当对象拥有其他强引用是该标记才有用。释放后,带__weak限定符的变量会被设置为nil
__unsafe_unretained:与__weak类似,但在对象释放后不会设置为nil,处于悬挂状态
__autoreleasing:用于通过引用传递对象
12.避免循环引用
Objective-C的引用计数模型是通过获取对象的所有权(retain消息),以及在不在使用对象后释放对象的所有权(release消息)实现的。ARC自动化了该过程。但是如果两个对象直接或间接相互引用,就会导致循环引用问题。
13.预处理器
Objective-C编译器编译源代码的一般流程是:接受源文件,然后把它们转换为能够在目标平台上执行的文件。
预处理器是在语法分析阶段前的语法分析阶段发挥作用的。
预处理语言
预处理语言是一门不同于Objective-C的独立编程语言。预处理语言对原文件进行的转换主要包括源文件的内容、条件编译和宏展开。预处理器语言元素会在程序边以前处理源文件,但预处理器不能识别Objective-C代码。
预处理器指令是指由预处理器执行的命令
宏指令是指具有名称的一段代码。当该名称在源代码中使用,就会被替换为它代表的那段代码。
指令
Objective-C源文件中的预处理器指令会使用独特的语法,是他们由预处理器(而不是编译器)处理。
预处理器指令形式: #指令名 指令参数
预处理器指令会将换行符号用作结束符号。要使预处理器扩展为多行,可使用反斜杠(\)连接多行代码
成套的预处理器指令及其作用
头文件包含(#include、#import)
作用是是预处理器获得被包含文件的文本,并将其插入到当前文件中。
#import和#Include的区别
#import指令可以确保头文件仅在源文件中被包含一次,防止递归包含。
条件编译(#if、#elif、#else、#endif、#ifdef和#ifndef)
#if指令可以测试表达式的值,并根据结果确定是否包含部分源文件 与#endif指令配对使用
诊断(#error、#warning和#line)
#pragma指令
宏是指有名称的代码段。使用#define 定义宏使用#undef移除宏
关于预处理器的部分还可以看我的上一篇博客。