Objective-C 语法

来源:互联网 发布:外汇汇率查询软件 编辑:程序博客网 时间:2024/06/05 22:57

每周坚持还真是好像没那么简单啊,比如这周,到了总结这一刻与非发现自己这星期似乎什么都没做没有可以写的,一份 Objective-C 语法整理好了,暂且当做这周的总结,下周要努力了。

Objective-C 语法手册

这些能够保存数据的空间称为变量(名称+类型)
有了变量的类型信息,编译器才知道要为相应的变量保留多少存储的空间
指针变量可以保存内存地址,它必须用星号来声明。例如 int 这里的指针变量并不直接保存 int 整型变量的数值,但是知道 int 变量的地址就可以得到其数值
== 运算符的作用是判断数字是否相等,= 的作用则是执行赋值操作
表达式有时很长、很复杂。为方便起见,可以将表达式的计算结果赋给变量,并为该变量起一个好记的变量名
某些变量的值只能为真或假,这类变量称为布尔 boolean 变量
处理三条以上的分支,用 else if 逐条进行测试,这些子句会按照编写的顺序逐条进行测试,直到某条子句的求值结果为真
条件运算符/三元运算符,关键字 ?
——位于 ? 之前的部分是条件表达式,位于 ? 之后的两个值分别对应表达式计算结果为真或假的情况
Char 8 位/ short 16 位/ int 32 位/ long 32 或 64 / long long 64 位,它们默认是有符号的,以上整数类型所占的位数是平台相关的 差别在于内存地址的大小
任何字符都可以用一个 8 位的数字来描述,ASCII 码表使用数字来代替所有常用的字符。处理其他文字系统(西里尔字母/日文字母等)用其他的编码(Unicode)
若分子和分母都是整数类型,那么执行的整数除法,若分子和分母有任何一个是浮点数,就会执行浮点数除法
NSInteger 有符号/NSUInteger 无符号
浮点数都是有符号的,float 32 位/ double 64 位/ long double 128 位
Mac-terminal-man math 回车->数学代码库,要包含头文件 #include

循环与指针

与三角函数有关的使用的都是弧度而不是角度
可以写一个注释什么难倒了你
While 的代码段会被反复地执行,直到表达式的计算结果为假
for 循环 程序使用循环来控制某段代码的执行次数,更常见的是使用循环来迭代一组保存在 collection 中的对象。
Break 当程序正在执行循环时,在内部将其终止,跳出循环
continue 当程序正在执行循环时,需要跳过余下的代码段,开始执行下一个循环
Do while 循环会先执行代码段,然后检查表达式,保证至少执行一次代码段,while 那行代码以分号结尾

中央处理器CPU/随机存取存储器RAM

内存有数字编号,用地址(adress)来指代某个特定字节的数据

变量的地址 是指内存中的某个位置

