【问题标题】:General Programming Question about properties, assign, retain, and declarations关于属性、赋值、保留和声明的一般编程问题
【发布时间】:2011-01-10 20:20:59
【问题描述】:

我正在浏览 WWDC 的 AVCam 项目,我对以下代码感到好奇。我以为你应该声明一个对象,然后@property(非原子,保留),然后合成。

演示代码的作用稍有不同,我将发布一些代码(只是一个示例),有人知道这是做什么的以及何时应该使用它吗?谁能解释一下它的意义以及何时使用它?

    @interface AVCamCaptureManager : NSObject {
@private
    // Capture Session
    AVCaptureSession *_session;
    AVCaptureVideoOrientation _orientation;

    // Identifiers for connect/disconnect notifications
    id _deviceConnectedObserver;
    id _deviceDisconnectedObserver;
}

@property (nonatomic,readonly,retain) AVCaptureSession *session;
@property (nonatomic,assign) AVCaptureVideoOrientation orientation;
@property (nonatomic,readonly,retain) AVCaptureAudioChannel *audioChannel;
@property (nonatomic,assign) NSString *sessionPreset;

在实现文件中:

    @interface AVCamCaptureManager ()

@property (nonatomic,retain) AVCaptureSession *session;
@property (nonatomic,retain) AVCaptureDeviceInput *videoInput;
@property (nonatomic,retain) AVCaptureDeviceInput *audioInput;

@end

    @implementation AVCamCaptureManager

@synthesize session = _session;
@synthesize orientation = _orientation;
@dynamic audioChannel;
@dynamic sessionPreset;

@dynamic focusMode;


- (id) init
{

【问题讨论】:

    标签: iphone objective-c


    【解决方案1】:
    @property (nonatomic,readonly,retain) AVCaptureSession *session;
    

    这是一个外部为readonly 的属性。在内部,它将有一个保留新值的设置器。

    @property (nonatomic,assign) AVCaptureVideoOrientation orientation;
    

    这是一个通过简单赋值来存储新值的属性(因为您不能使用-copy-retain 原语)。

    @property (nonatomic,readonly,retain) AVCaptureAudioChannel *audioChannel;
    

    这是一个外部为readonly 的属性。在内部,它将有一个保留新值的设置器。

    @property (nonatomic,assign) NSString *sessionPreset;
    

    这是一个执行简单赋值以存储新字符串值的属性。这通常不是一个好主意,除非您只允许预设的预定义常量。在处理NSString 属性时,您通常希望它们为copy,除非您有充分的理由反对它。

    在实现文件中:

    @property (nonatomic,retain) AVCaptureSession *session;
    @property (nonatomic,retain) AVCaptureDeviceInput *videoInput;
    @property (nonatomic,retain) AVCaptureDeviceInput *audioInput;
    

    这些与标头中声明的属性一起使用,但现在它是readwrite。通过将标头中的版本声明为readonly,任何使用该类的人都将无法访问setSession: 方法。我们在内部重新声明了这个属性,以便我们可以访问 setter(并且 setter 保留新值)。此外,如果标题中不存在该属性,用户将不会知道它存在,但我们仍然可以在内部使用它。

    @synthesize session = _session;
    @synthesize orientation = _orientation;
    

    这意味着您希望编译器为sessionorientation 属性生成适当的setter 和getter,并且您希望这些属性将它们的值分别存储在_session_orientation 实例变量中.

    @dynamic audioChannel;
    @dynamic sessionPreset;
    @dynamic focusMode;
    

    这意味着 setter 和 getter 的实现将在运行时提供。您通常不会自己使用 @dynamic 属性,Core Data 框架提供的属性除外。

    【讨论】:

    • 我认为他们可能使用@dynamic 来表示他们正在手动编写getter/setter 方法,这也可以告诉编码人员@synthesize 方法没有被遗忘......还有一个标志让你知道没有默认方法,所以你应该看看手工创建的版本是做什么的。
    • 感谢您的澄清!在一般情况下或仅在情况需要时将属性设置为只读属性是一种好习惯吗?
    • @Kendall 好点。如果我自己编写访问器,我的偏好是省略 @synthesize/@dynamic 位。但是您指出自定义功能的观点很好。
    • @W Dyson - 当您不希望外部人员能够更改它们时,它们通常是只读的。 IOW,这完全取决于财产的用途。 :)
    • 所以就我而言,作为一名独立开发人员,没有理由担心其他人会阅读和更改属性,因为没有其他人会处理它们?还是您的意思是其他类读取和更改属性?
    【解决方案2】:

    在此代码中,会话属性在类外部定义为只读,在类内部定义为读写。通过在合成之前覆盖未命名类别中的会话属性,集合访问器也将被合成,但头文件说它是只读的,因此其他类不知道集合访问器。该类别还定义了两个对其他类根本不可见的新属性。

    retain 和 assign 关键字告诉编译器访问器方法应该如何工作。 Retain 表示 set 访问器应该保留属性的值,assign 关键字告诉它设置属性而不保留它。还有 copy,它复制值,通常用于确保未设置可变值。默认为assign,但如果没有为对象属性指定任何内容,编译器会发出警告。

    【讨论】:

      【解决方案3】:

      你能解释一下你对这里的困惑吗?我唯一的猜测是您对 audioChannel 和 sessionPreset 感到困惑,因为它们没有 ivars 并且被声明为 @dynamic(还有 focusMode,但我什至没有在您粘贴的代码中看到 @property 声明)。

      无论如何,我希望如果您阅读其余代码,您会发现已经编写了-audioChannel-sessionPreset 的getter,以及-setSessionPreset: 的setter。假设是这种情况,那么 @dynamic 声明是完全没有必要的。 @dynamic 只需要告诉编译器这些方法将在运行时存在;如果它们在编译时存在,那么您不需要任何指令。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-31
        • 2012-02-21
        • 2011-03-04
        • 2016-05-04
        • 1970-01-01
        • 1970-01-01
        • 2011-05-26
        相关资源
        最近更新 更多