存取方法
本章向您介绍为什么应该使用存取方法,以及您应该如何声明和实现它们。
使用存取方法的一个主要原因是封装(见Objective-C面向对象编程中的“封装”部分)。在引用计数环境中,使用存取方法还有一个特别的好处,它们可以为您的类处理大部分的基本内存管理。
通常,您应该使用Objective - C的属性声明功能来声明存取方法,例如:
@property (copy) NSString *firstName;
|
@property (readonly) NSString *fullName;
|
@property (retain) NSDate *birthday;
|
@property NSInteger luckyNumber;
|
上述声明为属性指定了明确的内存管理语义。
在很多情况下,您可以(而且应该)避免实现您自己的存取方法,而使用Objective-C的属性声明功能,并要求编译器为您合成存取方法:
@synthesize firstName;
|
@synthesize fullName;
|
@synthesize birthday;
|
@synthesize luckyNumber;
|
即使您需要提供您自己的实现,您也应该使用声明属性来声明存取方法—当然,您必须保证您的实现符合您给出的规范。(要特别注意的是,在默认情况下,声明属性是原子的;如果您不提供原子的实现,那么您应该在声明中指定nonatomic
。)
对于简单的对象值来说,大致有三种方式来实现存取方法:
1. Getter在返回值之前保留并自动释放该值;setter释放旧的值并保留(或复制)新的值。
2. Getter返回值;setter自动释放旧的值并保留(或复制)新的值。
3. Getter返回值;setter释放旧的值并保留(或复制)新的值。
方法 1
在方法1中,getter返回的值在调用作用域内被自动释放:
- (NSString*) title {
|
return [[title retain] autorelease];
|
}
|
|
- (void) setTitle: (NSString*) newTitle {
|
if (title != newTitle) {
|
[title release];
|
title = [newTitle retain]; // Or copy, depending on your needs.
|
}
|
}
|
由于get存取器返回的对象在当前作用域内被自动释放,因此,如果属性的值发生改变,它仍然有效。这使得存取器更加健壮,但额外开销更多。如果您希望您的getter方法能够被频繁调用,则您也应该考虑到,相比于这种做法带来的性能开销,保留和自动释放对象所增加的额外开销是很不值得的。
方法 2
和方法1一样,方法2也使用了自动释放技术,但这次是在setter方法中完成:
- (NSString*) title {
|
return title;
|
}
|
|
- (void) setTitle: (NSString*) newTitle {
|
[title autorelease];
|
title = [newTitle retain]; // Or copy, depending on your needs.
|
}
|
在getter比setter调用更频繁的情况下,方法2的性能明显好于方法1。
方法 3
方法3完全没有使用自动释放技术:
- (NSString*) title {
|
return title;
|
}
|
|
- (void) setTitle: (NSString*) newTitle {
|
if (newTitle != title) {
|
[title release];
|
title = [newTitle retain]; // Or copy, depending on your needs.
|
}
|
}
|
方法3所采用的方式非常适合于getter和setter方法被频繁调用的情况。它也非常适合于那些不希望延长值的生命周期的对象,比如集合类。它的缺点是,旧的值可能被立即回收(如果没有其他的所有者),如果另一个对象持有指向该值的非所有性引用,那么这将导致一个问题。例如:
NSString *oldTitle = [anObject title];
|
[anObject setTitle:@"New Title"];
|
NSLog(@"Old title was: %@", oldTitle);
|
如果anObject
是拥有原始标题字符串的唯一对象,那么该字符串会在新的标题被设置之后被回收。随后,日志语句将引起程序崩溃,因为oldTitle
是一个已被释放的对象。
在Objective-C代码中,复制值对象—表示属性的对象—是一种很普遍的做法。C-类型的变量通常可以取代值对象,但值对象具有封装常用操作的优势。例如,NSString
对象被用来代替字符指针,因为它们封装了编码和存储。
当值对象作为方法的参数被传递或者从一个方法被返回时,通常会使用对象的副本而不是对象本身。例如,请仔细思考下面的方法,该方法将一个字符串赋值给对象的name
实例变量。
- (void)setName:(NSString *)aName {
|
[name autorelease];
|
name = [aName copy];
|
}
|
存储aName
的一个副本,其效果是产生一个独立于原始对象,但与原始对象具有相同内容的对象。副本的后续变化不会影响原始对象,并且原始对象的变化也不会影响副本。类似地,一种常见的做法是返回实例变量的副本,而不是实例变量本身。例如,下面的方法返回name
实例变量的一个副本:
- (NSString *)name {
|
return [[name copy] autorelease];
|
}
|
分享到:
相关推荐
这儿的运行时系统扮演的角色类似于Objective-C语言的操作系统,Objective-C基于该系统来工作。本文档将具体介绍NSObject类以及Objective-C程序是如何和运行时系统交互的。特别地,本文档还给出来怎样在运行时动态地加
objective-c运行时编程指南,
Objective-C高级编程 iOS与OS X多线程和内存管理.pdf
Objective-C高级编程 iOS与OS X多线程和内存管理.
《Objective-C 程序设计(第4版)》已经为iOS 5和Xcode4.2中的重大变更做了全面更新,最大的改动是引入了自动引用计数(ARC),并详细说明了如何在Objective-C编程过程中使用ARC提升和简化内存管理。
Objective-C 2.0运行时系统编程指南,有用指数5颗星。
objective-c 内存管理 alloc init release
帮助学习关于OC中内存管理的知识点
第7章到第10章讲述objective-c的基础框架,以及文件操作、内存管理、数据保存等内容。第11章讲述了应用工具框架。第12、13章分别讲述了如何开发iphone/ipad应用程序。第14章讲述了objective-c++和访问mysql数据库的...
Objective-C内存管理 刚接触的的人可能有些迷惑,看了本文 你将成为Objective-C内存管理高手 文字 高清版
Objective-C语言的许多决策可以在编译和运行时执行。只要有可能,它是动态的。这意味着Objective-C语言不仅需要一个编译器,还需要一个运行时系统来执行编译的代码。Runtime系统是一种用于Objective-C语言的操作系统...
Objective-C 内存管理 深入浅出发,熟悉内存管理。
通过学习Objective-C的基本语法、类和对象、控制流程和方法等内容,你将能够编写简单的Objective-C程序并逐渐掌握更复杂的概念。继续学习和实践,你将能够开发各种类型的应用程序,并为用户提供出色的体验。祝你在...
本书结合理论知识与示例程序,全面而系统地讲述Objective-C编程的相关内容,包括Objective-C在C的基础上引入的特性和Cocoa工具包的功能及其中的框架,以及继承、复合、源文件组织等众多重要的面向对象编程技术。...
初学objectice-C的朋友都有一个困惑,总觉得对objective-C的内存管理机制琢磨不透,程序经常内存泄漏 或莫名其妙的崩溃。我在这里总结了自己对objective-C内存管理机制的研究成果和经验,写了这么一个由 浅入深的...
objective-c 面向对象编程 ,主要讲objiectve-c 的面向对象方面。