Objective-C 笔记(一)
有关面向对象的相关术语
- 类(class)是一种表示对象类型的结构体。对象通过他的类来获取自身的各种信息,尤其是执行每个操作需要运行的代码。简单的程序可能仅包含少量的类,中等复杂的程序会包含十几个类。建议开发人员在objective-C编程时采用首字母大写的类名。
- 对象(object)是一种包含值和指向其类的隐藏指针的结构体。运行中的程序通常都包含成百上千对象。指针对象的变量通常不需要首字母大写。
- 实例(instance)是“对象”的另一种称呼。比方说circle对象也可以称为Circle类的实例。
- 消息(message)是对象可以执行的操作,用于通知对象去做什么。在【shape draw】的代码中,通过向shape对象发送draw消息来通知对象绘制自身。对象接收消息后,将查询相应的类,以便找到正确的代码来运行。
- 方法(method)是为响应消息而运行的代码。根据对象的类,消息(比如draw)可以调用不同的方法。
- 方法调度(method dispatcher)是Objective-C使用的一种机制,用于推测执行什么方法以响应某个特定的消息。
- 接口(interface)是类为对象提供的特性描述。
- 实现(implementation)是使接口能正常工作的代码。
@在Objective-C中可以把它看成对C语言的扩展
@interface
创建某个特定类的对象之前,Objective-C编译器需要一些有关该类的项宣,尤其是对象的数据成员(即对象的C语言类型借结构体应该是什么样子)及其提供的功能。可以使用@interface指令把这些信息传递给编译器
- 实例变量(instance variable)
- 方法声明(method declaration):列出了每个方法的名称、方法返回值的类型和某些参数
继承(is a)
OOP中的继承表明 一个类从另一个类(它的父类或超类(superclass)中获取了某些特性。
继承是在两个类之间建立关系的一种方式,它可以避免许多重复的代码
Objective-C不支持多继承
@interface Circle:Shape
@end
超类(superclass)、父类(parent class)是继承的类
子类(subclass)、孩子类(child class)是执行继承的类
继承在子类和父类之间建立了一种“is a “的关系
每个类都必须有一个父类,除了NSObject本身,它是所有类的父类
为了调用继承的方法在父类中的实习,需要使用super作为方法调用的目标
复合(composition)(has a )
复合:就像音乐中的作曲一样:将许多组件组合在一起,配合使用,从而得到完整的作品。在软件开发中,程序员可能会用一个Pedal(脚踏板)对象和一个Tire(轮胎)对象组合出虚拟的Unicyle(独轮车)
在Objective-C中,复合是通过包含作为实例变量的对象指针实现的
@interface Unicycle:NSObject
{
Pedal *pedal;
Tire * tire;
}
@end
存取(accessor)方法是用来读取或改变某个对象属性的方法(setter getter)
tips:如果要对其他对象中的属性进行操作,应该尽量使用对象提供的存取方法,绝对不能直接改变对象里面的值
拆分接口和实现
#improt <Cocoa/Cocoa.h> @interface Tire:NSObject @end #improt "Tire.h" A@implementation Tire -(NSString*)description{return(@“”);} @end
#import 编译器需要知道类里的实例变量的配置,这样才能生成合适的代码,但是它并不知道与源文件配套的头文件也存在,所以要添加#import语句,将此消息告知编译器,否则会报”Cannot find interface declaration for…”的信息错误。
tips:导入头文件有两种方法:使用引号或者尖括号,例如#import <Cocoa/Cocoa.h>和#import “Tire.h”,带尖括号的语句用于导入系统头文件(对项目来说是只读的,因为它属于系统),而带引号的语句则说明导入的是项目本地的头文件(参与项目的人可以编辑它)。
依赖关系(dependency)是两个实体之间的关系,可以存在于两个或对个文件之间
@class创建了一个前向引用,这是在告诉编译器“这是一个类,所以我只会通过指针来引用它”这样编译器就放心了:它不必之道关于这个类的更多信息,只要了解它是通过指针来引用的即可
@class可以解决循环依赖关系,即A类使用B类,B类也使用A类
通常将一个基本类型的数据封装成对象的过程被称为装箱(boxing),从对象中提取基本类型的数据叫做开箱(unboxing),Objective-C语言不支持自动装箱功能
内存管理:
是程序设计中常见的资源管理的一部分。每个计算机系统可供程序使用的资源是有限的,包括内存、打开的文件以及网络连接等。如果使用了某种资源,那么需要随后对其进行清理
内存泄露(leak memory)
对象的生命周期
诞生(通过alloc或new方法实现)
生存(接收消息并执行操作)
交友(通过复合以及向方法传递参数
死去(被释放掉)内存被回收
引用计数(reference counting)/保留计数(retain counting)
每个对象都有一个与之相关联的整数,被称作它的引用计数器或保留计数器
当某段代码需要访问一个对象时,该代码就将该对象的保留计数器值加1,表示“我要访问该对象”当这段代码结束对象访问时,将对象的保留计数器减1,表示它不再访问该对象。当保留计数器值为0时,表示不再有代码访问该对象了,因此它将被销毁,其占用的内存被系统回收以便重用。
当使用alloc、new方法或者通过copy消息(接收到消息的对象会创建一个自身的副本)创建一个对象时,对象的保留计数器值被设为1,要增加对象的保留计数器的值,可以给对象发送一条retain消息,要减少的话,可以给系统发送一条release消息
当一个对象因其保留计数器归0而即将被销毁时,Objective-C会自动向对象发送一条delloc消息。你可以在自己的对象里重写delloc方法,这样就能释放掉已经分配的全部相关资源,一定不要直接调用delloc方法,Objective-C会在需要销毁对象时自动调用它
要获得保留计数器当前的值,可以发送retainCount消息。
-(id)retain
-(oneway void)release
-(NSUInteger)retainCount
retain方法返回的一个id类型的值,通过这种方式,可以在接收其他消息的同时进行retain调用,增加对象的保留计数器的值并要求对象完成某种操作。例如[[car retain] setTire:tire atIndex:2];表示在要求car对象将其保留计数器的值加1并执行setTire操作
对象所有权(object ownership)
如果一个对象内有指向其他对象的实例变量时,则称该对象拥有这些对象
自动释放池(autorelease pool)
一个用来存放对象的池子(集合),并且能够自动释放
-(id)autorelease;
当给一个对象发送autorelease消息时,实际上是将该对象添加到了自动释放池中,当自动释放池被销毁时,会向该池中的所有对象发送release消息
创建一个自动释放池:
1.通过@autoreleasepool关键字
2.通过NSAutoreleasePool对象
NSAutoreleasePool *pool = [NSAutoreleasePool alloc]new];
…
[pool release];
在我们一直使用的Foundation库工具集中,创建和销毁自动释放池已经由@autorelease关键字完成,当你使用@autorelease{}时,所有在{}里的代码都会被放入这个新池子里。如果你的程序运算是内存密集型的,你可以使用这种自动释放池。
tips:
1.任何在{}里定义的变量在括号外就无法使用了
2.更加明确的方法就是使用NSAutoreleasePool对象。如果你使用了这个方法,创建和释放NSAutoreleasePool对象之间的代码就会使用这个新的池子。
推荐使用关键字方法,它比对象方法更快,因为Objective-C语音创建和释放内存的能力远在我们之上
使用AppKit时,Cocoa定期自动为你创建和销毁自动释放池。
-drain方法只是清空自动释放池而不会销毁它,而且只适用于Mac OSX10.4以后的操作系统版本
这些规则如下所示:
- 当你使用new、alloc或copy方法创建一个对象时,该对象的保留计数器的值为1。当不再使用该对象时, 你应该向该对象发送一条release或autorelease消息。这样,该对象将在其使用寿命结束时被销毁。
- 当你通过其他方法获取一个对象时,假设该对象的保留计数器的值为1,而且已经被设置为自动释放,那么你不需要执行任何操作来确保该对象得到清理。如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它。
- 如果你保留了某个对象,就需要(最终)释放或自动释放该对象。必须保持retain方法和release放发的使用次数相等。
对象初始化
属性(property)
类别(category)
是一种为现有的类添加新方法的方式
创建
@interface部分
委托(delegate)
是一种对象,由另一个类请求执行某些工作
NSNetServiceBrowser:支持你查找由Bonjour(Rcndezvous)发布的网络服务的Cocoa类
委托对象和类别的关系:委托强调类别的另一种应用:被发送给委托对象的方法可以声明为一个NSObject的类别,创建一个NSObject的类别成为创建一个“非正式协议”
@required
@optional
代码块和并发性
代码块和指针类似,具有以下特征
1.返回类型可以手动声明也可以由编译器推导
2.具有指定类型的参数列表
3.拥有名称