Effective Objective-C 2.0:Item 7: Access Instance Variables

原创 2013年12月03日 00:14:30

initializer: set 时候直接访问ivar;get时候看具体;

一般情况下,set用accessors; get用ivar快 

Item 7: Access Instance Variables Primarily Directly When Accessing Them Internally

Properties should always be used to access instance variables of an object externally, but how you access instance variables internally is a hotly debated topic within the Objective-C community. Some suggest always using a property to access instance variables, some suggest always accessing the instance variable directly, and some suggest a mixture of the two. I strongly encourage you to read instance variables using direct access but to set them using the property, with a few caveats.

Consider the following class:

@interface EOCPerson : NSObject
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;

// Convenience for firstName + " " + lastName:
- (NSString*)fullName;
- (void)setFullName:(NSString*)fullName;

The convenience methods fullName and setFullName: might be implemented like this:

- (NSString*)fullName {
    return [NSString stringWithFormat:@"%@ %@",
            self.firstName, self.lastName];

/** The following assumes all full names have exactly 2
 *  parts. The method could be rewritten to support more
 *  exotic names.
- (void)setFullName:(NSString*)fullName {
    NSArray *components =
        [fullName componentsSeparatedByString:@" "];
    self.firstName = [components objectAtIndex:0];
    self.lastName = [components objectAtIndex:1];

In both the getter and the setter, we access the instance variables via the accessor methods, using the property dot syntax. Now suppose that you rewrote both methods to access the instance variables directly:

- (NSString*)fullName {
    return [NSString stringWithFormat:@"%@ %@",
            _firstName, _lastName];

- (void)setFullName:(NSString*)fullName {
    NSArray *components =
        [fullName componentsSeparatedByString:@" "];
    _firstName = [components objectAtIndex:0];
    _lastName = [components objectAtIndex:1];

The two styles have a few differences.

Image Direct access to the instance variables will undoubtedly be faster, as it does not have to go through Objective-C method dispatch (see Item 11). The compiler will emit code that directly accesses the memory where the object’s instance variables are stored.

Image Direct access bypasses the property’s memory-management semantics defined by the setter. For example, if your property is declared as copy, directly setting the instance variable will not cause a copy to be made. The new value will be retained and the old value released.

Image Key-Value Observing (KVO) notifications would not be fired when accessing the instance variables directly. This may or may not be a problem, depending on how you want your objects to behave.

Image Accessing through properties can make it easier to debug issues surrounding a property, since you can add a breakpoint to the getter and/or setter to determine who is accessing the properties and when.

A good compromise is to write instance variables using the setter and to read using direct access. Doing so has the benefit of fast reading and not losing the control of writing via properties. The most important reason for writing via the setter is that you will ensure that the memory-management semantics are upheld. There are, however, a few caveats to that approach.

The first caveat is when values are set within an initializer method. Here, you should always use direct instance variable access, because subclasses could override the setter. Consider that EOCPerson has a subclass EOCSmithPerson that is designed to be used only for people whose last name is “Smith.” This subclass might override the setter for lastName like so:

- (void)setLastName:(NSString*)lastName {
    if (![lastName isEqualToString:@"Smith"]) {
        [NSException raise:NSInvalidArgumentException
                    format:@"Last name must be Smith"];
    self.lastName = lastname;

The base class EOCPerson might set the last name to the empty string in its default initializer. If it did this through the setter, the subclass’s setter would be called and throw an exception. However, there are some cases in which you must use the setterin an initializer. This is when the instance variable is declared within a superclass; you cannot access the instance variable directly anyway, so you must use the setter.

Another caveat is when the property uses lazy initialization. In this case, you have to go via the getter; if you don’t, the instance variable will never get a chance to be initialized. For example, the EOCPerson class might have a property to give access to a complex object representing each person’s brain. If this property is infrequently accessed and expensive to set up, you might initialize it lazily in the getter, like this:

- (EOCBrain*)brain {
    if (!_brain) {
        _brain = [Brain new];
    return _brain;

If you were to access the instance variable directly and the getter had not been called yet, brain would not have been set up, and you would need to call the accessor for all accesses to the brain property.

Things to Remember

Image Prefer to read data directly through instance variables internally and to write data through properties internally.

Image Within initializers and dealloc, always read and write data directly through instance variables.

Image Sometimes, you will need to read data through properties when that data is being lazily initialized.

编写高质量的iOS代码--Effective Objective-C 2.0 读书笔记

编写高质量的iOS代码--Effective Objective-C 2.0 读书笔记 这本书年初刷完,感觉不错,介绍了很多小点,都是平日不怎么关注的. 第1章 熟悉Objective-C...
  • uxyheaven
  • uxyheaven
  • 2014年12月26日 23:56
  • 5030

阅读《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》总结

第1条:了解Objective-C语言的起源 Objective-C为C语言添加了面向对象特性,是其超集。Objective-C使用动态绑定的消息结构,也就是说,在运行时才会检查对象类型。接收一...
  • caojengineer
  • caojengineer
  • 2015年06月07日 22:52
  • 1158

Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法(一)

1. 使用消息结构的语言,其运行时所应执行的代码由运行环境来决定;而使用函数调用的语言,则由编译器来决定。 如果范例代码调用的函数是多态的,则运行时根据虚函数表来查出应该执行哪个函数实现。 而采用...
  • mad2man
  • mad2man
  • 2014年03月25日 16:23
  • 3038

《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》--读书笔记

个人觉得这本书很不错!里面有很多很实用但以前没有太注意的地方,所以想纪录下来,当作自己的读书笔记吧。 熟悉Objective-C 1)Objective-C语言使用“消息结构”而不是“函数调用”。O...
  • weimeng809
  • weimeng809
  • 2016年01月11日 00:18
  • 569

Objective-C 2.0 基础要点归纳

本文的阅读基本条件: 具备C/C++基础知识,了解面向对象特征 阅读过《Objective-C 2.0 程序设计(第二版)》、《Objective-C 程序设计 第6版》或相关基础OC书籍 知识要点...
  • gujinjin2008
  • gujinjin2008
  • 2015年07月18日 20:11
  • 1584

【Effective Objective-C 2.0读书笔记】第一章:熟悉Objective-C

  • freeWayWalker
  • freeWayWalker
  • 2015年07月21日 17:42
  • 1417

Item 31:最小化文件之间的编译依赖 Effective C++笔记

Item 31: Minimize compilation dependencies between files. 曾听老师讲过,每天上班的第一件事就是下载最新代码开始编译,然后可以有半个小...
  • yangjvn
  • yangjvn
  • 2015年09月19日 11:56
  • 843

《Effective Objective-C 2.0》2、数据的定义方法

第三条:多用字面量语法,少用等价的方法 这部分所描述的是创建foundation类的对象时的技巧。Foundation框架是iOS中至关重要的框架,iOS应用中大部分数据都可以用foundation类...
  • shaqoneal
  • shaqoneal
  • 2015年04月21日 23:00
  • 712

【Effective Objective-C 2.0读书笔记】第五章:内存管理

Objective-C语言以引用计数来管理内存,这令许多初学者纠结,要是用过以“垃圾收集器”(garbage collector)来管理内存的语言,那么更会如此。“自动引用计数”机制缓解了此问题,不过...
  • freeWayWalker
  • freeWayWalker
  • 2015年06月11日 21:28
  • 772

JAVA菜鸟入门(12) reference variable是气球的线 +JVM中怎么实现

1 如果variable是primitive,那就拷贝原来变量的值到新变量。 2 如果variable是object referece, 那就拷贝原来reference的值到新的变量,所以就有2个re...
  • feliciafay
  • feliciafay
  • 2015年04月28日 23:42
  • 1652
您举报文章:Effective Objective-C 2.0:Item 7: Access Instance Variables