用变量保存地址,为变量声明特定的类型(例 float *ptr这里的ptr是变量/指向某个浮点数变量的指针(pointer),ptr本身不保存浮点数变量的值,而是指向某个地址,该地址对应的是保存浮点数的内存
程序不一定能通过拷贝来传递数据,但是一定能够直接传递或拷贝来传递数据的起始地址,容易存取相应数据

使用运算符,可访问保存在某个地址中的数据(号的两种用法)
1/声明指针:将变量adressOfI声明位int*,即指向保存int值的内存地址
2/访问保存在adressOfI地址中的int值,通过指针访问某个地址中的数据这一过程也称为引用
Null/nil:“空指针”不指向任何地址
写在变量名这边,在每个要声明为指针的变量前加上

通过引用传递参数的函数:调用函数时传入某个地址,然后由函数将数据存入该地址指向的内存(可以返回不止一个值的方法)
用不到返回数据时,将NULL作为地址传入函数,表示“无须传回相应的值”,在对地址取值时,应先检查指针是否为NULL: if(ftPtr){//ftPtr变量名
代码段
}

结构:使用一个变量保存多个相关的数据

栈中的内存:在调用函数时由系统自动分配,并在函数结束后自动释放,因此局部变量常被称为自动变量

缓冲区:一块连续的内存,缓冲区来自特定的内存区域——堆(heap)
在堆上,缓冲区独立于任何函数的栈,它可以在多个函数中使用

使用 malloc() 函数可以得到一块内存缓冲区,当程序不再使用这块缓冲区时,可以调用 free() 函数,释放相应的内存,将其返回给堆。

用 sizeof() 来获得缓冲区的准确大小,例:malloc(1000 * sizeof(float))

框架与对象

Foundation 框架
框架(framework)是由很多相关的 类(class)/函数/常量/数据类型 组成的库。
对象和结构类似,一个对象可以保存多个相关数据,称这些数据为实例变量(instance variables)(结构中的成员)
对象还可包含一组函数,并且这些函数可以使用对象所保存的数据,这类函数称为方法。

类(class)负责描述某个特定类型的对象,其中包括方法和实例变量。

一个类定义了一种对象,同时它也可以用来创建这种对象。类既是对象的原型,又是生产对象的工厂——例:创建一个 类,命名为 Person,由 Person 类创建的 对象,称为它的 实例,Person 实例将使用 实例变量 来保存身高和体重,Person 实例还将包含一个方法

“#import” 指令会让编辑器先检查之前是否已经导入过这个文件 或是已经被包含到目标文件中了

NSLog( ) 是一个 Objective-C 函数,会根据传入的格式化字符串将格式说明符替换为实际的值,然后输出结果。先输出日期 时间 程序名称 进程ID,然后输出实际内容

方法和函数类似,根据指令执行相应功能。
Objective-C语言中,执行方法里的代码,首先需要发送一条消息给你包含这个方法的对象或类

NSDate类,它的实例代表某个时间点

NSDate *now = [NSDate date];
——变量now前面的 *说明它是一个指针,这个指针保存了NSDate实例在内存中的地址
——我们创建了一个NSDate的实例,它的地址保存在now变量中
——NSDate类中有一个date方法,你向NSDate类发送了date消息,让它执行date方法

消息发送(指令)写在[ ]中,必须包含接收方(receiver)和选择器(selector)
——NSDate 接收方:指针,指向接受消息的对象的地址
——date 选择器:方法名,要触发的方法的方法名
——给 NSDate类 发送了date消息,date是一个 类方法,类方法会创建类的实例 并初始化实例变量
Double seconds = [now timeIntervalSince1970](缺点:发送一条消息给类会创建一个实例 这条消息只会执行一个类方法,但这个实例被创建后 在程序运行期间 它可能会接受更多消息 而这些消息又会执行其它的实例方法)
——给now变量指向的 NSDate实例 发送了timeIntervalSince1970这个 实例方法,实例方法会提供实例中实例变量的信息 或对实例等实例变量进行操作(实例方法用的更多)
——使用date方法可以用最少的代码获取一个NSDate实例,称这种方法为便利方法

格式说明符:%@ 输出相应对象的描述信息

OS X 和 iOS 系统都是基于 Unix 开发的。

Objective-C 区分大小写。
——指向实例的变量/方法 使用“骆驼拼写法(camel case)”来命名,以小写字母开头,接下每个单词的第一个字母使用大写
——类 的名称以大写字母开头,接下来的单词继续使用骆驼拼写法。一般来说,类的名称要加前缀,避免相似的类名造成混乱,通过前缀还可以知道它属于哪个框架。Foundation框架的类使用NS(NEXTSTEP简写)前缀
——很多苹果创建的类型和常量的命名 前缀大写的骆驼拼写法

[now dateByAddingTimeInterval : 100000]
——传递实参的消息
——接收方 now
——选择器 dateByAddingTimeInterval :
——实参 100000
——“:” 方法名后的冒号,向 dateByAddingTimeInterval :方法传入一个实参。方法带实参的时候,冒号是构成方法名的一个重要部分,所以不存在dateByAddingTimeInterval方法,只有dateByAddingTimeInterval : 方法

多个实参,编写消息发送代码时,通常会对齐冒号,能方便地通过实参分辨方法名中的各个部分,(Xcode的缩进设置)

NSDate *now = [NSDate date];
double seconds = [now timeIntervalSince1970];
写在一行代码:
double seconds = [[NSDate date] timeIntervalSince1970];
——嵌套发送的消息,系统会先执行最里面的消息,然后按由内至外的顺序依次执行外层的消息
——系统先向NSDate类发送date消息,然后向得到的返回值(即指向新创建的NSDate实例的指针)发送 timeIntervalSince1970 消息

每个类都有一个 alloc 类方法,它能够创建一个新的对象,并返回指向该对象的指针。通过alloc创建出来的对象,必须经过初始化才能使用。
若创建出来的新对象没有经过初始化,它会存在于内存里,但是无法接受消息。
每个类都有一个init实例方法,它用来初始化实例。

在Objective-C中,可以向 nil 发送消息,什么事情也不会发生。
——如果程序向某个对象发送了消息,但却没有得到预期的结果,请检查消息接收方是否为 nil。
——向 nil 发送消息,得到的返回值没有意义。

id delegate;
——当声明指向对象的指针时 通常都会明确写出相应对象的类。
——声明指针时 不知道所指对象的准确类型,这时使用 id 类型 它的含义是:可以指向任意类型Objective-C对象的指针。
——这则变量声明没有使用星号,id 已经隐含了星号的作用。

NSString:NSString 实例可以保存字符串
NSString 方法:
——获取字符串中字符的数量 length
——查看一个字符串是否和另一个字符串相等 isEqualToString: 方法
——把一个字符串变成大写形式 uppercaseString 方法

类参考 (class reference) :苹果公司在它的API里提供了每个类的类参考,列出了一个类的所有方法 以及它们的基本用法。Xcode_Help_Documentation and API Reference

NSArray:NSArray 实例可以保存一组指向其他的对象的指针
——NSArray 实例是无法改变的,一旦 NSArray 实例被创建后,就无法添加或删除数组里的指针,也无法改变数组的指针顺序。

实例变量的名字以下划线“_” 开始,使用下划线的前缀可以容易分辨实例变量和局部变量,没有特别的语法意义

self
——Objective-C的方法都包含一个隐含的局部变量 self
——self 是指针,指向运行当前方法的对象
——当某个对象要向自己发送消息时,就需要使用 self
——还可以将 self 作为实参传给其他方法,以便其访问“当前的”对象

类前缀

属性(properties):用来简化存取方法的过程
——声明属性的时候,编译器声明并实现存取方法
——属性的声明可以有一个或多个属性特性,在@property接口后的括号中

用点号调取存取方法 dot notation
float w = mikey.weightInkilos;
两行代码作用完全相同
float w = [mikey weightInKilos];
——使用 dot notation 的时候是在发送消息。mikey.weightInkilos 会根据使用的情况发送一至两条消息
——根据是否读取 mikey 的 _weightInKilos 会调用 取方法(weightInKilos)或 存方法(setWeightInKilos: )

覆盖一个方法的时候,子类可以利用父类的实现,而不是整个替换。用 super 指令。

//类扩展
@interface BNREmployee ( )
@property (nonatomic) unsigned int officeAlarmCode;
@end
——头文件是类声明它的属性及方法的地方,这样其他的对象才能够知道如何和类进行交互。
——不是所有属性或方法都需要在类的头文件中声明,有的属性或方法只是该类或其实例菜需要使用的。涉及实现细节的属性或方法最好在类扩展中声明。
——类扩展是一组私有的声明,只有类和其实例才能使用在类扩展中声明的属性 实例变量或方法。
——类扩展添加在类实现文件中,实现方法的@implementation之上的。
——在类扩展中,和头文件中使用冒号和父类的名称不同,它使用的是一对空的括号。

强引用循环:两个对象互相拥有,这种“互相拥有”的所有权关系导致相关的对象都无法被释放,强引用循环是导致内存泄漏的常见原因。

弱引用:是不说明所有权的指针

强引用会保留对象的拥有方,使其不被释放,而弱引用则不会保留
标为弱引用的实例变量与属性指向的对象可能会消失,如果发生了这种情况,那这个实例变量或属性会被设为nil 而不是继续指向曾经指向的对象

C/C++/Objective-C 代码文件要经过两步才能完成编译
——预处理器(preprocessor)会读入并处理整个文件
——预处理器的输出结果会作为输入交给真正的编译器
——预处理指令都以 #开头

回调(callback):将一段可执行的代码和一个特定的事件绑定起来,当特定的事件发生时,就会执行这段代码。

当某个对象收到消息时,会向该对象的类进行查询,检查是否有与消息名称相匹配的方法
查询过程沿着继承层次结构向上,直到某个类回应“我有与消息名称相匹配的方法”
为了提速,编译器会为每个其接触过的方法附上一个唯一的数字,运行时,程序使用的是这个数字,而不是方法名
代表特定方法名的唯一数字称为选择器(selector)
当一个方法需要一个选择器作为实参时,它实际就是需要这个数字
通过编译指令 @selector 可以得到与方法名相对应的选择器

其它

协议是一组方法声明,其中的部分方法是必需的,另一些是可选的。
协议可以为一个对象制定角色。
如果某个对象要扮演特定的角色,就一定要实现相应的必需方法,并选择实现部分可选方法。

向新创建的对象发送 init 消息,它就会初始化其下的实例变量
Alloc 负责分配对象空间,init 负责初始化对象
Init 是实例方法,返回的是初始化后的对象地址

Instancetype 这个关键字会告诉编译器方法返回什么类型的对象,你编写的或是覆盖的任何初始化方法都应该返回 instancetype 类型的值。


这周就到这里结束了,希望下周能给大家带来更有价值的东西,做到真正的输出。还需要努力努力再努力,谢谢。