简略记录部分概念,后期有时间会针对性的另开新篇。
.m扩展名?
Xcode通过.m扩展名来表示文件使用的是Objective-C代码,应该由Objective-C编译器处理。例如C编译器处理.c文件,C++编译器处理.cpp文件。
#import语句?
Objective-C使用头文件来包含结构体、符号常量和函数原型等元素的申明,#import可保证头文件只被包含一次,无论该命令在该文件中出现多少次。例如#import<Foundation/Foundation.h>语句告诉编译器查找Foundation框架中的Foundation.h头文件。Xcode使用预编译头文件来加快读取速度,通过#import导入文件时加载速度很快,同时在编译时会将该类的头文件中的所有信息都引入。
@class?
@class创建了一个向前引用,告诉编译器有这样一个类,并不会引入该类的其他信息。
框架?
框架是一种把头文件、库、图片、声音等内容聚集在一个独立单元中的集合体。每一个框架都有一个主头文件,它包含了框架中所有的头文件。通过在头文件中使用#import,就可以访问框架内的所有功能。
NSLog()?
NSLog()接受一个字符串作为其第一个参数,该字符串可以包含格式说明符(eg:d%),接受与格式说明符相匹配的参数,NSLog本质上就是具有Cocoa特色的printf()函数。
@%?
NSLog()可以使用@%格式说明符来输出对象,NSLog()处理@%说明符时,会询问参数列表中相应的对象以得到这个对象的描述。从技术上讲,也就是NSLog()给这个对象发送了description消息,然后对象的description方法生成一个NSString并将其返回,NSLog()就会在输出结果中包含这个字符串。@%只是调用每个对象的description方法并显示结果,在类中提供description方法就可以自定义NSLog()会如何输出对象
NS前缀?
Cocoa下的所有函数、常量和类型名称都添加了NS前缀,这个前缀代表创建的内容属于Cocoa。1985年乔布斯创立了Next公司,Next公司以Unix作为操作系统并创建了NextSTEP(使用Objective-C语言开发的一款功能强大的用户界面工具包),苹果公司在1996年收购Next公司之后NextSTEP更名为Cocoa,Cocoa下NS的前缀实际来源于NextSTEP。
字符串用@?
NSLog(@"Hello,Objective-C");
@符号是Objective-C在标准C语言基础上添加的特性之一,@符号表明引号内的字符串内容应作为Cocoa下的NSString元素来处理。
return 0?
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
}
return 0;
}
程序中最后一行是返回语句,它可以终止main()函数的执行并结束程序,return 0;
意味着这个程序成功的执行完了。
bool,BOOL?
bool是C语言的布尔数据类型具有true与false两个值,BOOL是Objective-C的布尔数据类型具有YES与NO两个值。BOOL实际上是一种对带符号的字符类型(signed char)的类型定义,使用8位的存储空间,通过#define指令把YES定义为1,NO定义为0。Objective-C不会将BOOL作为只能保存YES和NO值的真正布尔类型来处理,编译器将BOOL认作8位的二进制数,当将一个非0非1的数赋给BOOL变量时,只有低位字节会作用BOOL值。即在signed char的范围内-128到+127之间只有0是NO,非0是YES;(切记,不要将BOOL值和YES直接进行比较,直接与NO值比较一定是安全的,因为C语言中的假值只有一个0)
面向对象?
面向对象编程(Object-Oriented Programming)的首字母缩写为OOP,是一种编程架构,可构建由多个对象组成的软件。
变量与间接?
变量就是指通过变量名访问,它的值是可变的;
间接就是指在代码中通过指针间接获取某个值,而不是直接获取,间接是OOP的核心,OOP使用间接来调用代码,而不是直接调用函数。
过程式编程?
过程式编程建立在函数之上,数据为函数服务,就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用。
面向对象编程?
面向对象编程以程序的数据为中心,函数为数据服务,数据通过间接方式引用代码,代码可以对数据进行操作。
id?
id是一种泛型,可以用来引用任何类型的对象。
[class new]; 方括号?
在Objective-C中方括号还表示:用于通知某个对象该去做什么,方括号里第一项是对象,其余部分是需要对象执行的操作。通知对象执行某种操作称为发送消息,也叫调用方法。
类?
类是一种能够实例化成对象的结构体。对象通过它的类来获取自身的各种信息。在Objective-C编程时采用首字母大写的类名。
对象?
对象是一种包含值和指向其类的隐藏指针的结构体,指向对象的变量通常不需要首字母大写。在Objective-C中所有对象的交互都是通过指针来实现的。
实例?
实例是“对象”的另一种称呼。
消息?
消息是对象可以执行的操作,用于通知对象去做什么,对象接收到消息后,将查询相应的类,找到正确的代码来运行。
方法?
方法是为响应消息而运行的代码。根据对象的类,消息可以调用不同的方法。
接口?
接口是类为对象提供的特性描述。
实现?
实现是使接口可以正常工作的代码。
UML?
UML是一种用图表表示类、类的内容以及它们之间关系的常见方式。
实例化对象?
用类创建对象的过程称为实例化,实例化对象时需要分配内存,然后将这些内存初始化并保存为有用的默认值,内存分配和初始化工作完成之后,就意味着新的对象实例已经创建好了,创建一个新的对象,需要向相应的类发送new消息,该类接收并处理完new消息后就可以得到一个可以使用的新对象实例。
开放/关闭原则?
软件实体应该对扩展开放,而对修改关闭。(面向对象编程大师Bertrand Meyer)
self?
每个方法调用都包括一个名为self的隐藏参数,它是一个指向接收消息的对象的指针,是对象自身。使用self参数后,方法可以查找并操作对象的数据。
继承?
表示一个类从另一个类(它的父类或超类)中获取了某些特性。
方法调度?
方法调度是Objective-C使用的一种机制,用于推测执行什么方法以响应某个特定的消息。当代码发送消息时,Objective-C的方法调度机制将在当前的类中搜索相应的方法,如果无法在接收消息的对象的类中找到相应的方法,就会在该对象的超类中进行查找,逐步在继承链中的每一个类中重复的查找,如果在最顶层的NSObject类中也没有找到相应的方法,则会出现一个运行时的报错。
实例变量?
在创建一个新类时,其对象首先会从它的超类中继承实例变量,然后根据自身情况添加自己的实例变量。
基地址加偏移?
编译器使用“基地址加偏移”的机制查找存储变量的位置。对象基地址即第一个实例变量的首个字节在内存中的位置,再在该地址上加上偏移地址,编译器就可以查找其他实例变量的位置。
方法重写?
子类实现父类的某一个方法,即重写父类的方法,方法调度机制将运行重写后的方法,父类中定义的方法实现将被忽略。
super?
为了调用继承的方法在父类中的实现,需要使用super作为方法调用的目标。super既不是参数也不是实例变量,是由Objective-C编译器提供的一种功能,当你向super发送消息时,实际上是在向该类的超类发送消息,如果超类中没有定义该消息,会继续在继承链上一级中查找。调用继承的方法可以确保获得方法实现的所有特性
复合?
对象引用其他对象时,可以利用其他对象提供的特性,这就是复合。在Objective-C中,复合是通过包含作为实例变量的对象指针实现的。
if (self = [super init]) ?
if (self = [super init]) {
为了让超类将所有需要的初始化工作一次性完成,需要调用[super init],init返回的值就是被初始化的对象,将[super init]返回的结果赋给self是Objective-C的惯例,这么做是为了防止超类在初始化过程中返回的对象与一开始创建的不一致。self参数是通过固定的距离寻找实例变量所在的内存位置的,如果init方法返回一个新对象则需要更新self,以便其后的实例变量的引用可以被映射到正确的内存位置,这也是需要使用self = [super init]这种形式赋值的原因,这个赋值操作只影响该init方法中self的值,而不影响该方法范围以外的任何内容。如果从[super init]返回的值是nil,则 if (self = [super init]) 的判断不会让主体代码执行。
存取方法?
存取方法是用来读取或改变某个对象属性的方法,分为setter方法和getter方法。setter方法通过给对象指针发送该消息(调用setter方法)修改内部属性值。getter方法用代码通过对象自身访问对象属性。存取方法一般是成对出现的,一个用来设置属性的值,另一个用来读取属性的值。有时只有一个getter方法用于只读属性,或者只有一个setter方法(如修改密码)也是合理的。setter方法根据它所更改的属性的名称来命名并加上前缀set,getter方法则是以其返回的属性名称来命名。不要将get用作getter方法的前缀
Foundation?
Foundation是两类UI框架的基础,它不包含UI对象。Foundation框架中有很多有用的、面向数据的简单类和数据类型,Foundation框架是以另一个框架CoreFoundation为基础创建的,CoreFoundation框架是用纯C语言写的。
类方法?
Objective-C运行时生成一个类时,会创建一个代表该类的类对象,在声明方法时使用“+”,就是把这个方法定义为类方法,这个方法属于类对象(而不是类的实例对象)。
内存泄漏?
必须确保在需要的时候分配内存,在程序结束运行的时候释放占用的内存,如果只分配而不释放内存,则会发生内存泄漏,程序的内存占用量不断增加,最终会被耗尽并导致程序崩溃。(不要使用任何刚释放的内存,可能误用陈旧数据,引发错误
)
对象所有权?
如果一个对象内有指向其他对象的实例变量,则称该对象拥有这些对象,如果一个函数创建了一个对象,则称该函数拥有这个对象。
垃圾回收?
Objective-C2.0引入了自动内存管理机制,也称垃圾回收。(只支持OS X应用开发,无法用在iOS应用程序上)
自动引用计数?
自动引用计数(automatic reference counting,ARC),ARC不是垃圾回收器,在编译时进行工作,适时插入retain和release语句,完成内存管理的工作,ARC是一个可选的功能,必须明确的启用或禁用它;ARC只对可保留的对象指针有效,主要包括:1.代码块指针 2.Objective-C对象指针 3.通过 _attribute____((NSObject))类型定义的指针。(所有其他的指针类型如char* 和 CFStringReg不支持ARC特性,必须手动管理)
弱引用?
属性使用了assign特性便是创建了一个弱引用,弱引用有助于处理保留循环,使用弱引用计数器的值不会增加。
归零弱引用?
让对象自己去清空弱引用的对象,在指向的对象释放后,弱引用就会被设置为nil,这种特殊的弱引用称为归零弱引用。有两种方式申明归零弱引用:使用__weak关键字或对属性使用weak属性。,__unsafe_unretained关键字和unsafe_unretained特性也可以指定引用是弱引用。
使用ARC时,属性名称不能以new开头,属性不能只有一个read-only而没有内容管理特性,内存管理的关键字和特性是不能一起使用的,两者互相排斥。
异常?
异常就是意外事件,如数组溢出,当发生异常时,程序会创建一个异常对象,Cocoa中使用NSException类来表示异常,Cocoa要求所有的异常必须是NSexception类型的异常,其他对象抛出异常Cocoa不会处理。异常处理的目的是处理程序中的错误,Cocoa框架的处理方式是程序退出。
异常的所有关键字都是以@开头:
@try:代码块是否抛出异常;
@catch:处理已抛出异常的代码块,接收一个参数,通常是NSException类型;
@finally:无论是否抛出异常,最终会执行的地方;
@throw:抛出异常;
异常会对程序资源有影响,对一般的流程不能使用异常简单地标记错误,虽然使用@try建立异常不会产生消耗,但是捕捉异常会消耗大量资源并影响程序运行的速度。
抛出异常?
程序会创建一个NSException实例使用两种方式来抛出异常,
使用“@throw异常名”语句来抛出异常,向某个NSException对象发送raise消息;
raise只对NSException对象有效,而@throw可以用在其他对象上。
对象初始化?
通常有两种方式创建对象,第一种[类名 new],第二种[[类名 alloc] init],这两种方法是等价的,但是Cocoa惯例是使用alloc和init而不使用new。对象初始化分为两个步骤,第一步分配对象,第二步初始化对象。
分配就是从操作系统中获得一块内存,并将其指定为存放对象的实例变量的位置。向类发送alloc消息就能为类分配一块足够大的内存,以存放该类的全部实例变量,同时alloc方法还会将这块内存区域全部初始化为0。
初始化是从操作系统取得一块内存用于存储对象,init方法一般返回其正在初始化的对象。
在执行初始化工作时包括给实例变量赋值并创建对象进行工作时所需的其他对象。
初始化函数的一般规则是,假如你对象必须要用某些信息进行初始化,那么你应该讲这些信息作为init方法的一部分添加进来,这些事典型的不可变对象。
@property?
@property预编译指令的作用是自动声明属性的setter和getter方法,事实上属性的名称不必与实例变量的名称相同,但大多数情况下是一样的。
@synthesize ?
一种新的编译器功能,表示创建了该属性的访问代码。不同于代码生成,看不到实现的setter和getter方法,但是这些方法是存在的并且可以调用。
@dynamic?
不生成任何代码或创建相应的实例变量。
点表达式?
点表达式只是调用访问方法的一种便捷方式,无特殊之处。如果点表达式出现在等号的左边表示该变量名称的setter方法将被调用,如果如果点表达式出现在等号的右边表示该变量名称的getter方法将被调用。
类别?
类别是一种为现有的类添加新方法的方式。可以在类别中添加属性,但是不能添加实例变量,而且属性必须是@dynamic类型的,添加属性的好处在于你可以通过点表达式来访问setter和getter方法。类别可以访问其继承的类的实例变量;类别有两个局限性,
- 第一个是无法向类别添加新的实例变量,类别没有空间容纳实例变量;
- 第二个就是名称冲突,就是类别中的方法与初始类的方法重名时,类别的方法具有更高的优先级,会完全取代初始类方法,导致初始类方法不可用。
类别主要有三个用处,
- 将类的实现分散到多个不同的文件或框架中;
- 创建对私有方法的向前引用;
- 向对象添加非正式协议。
类扩展?
类扩展,一种特殊的类别。具有以下特点:
- @interface部分不需要名字;
- 可以在包含的初始类中使用;
- 可以添加实例变量;
- 没有有独立的实现部分(@implementation部分),所声明的方法必须依托对应初始类来实现;
- 可以将只读权限改为可读写的权限;
- 创建数量不限;
选择器?
选择器只是一个方法名称,以Objective-C运行时使用的特殊方式编码,以快速执行查询。可以使用@selector()编译指令括号中的方法名称来指定选择器。选择器可以被传递,可以作为方法的参数使用,甚至可以作为实例变量被存储。
非正式协议?
非正式协议是NSObject的一个类别,它列出了对象可以响应的方法,可用于实现委托。
协议?
协议是包含了方法和属性的有名称列表,采用协议的方法是在类的@interface声明中列出的协议的名称,采用协议后,就要遵守协议,实现协议下的方法。@protocol后面是协议名称,协议名称必须唯一,可以继承父协议(与继承父类相似),在声明语句协议名称后面的尖括号内可以指定父协议的名称。
委托方法?
委托就是某个对象指定另一个对象处理某些特定任务的设计模式,经常与协议共用。
复制?
复制分为两类:
- 浅层复制
不会复制所引用的对象,新复制的对象只会指向现有的引用对象,复制的对象只会复制指向引用对象的指针,而不会复制引用对象本身。 - 深层复制
复制所有的引用对象。
代码块?
代码块对象是对C语言中函数的扩展,除了函数中的代码,还包含变量绑定,代码块也称为闭包。代码块包含两种类型的绑定:自动型与托管型,自动型使用的是栈中的内存,而托管绑定是通过堆创建的。代码块可以访问与它同时创建的有效变量。代码块借鉴了函数指针的语法,具有以下特征:
- 返回类型可以手动声明也可以编译器推导
- 具有指定类型的参数列表
- 拥有名称
__block变量?
本地变量会被代码块作为常量获取到,如果要修改它们的值必须将它们声明为可修改的,将变量标记为__block,有些变量无法声明为__block类型:
- 没有长度可变的数组
- 没有包含可变长度数组的结构体
GCD?
GCD是一个系统级别的技术,可以在任意级别的代码中使用,GCD决定需要多少线程并安排它们运行的进度,平衡应用程序所有内容的加载。
调度队列?
GCD可以使用调度队列同步或异步的执行任意代码,分为三种类型:
连续队列
连续队列会根据指派的顺序执行任务,遵循先入先出(FIFO)的原则。并发队列
并发队列能并发执行一个或多个任务,适用于并行运行的任务,任务会根据指派到队列的顺序开始执行,任务可以在前一个任务结束前就开始执行,遵循先入先出(FIFO)的原则。主队列
它是应用程序中有效的主队列,执行的是应用程序的主线程任务。使用dispatch_get_main_queue()
可以访问与应用程序主线程相关的连续队列。
队列添加任务?
有两种方式可以向队列中添加任务:
同步
队列会一直等待前面任务结束异步
添加任务后不必等待任务结束,函数会立刻返回。推荐使用这种方式,避免阻塞其他代码的运行。
死锁?
指的是两个或多个任务在等待对方运行结束,想要避免死锁就绝对不要给运行在同一队列中的任务调用dispatch_sync
函数。
UIKit?
iOS应用程序使用UIKit框架,它包含了所有的UI组件和构成iOS应用程序的资源。
属性列表?
属性列表一般简写为plist,用来放置一些Cocoa能够处理(主要是存储到文件和从文件加载)的对象。
编码?
Cocoa具备一种将对象转换成某种格式并保存到磁盘的机制。对象可以将它们的实例变量和其它数据编码为数据块,然后保存到磁盘中,这个过程称为编码也叫做序列化。
解码?
编码后,数据块以后还可以读回内存中,并且还能基于保存的数据创建新对象,这个过程叫做解码也叫反序列化。
可以采用NSCoding协议和实现方法来编码和解码对象
KVC?
键/值编码(key-value-coding)是一种间接更改对象状态的方式,也称为KVC。其实现方法是使用字符串表示要更改的对象状态,键/值编码中的基本调用时-valueForKey:
和-setValue: forkey:
。你可以向对象发送消息,并传递你想要访问的属性名称的键作为参数。
-valueForKey:
:的功能非常强大,会首先查找以参数名命名(格式为-key或-isKey)的getter方法,如果没有getter方法,它会在对象内寻找名称格式为_key和key的实例变量。-valueForKey:
在Objective-C运行时中使用元数据打开对象并进入其中查找需要的信息,通过KVC,没有相关getter方法也能获取对象值,不需要通过对象指针来直接访问实例变量。键路径不仅能引用对象值,还可以引用一些运算符来进行一些运算。KVC也可以为对象进行批量处理。
如果使用KVC访问一个NSArray数组,它实际上会查询相应数组中的每个对象,然后将查询结果打包到另一个数组中并返回给你,这种方法也同样适用于通过键路径访问的位于对象中的数组。
KVC需要解析字符串类计算需要的答案,速度比较慢,此外编译器无法对他进行错误检查,不能判断键路径是否正确。
null?
NSNull用于表示不允许空值的集合对象中的空值,可以用[NSNull null]
表示nil值。
<null>:是一种[NSNull null]对象。
(null):是一个真正的nil值。
静态分析器?
静态分析器(static analyzer),是一个不需要运行程序就可以从逻辑上检测代码的工具,它可以寻找会演变成bug的错误,它不是简单的浏览源代码,而是在应用程序的代码通道中查找逻辑错误并反馈给你,可以检测的错误包括:
- 安全问题,如内存泄漏和缓冲区溢出;
- 并发性问题,如静态条件(依赖时间的两个或多个任务失效);
- 逻辑问题,包括废代码和不好的编码习惯;
有时会误报错误,需要消耗时间来分析,拖慢构建程序的过程
Clang?
Clang是一个加强了C编译器并在Xcode中为静态分析器提供基础的开源项目。
谓词?
Cocoa中提供了一个名为NSPredicate的类,用于指定过滤器的条件。可以创建NSPredicate对象,通过它准确地描述所需的条件,通过谓词筛选每个对象,判断它们是否与条件相匹配。predicate是一个普通的Objective-C对象指针,它将指向NSPredicate对象。
正则表达式?
它是一种指定字符串匹配逻辑的非常紧凑的方式,正则表达式功能非常强大,但是计算开销非常大。