何时使用实例变量以及何时使用属性?

时间:2010-06-26 08:52:35

标签: iphone objective-c

在诸如此类的头文件中,何时使用实例变量以及何时使用属性?

他们必须具有相同的名称吗?

#import <UIKit/UIKit.h>

@class BlueViewController;
@class YellowViewController;

@interface SwitchViewController : UIViewController {
    YellowViewController *yellowViewController;
    BlueViewController *blueViewController;
}

@property (retain, nonatomic) YellowViewController *yellowViewController;
@property (retain, nonatomic) BlueViewController *blueViewController;

@end

3 个答案:

答案 0 :(得分:4)

@property声明只为ivar创建存取方法。所以属性实际上没有名称,只有访问器方法呢;这些不必与ivar同名。事实上,他们甚至不需要相应的伊娃。

您可以使用gettersetter装饰器更改方法的名称,如下所示:

@property (assign, getter=isValid) BOOL valid;

现在,正如我所说,@property声明只是为ivar创建存取方法。因此,当您需要访问器方法时,可以使用属性。以下是您可能需要访问器方法的几个原因:

  1. 封装(属性可能会宣传为与ivar不同的类型,或者甚至可能没有ivar)

  2. 相关状态更改(更改另一个ivar或在修改ivar时调用方法)

  3. 您可以使用retain装饰器和@synthesize属性来简化内存管理

  4. 你可以使用atomic装饰器(或者根本不使用nonatomic装饰器,因为默认情况下属性是原子的)来创建原子属性

  5. 以下是演示第1点和第2点的示例:

    @interface Foo : NSObject {
        @private
        int flags;
        // Humpty and Dumpty are mutually exclusive
        BOOL humpty;
        BOOL dumpty;
    }
    
    @property (nonatomic) BOOL flagA;
    @property (nonatomic) BOOL flagB;
    @property (nonatomic) BOOL humpty;
    @property (nonatomic) BOOL dumpty;
    @property (nonatomic, readonly, getter=isClean) BOOL clean;
    
    @end
    
    @implementation Foo
    
    @synthesize humpty, dumpty; // Synthesize the getters, but provide the setters
    
    - (void)setHumpty:(BOOL)value {
        if(value && dumpty)
            dumpty = NO;
    
        humpty = value;
    }
    
    - (void)setDumpty:(BOOL)value {
        if(value && humpty)
            humpty = NO;
    
        dumpty = value;
    }
    
    - (BOOL)flagA {
        return flags & 0x01;
    }
    
    - (void)setFlagA:(BOOL)value {
        if(value)
            flags |= 0x01;
        else
            flags &= ~0x01;
    }
    
    - (BOOL)flagB {
        return flags & 0x02;
    }
    
    - (void)setFlagB:(BOOL)value {
        if(value)
            flags |= 0x02;
        else
            flags &= ~0x02;
    }
    
    // Making this a property doesn't really make sense
    // but I'm just trying to demonstrate what you can do
    // with properties
    - (BOOL)isClean {
        return flags == 0;
    }
    
    @end
    

答案 1 :(得分:0)

它们可以具有相同的名称,尽管它们不必具有相同的名称。实际上,外部可见属性并不需要完全对应于单个实例变量。如果您要使用@synthesize访问器方法,那么这种对应,但是有充分合理的理由手动创建方法并让它们做除了获取/设置之外的其他方法匹配ivar。

实例变量通常无法从外部访问,因此所有外部访问都必须通过属性方法。 (可以声明ivars @public,但这不是一个好主意。)

从对象内部,无论您是作为属性还是实例变量进行访问,都取决于属性的实际内容以及您使用它们执行的操作。

对于简单的合成属性,通常使用访问器(明确使用[self setXxx]或使用点符号作为self.xxx),dealloc内部(可能init除外) ,取决于你问的是谁。

在更复杂的情况下,你真的必须考虑你想要实现的目标。但是,如果你遇到了制作属性的麻烦,你可能希望在大多数情况下都可以调用封装在accessor方法中的任何功能。

无论如何,请阅读properties documentation以更好地了解正在发生的事情。

答案 2 :(得分:0)

您希望使用所有外部访问权限的属性来提供encapsulation,这取决于您是否要在内部使用它们,我认为这是一个品味问题。

通过使用类外部的属性,您可以执行一些惰性loading,通过在getter / setter中提供弃用警告,可以更轻松地进行任何潜在的API更改。