Objective-C 编程语言官网文档(五)-属性的声明

14 篇文章 0 订阅
14 篇文章 0 订阅

声明:本文档仅为个人学习过程中顺手翻译之作,方便开发的同胞借鉴参考。如有觉得译的不好不到位的地方,欢迎指正,将及时做出更正

尽量尊重原文档,因为首次Objective-C,有些地方可能直译了没有注意该语言的专有词,希望指正。如需转载,请注明出处


我的编程环境:

IDE:XCODE4.3.1

OS: MAC OS X 10.7.4

文章来译自:http://developer.apple.com/

属性声明

Objective-C 声明属性特性提供了一个简单的方式来声明以及实现一个变量访问其方法。

概述

通常你会通过一对访问器方法(getter/setter)来访问对象的属性 (in the sense of its attributes and relationships) 。通过使用访问器方法,你很好的遵循了封装的原则 (可以参考Object-Oriented Programming with Objective-C中的“Mechanisms Of Abstraction” )。当API的客户端与实现的改变保持隔离时,你可以有效的控制getter/setter 方法的以及对基本状态管理的行为。 

尽管使用访问器方法显然有着重要的好处,但写这些访问器方法无疑是件枯燥的活儿。除此之外,对于API的使用者很重要的属性方面变的含混不清—例如是否访问器方法是线程安全的或者当设值时是否新值被复制。

声明的属性通过提供以下特性来解决上述问题:

  • 属性声明为访问器方法的行为提供了清晰,显式的配置。

  • 编译器可以按照你在声明中的配置为你合成访问器方法。

  • 属性语法上表示标示符,加上作用域限制,因此,编译器可以检测到未声明的属性的使用。

属性声明以及实现

声明的属性包含两个部分,声明以及实现。

属性声明

属性声明以关键词@property开头。 @property 可以出现在类的 @interface 块中方法声明的任何地方。@property 还可以出现在protocol 或者 category声明中。

@property (attributes) type name;

@property 指令声明了一个属性。 括号内的可选参数提供了有关语义存储以及其它行为的额外细节—可用值可以参考 “Property Declaration Attributes” 。像其它的 Objective-C 类型,每个属性都有类型配置和名字。

4-1 展示了一个简单的属性声明

4-1  

@interface MyClass : NSObject
@property float value;
@end

你可以把一个属性声明等价于两个访问器方法。

@property float value;

等价于

- (float)value;
- (void)setValue:(float)newValue;

然而,一个属性声明还可以提供有关访问器方法如何实现的额外信息。 (就像 “Property Declaration Attributes” 中描述的那样).

你也可以把属性声明放在类扩展中 (参见“Extensions”). 例如,你可以把之前看到过的 value 属性声明如下:

@interface MyClass : NSObject
@end
 
@interface MyClass ()
@property float value;
@end

要是你向隐藏私有属性的声明的话,上面的方法将会很有用。

属性(Property)声明中的额外属性(Attribute)

Property跟Attribute都可翻译为属性,但两者在这里是不同的,Property只类范围的属性,而Attributes是额外属性,作用域比Property小。为避免混淆, 额外属性指代Attribute,如果没有加额外二字,则默认指Property。通过@property(attribute [, attribute2, ...])可以使用带有额外属性的属性。 像方法一样,属性作用域限定在它们的包装借口声明中。属性使用逗号来分隔一系列变量名,属性的额外属性会应用于所有的命名属性。

如果你使用 @synthesize 指令来告诉编译器去创建访问器方法 (参见 “Property Implementation Directives”),自动生成的代码与所给的关键词是匹配的。如果你自己来实现访问器方法,你应当确保访问器方法与配置相匹配 (例如,要是你指定了 copy ,你就要确保你确实将输入值拷贝到了setter 方法).

访问器方法名

默认与属性相关的getter 和 setter 方法是这样的形式: propertyName  和 setPropertyName  例如,有个属性叫 “foo”, 访问器则应当是foo 跟 setFoo:. 下面的结构则允许我们指定个性化的名字来取代上面的默认形式。它们都是可选的,可以出现在任何其它额外属性中(除了setter=中的 readonly ).

getter=getterName

指定属性的get访问器名。getter 返回值类型必须符合属性类型并且getter方法中不能有任何参数。

setter=setterName

指定属性的 set 访问器名。setter 方法必须带有一个与属性类型一样类型的参数,并且返回值类型为 void.

假如你指定了一个属性为 readonly 并且用 setter=指定了一个 setter方法, 编译器就会给出警告。

通常你指定的访问器方法名应当符合键值编码标准(参考 Key-Value Coding Programming Guide)—通常我们使用 getter 修饰器的原因是为了遵循布尔值的属性命名约定.

可写性

这些额外属性指定了是否一个属性与set访问器关联了。这些选项是互斥的。

readwrite

知名属性属性是 read/write. 默认是这个选项。

 getter 跟 setter 方法都要放在 @implementation 块中. 要是你在实现块中使用 @synthesize指令,  getter 和 setter 方法则将被集成。

readonly

指明属性是只读的。

如果你指定了 readonly, 那么 @implementation 块中只需要一个getter方法. 要是你在实现块中使用 @synthesize指令,  那么只有 getter 方法会被集成。除此之外,假设你试图使用逗点语法给一个只读属性赋值,编译器将会报错。

Setter 语法

这些额外属性指明了set访问器的语法。这些选项是互斥的。

strong

指明此属性跟目标对象有着紧密的(拥有)关系。

weak

指明与目标对象是松散的(非拥有)关系。

假如目标对象被释放了,属性值将自动被设为 nil.

( OS X v10.6 和 iOS 4不支持弱属性; 取而代之的是 assign.)

copy

指明对象的副本应当用于赋值操作。

之前的值发送给一个 release 消息.

副本通过调用 copy 方法被创建. 除了对象类型(实现了 NSCopying  协议),对其它类型这个额外属性是无效的。

assign

指明 setter 使用简单赋值。这个额外属性是默认选项。

在标量类型中你会用到这个额外属性,例如 NSInteger 和 CGRect.

retain

指明对象赋值时执行 retain 。

之前的值将发给一个 release 消息。

在 OS X v10.6 以及更新的版本中,你可以使用 __attribute__ 关键字来指定一个 Core Foundation 属性应当被当做一个用于内存管理的 Objective-C 对象对待。

@property(retain) __attribute__((NSObject)) CFDictionaryRef myDictionary;
原子性

你可以使用这个额外属性来指明访问器方法是非原子的。 (没有关键词可以表示原子的)

nonatomic

指明访问器是非原子的。默认情况下,访问器是原子的。

属性默认是原子的,这种情况下生成的访问器提供了多线程环境下对属性的安全访问/存取互斥互斥,同一时刻,只有一个线程可以访问属性。

要是你指定了 strongcopy 或者 retain 并且没有指定 nonatomic 那么在一个引用计数环境中,为属性生成的get访问器将使用lock, retain ,自动释放返回的值,然后才返回结果。实现与下面的代码类似:

[_internal lock]; // lock using an object-level lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;

要是指定了 nonatomic, 该对象属性生成的访问器会直接返回值。

标记和弃用

属性支持所有C形式的修饰符。属性可以被启用并支持 __attribute__风格的标记:

@property CGFloat x
AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
@property CGFloat y __attribute__((...));

如果你向指定某个属性为一个 outlet (参考 outlet in iOS, 以及 outlet in OS X), 你可以使用 IBOutlet 标示符:

@property (nonatomic, weak) IBOutlet NSButton *myButton;

尽管IBOutlet 不是这些额外属性列表中的正式成员。更多有关声明 outlet 属性的信息,可以参见“Nib Files”.

属性的实现指令

你可以在 @implementation 块中使用 @synthesize 和 @dynamic 指令来触发特定的编译器动作。这些对 @property 声明的属性都是可选的。

注意 如果你没有为一个特定的属性指定 @synthesize 或者 @dynamic ,那么你就必须提供属性的 getter 及 setter 方法实现(或者在 readonly 情况下提供getter) ,否则,编译器就会给出一个警告。

@synthesize

你可以使用 @synthesize 指令来告诉编译器,要是你没有在 @implementation 块中提供setter/getter方法,则它应当为一个该属性生成它们。 @synthesize指令还可以为它生成一个实例变量。 

Listing 4-2  使用 @synthesize

@interface MyClass : NSObject
@property(copy, readwrite) NSString *value;
@end
 
@implementation MyClass
@synthesize value;
@end

你可以使用 property=ivar 的形式来为一个属性指定一个特定的实例变量,例如

@synthesize firstName, lastName, age=yearsOld;

生成方法的其它方面决定于其它可选的额外属性。(参见 “Property Declaration Attributes”).

你指定的实例变量的名字, @synthesize 指令只能使用来自当前类的实例变量,而不是父类中的。

访问器方法的生成行为可能因运行时环境而异(可以参考 “Runtime Difference”):

  • 对于 legacy 运行时环境, 实例变量必须已经声明在当前类的 @interface 块中了. 如果有跟属性同名的一个实例变量存在,并且类型也与属性类型一致,它将被使用,否则,你将看到一个编译器错误。

  • 而对于 modern 运行时 (参考Objective-C Runtime Programming Guide 中的 “Runtime Versions and Platforms”  ),实例变量将按需生成。如果一个同名实例变量存在,它将被使用。

@dynamic

你可以使用 @dynamic 关键字来告诉编译器,属性的获取与赋值方法由用户自己实现, 不自动生成,不在这个类中,可能在父类或者别的地方。只有在你确信运行时这些访问器方法将可用时才使用这个关键字。

例如:

 4-3  

@interface MyClass : NSManagedObject
@property(nonatomic, retain) NSString *value;
@end
 
@implementation MyClass
@dynamic value;
@end

NSManagedObject 是由 Core Data 框架提供的,一个托管的对象类有它自己相应的架构,定义有类的属性及关系。运行时, Core Data 框架会为它们按需生成访问器方法。

使用属性

支持类型

你可以为任何Objective-C 类声明属性, Core Foundation 数据类型,或者 “plain old data” (POD) 类型 (参见 C++ Language Note: POD Types).使用 Core Foundation 类型的约束,可以参看 “Core Foundation.”

属性的重定义

你可以在子类中对一个属性进行重定义,但是 (with the exception of readonly versus readwrite) 你必须在子类中同样重复它的所有额外属性。对于类别或者协议中的属性也是一样的—当属性可能在类别或者协议中被重定义式,属性的所有额外属性也要被完整重复。

如果你在一个类中声明了一个 readonly 属性,你可以在一个类扩展(参见“Extensions”)/协议或者子类中(参见 “Subclassing with Properties”)中把它声明为 readwrite。重声明一个只读属性的能力使两种常见的实现模式成为可能: 一个不可变父类的可变的子类(例如 NSString, NSArray, 和 NSDictionary) 以及一个作用域声明为public的只读属性有着一个作用域为私有的可读写的属性实现。例如:

// public header file
@interface MyObject : NSObject
@property (readonly, copy) NSString *language;
@end
 
// private implementation file
@interface MyObject ()
@property (readwrite, copy) NSString *language;
@end
 
@implementation MyObject
@synthesize language;
@end

Core Foundation

就像在 “Property Declaration Attributes,” 一节中提到的, Mac OS X v10.6 之前不能为非对象类型指定 retain 额外属性。假设,你要声明一个类型为CFT的属性,并且像下面的例子中这样自动生成访问器。

@interface MyClass : NSObject
@property(readwrite) CGImageRef myImage;
@end
 
@implementation MyClass
@synthesize myImage;
@end

在引用计数环境中,自动生成的set访问器简单的为实例变量赋予了一个新值(新值没有保持而旧值没有释放). 对于Core Foundation对象来说,简单赋值通常是错误的。你不应该自动生成这些方法,而是你自己来实现。

属性子类化

你可以重写一个 readonly 属性,并用可写来替换它。 例如,下面定义了一个类MyInteger ,它有一个只读的属性 value:

@interface MyInteger : NSObject
@property(readonly) NSInteger value;
@end
 
@implementation MyInteger
@synthesize value;
@end

然后你实现了一个子类,MyMutableInteger, 它重定义了这个属性并把它设为可写

@interface MyMutableInteger : MyInteger
@property(readwrite) NSInteger value;
@end
 
@implementation MyMutableInteger
@dynamic value;
 
- (void)setValue:(NSInteger)newX {
    value = newX;
}
@end

运行时差异

一般情况下属性在 modern 和 legacy 运行时环境下的行为是一致的 (参见Objective-C Runtime Programming Guide 中的 “Runtime Versions and Platforms” )。 有个关键的区别是,modern 运行时支持实例变量的访问器方法自动生成而 legacy 运行时不支持。

要让 @synthesize 在 legacy 运行时能够工作,你就必须提供一个跟该属性有相同名字以及类型的实例变量或者指定另外一个已经存在于 @synthesize 块中的实例变量。在 modern 运行时下, 如果你不提供实例变量,编译器会为你自动添加一个。例如,

@interface MyClass : NSObject
@property float noDeclaredIvar;
@end
 
@implementation MyClass
@synthesize noDeclaredIvar;
@end

在 legacy 运行时下会在 @synthesize noDeclaredIvar 处报错,而在 modern 运行时下,编译器会添加一个实例变量来代替noDeclaredIvar.



英文原文:

Declared Properties

The Objective-C declared properties feature provides a simple way to declare and implement an object’s accessor methods.

Overview

You typically access an object’s properties (in the sense of its attributes and relationships) through a pair of accessor (getter/setter) methods. By using accessor methods, you adhere to the principle of encapsulation (see“Mechanisms Of Abstraction” in Object-Oriented Programming with Objective-C). You can exercise tight control of the behavior of the getter/setter pair and the underlying state management while clients of the API remain insulated from the implementation changes.

Although using accessor methods therefore has significant advantages, writing accessor methods is a tedious process. Moreover, aspects of the property that may be important to consumers of the API are left obscured—such as whether the accessor methods are thread-safe or whether new values are copied when set.

Declared properties address these issues by providing the following features:

  • The property declaration provides a clear, explicit specification of how the accessor methods behave.

  • The compiler can synthesize accessor methods for you, according to the specification you provide in the declaration.

  • Properties are represented syntactically as identifiers and are scoped, so the compiler can detect use of undeclared properties.

Property Declaration and Implementation

There are two parts to a declared property, its declaration and its implementation.

Property Declaration

A property declaration begins with the keyword @property@property can appear anywhere in the method declaration list found in the @interface block of a class. @property can also appear in the declaration of aprotocol or category.

@property (attributes) type name;

The @property directive declares a property. An optional parenthesized set of attributes provides additional details about the storage semantics and other behaviors of the property—see “Property Declaration Attributes” for possible values. Like any other Objective-C type, each property has a type specification and a name.

Listing 4-1 illustrates the declaration of a simple property.

Listing 4-1  Declaring a simple property

@interface MyClass : NSObject
@property float value;
@end

You can think of a property declaration as being equivalent to declaring two accessor methods. Thus

@property float value;

is equivalent to:

- (float)value;
- (void)setValue:(float)newValue;

A property declaration, however, provides additional information about how the accessor methods are implemented (as described in “Property Declaration Attributes”).

You can also put property declarations in class extensions (see “Extensions”). For example, you could declare thevalue property shown previously as follows:

@interface MyClass : NSObject
@end
 
@interface MyClass ()
@property float value;
@end

This is useful if you want to hide the declaration of private properties.

Property Declaration Attributes

You can decorate a property with attributes by using the form @property(attribute [, attribute2, ...]). Like methods, properties are scoped to their enclosing interface declaration. For property declarations that use a comma-delimited list of variable names, the property attributes apply to all of the named properties.

If you use the @synthesize directive to tell the compiler to create the accessor methods (see “Property Implementation Directives”), the code it generates matches the specification given by the keywords. If you implement the accessor methods yourself, you should ensure that it matches the specification (for example, if you specify copy you must make sure that you do copy the input value in the setter method).

Accessor Method Names

The default names for the getter and setter methods associated with a property are propertyName andsetPropertyName: respectively—for example, given a property “foo”, the accessors would be foo and setFoo:. The following attributes allow you to specify custom names instead. They are both optional and can appear with any other attribute (except for readonly in the case of setter=).

getter=getterName

Specifies the name of the get accessor for the property. The getter must return a type matching the property’s type and take no parameters.

setter=setterName

Specifies the name of the set accessor for the property. The setter method must take a single parameter of a type matching the property’s type and must return void.

If you specify that a property is readonly and also specify a setter with setter=, you get a compiler warning.

Typically you should specify accessor method names that are key-value coding compliant (see Key-Value Coding Programming Guide)—a common reason for using the getter decorator is to adhere to the isPropertyNameconvention for Boolean values.

Writability

These attributes specify whether or not a property has an associated set accessor. They are mutually exclusive.

readwrite

Indicates that the property should be treated as read/write. This attribute is the default.

Both a getter and setter method are required in the @implementation block. If you use the @synthesizedirective in the implementation block, the getter and setter methods are synthesized.

readonly

Indicates that the property is read-only.

If you specify readonly, only a getter method is required in the @implementation block. If you use the@synthesize directive in the implementation block, only the getter method is synthesized. Moreover, if you attempt to assign a value using the dot syntax, you get a compiler error.

Setter Semantics

These attributes specify the semantics of a set accessor. They are mutually exclusive.

strong

Specifies that there is a strong (owning) relationship to the destination object.

weak

Specifies that there is a weak (non-owning) relationship to the destination object.

If the destination object is deallocated, the property value is automatically set to nil.

(Weak properties are not supported on OS X v10.6 and iOS 4; use assign instead.)

copy

Specifies that a copy of the object should be used for assignment.

The previous value is sent a release message.

The copy is made by invoking the copy method. This attribute is valid only for object types, which must implement the NSCopying  protocol.

assign

Specifies that the setter uses simple assignment. This attribute is the default.

You use this attribute for scalar types such as NSInteger and CGRect.

retain

Specifies that retain should be invoked on the object upon assignment.

The previous value is sent a release message.

In OS X v10.6 and later, you can use the __attribute__ keyword to specify that a Core Foundation property should be treated like an Objective-C object for memory management:

@property(retain) __attribute__((NSObject)) CFDictionaryRef myDictionary;
Atomicity

You can use this attribute to specify that accessor methods are not atomic. (There is no keyword to denote atomic.)

nonatomic

Specifies that accessors are nonatomic. By default, accessors are atomic.

Properties are atomic by default so that synthesized accessors provide robust access to properties in a multithreaded environment—that is, the value returned from the getter or set via the setter is always fully retrieved or set regardless of what other threads are executing concurrently.

If you specify strongcopy, or retain and do not specify nonatomic, then in a reference-counted environment, a synthesized get accessor for an object property uses a lock and retains and autoreleases the returned value—the implementation will be similar to the following:

[_internal lock]; // lock using an object-level lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;

If you specify nonatomic, a synthesized accessor for an object property simply returns the value directly.

Markup and Deprecation

Properties support the full range of C-style decorators. Properties can be deprecated and support __attribute__style markup:

@property CGFloat x
AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
@property CGFloat y __attribute__((...));

If you want to specify that a property is an outlet (see outlet in iOS, and outlet in OS X), you use the IBOutletidentifier:

@property (nonatomic, weak) IBOutlet NSButton *myButton;

IBOutlet is not, though, a formal part of the list of attributes. For more about declaring outlet properties, see“Nib Files”.

Property Implementation Directives

You can use the @synthesize and @dynamic directives in @implementation blocks to trigger specific compiler actions. Note that neither is required for any given @property declaration.

Important If you do not specify either @synthesize or @dynamic for a particular property, you must provide a getter and setter (or just a getter in the case of a readonly property) method implementation for that property. If you do not, the compiler generates a warning.

@synthesize

You use the @synthesize directive to tell the compiler that it should synthesize the setter and/or getter methods for a property if you do not supply them within the @implementation block. The @synthesizedirective also synthesizes an appropriate instance variable if it is not otherwise declared.

Listing 4-2  Using @synthesize

@interface MyClass : NSObject
@property(copy, readwrite) NSString *value;
@end
 
@implementation MyClass
@synthesize value;
@end

You can use the form property=ivar to indicate that a particular instance variable should be used for the property, for example:

@synthesize firstName, lastName, age=yearsOld;

This specifies that the accessor methods for firstNamelastName, and age should be synthesized and that the property age is represented by the instance variable yearsOld. Other aspects of the synthesized methods are determined by the optional attributes (see “Property Declaration Attributes”).

Whether or not you specify the name of the instance variable, the @synthesize directive can use an instance variable only from the current class, not a superclass.

There are differences in the behavior of accessor synthesis that depend on the runtime (see also “Runtime Difference”):

  • For the legacy runtimes, instance variables must already be declared in the @interface block of the current class. If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used—otherwise, you get a compiler error.

  • For the modern runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide), instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.

@dynamic

You use the @dynamic keyword to tell the compiler that you will fulfill the API contract implied by a property either by providing method implementations directly or at runtime using other mechanisms such as dynamic loading of code or dynamic method resolution. It suppresses the warnings that the compiler would otherwise generate if it can’t find suitable implementations. You should use it only if you know that the methods will be available at runtime.

The example shown in Listing 4-3 illustrates using @dynamic with a subclass of NSManagedObject.

Listing 4-3  Using @dynamic with NSManagedObject

@interface MyClass : NSManagedObject
@property(nonatomic, retain) NSString *value;
@end
 
@implementation MyClass
@dynamic value;
@end

NSManagedObject is provided by the Core Data framework. A managed object class has a corresponding schema that defines attributes and relationships for the class; at runtime, the Core Data framework generates accessor methods for these as necessary. You therefore typically declare properties for the attributes and relationships, but you don’t have to implement the accessor methods yourself and shouldn’t ask the compiler to do so. If you just declared the property without providing any implementation, however, the compiler would generate a warning. Using @dynamic suppresses the warning.

Using Properties

Supported Types

You can declare a property for any Objective-C class, Core Foundation data type, or “plain old data” (POD) type (see C++ Language Note: POD Types). For constraints on using Core Foundation types, however, see “Core Foundation.”

Property Redeclaration

You can redeclare a property in a subclass, but (with the exception of readonly versus readwrite) you must repeat its attributes in whole in the subclasses. The same holds true for a property declared in a category orprotocol—while the property may be redeclared in a category or protocol, the property’s attributes must be repeated in whole.

If you declare a property in one class as readonly, you can redeclare it as readwrite in a class extension (see“Extensions”), in a protocol, or in a subclass (see “Subclassing with Properties”). In the case of a class extension redeclaration, the fact that the property was redeclared prior to any @synthesize statement causes the setter to be synthesized. The ability to redeclare a read-only property as read/write enables two common implementation patterns: a mutable subclass of an immutable class (NSStringNSArray, and NSDictionary are all examples) and a property that has a public API that is readonly but a private readwrite implementation internal to the class. The following example shows using a class extension to provide a property that is declared as read-only in the public header but is redeclared privately as read/write.

// public header file
@interface MyObject : NSObject
@property (readonly, copy) NSString *language;
@end
 
// private implementation file
@interface MyObject ()
@property (readwrite, copy) NSString *language;
@end
 
@implementation MyObject
@synthesize language;
@end

Core Foundation

As noted in “Property Declaration Attributes,” prior to Mac OS X v10.6 you cannot specify the retain attribute for non-object types. If, therefore, you declare a property whose type is a CFType and synthesize the accessors as illustrated in the following example:

@interface MyClass : NSObject
@property(readwrite) CGImageRef myImage;
@end
 
@implementation MyClass
@synthesize myImage;
@end

then in a reference-counted environment, the synthesized set accessor simply assigns the new value to the instance variable (the new value is not retained and the old value is not released). Simple assignment is typically incorrect for Core Foundation objects; you should not synthesize the methods but rather implement them yourself.

Subclassing with Properties

You can override a readonly property to make it writable. For example, you could define a class MyInteger with a readonly property, value:

@interface MyInteger : NSObject
@property(readonly) NSInteger value;
@end
 
@implementation MyInteger
@synthesize value;
@end

You could then implement a subclass, MyMutableInteger, which redefines the property to make it writable:

@interface MyMutableInteger : MyInteger
@property(readwrite) NSInteger value;
@end
 
@implementation MyMutableInteger
@dynamic value;
 
- (void)setValue:(NSInteger)newX {
    value = newX;
}
@end

Runtime Difference

In general the behavior of properties is identical on both modern and legacy runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.

For @synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the @synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you. For example, given the following class declaration and implementation:

@interface MyClass : NSObject
@property float noDeclaredIvar;
@end
 
@implementation MyClass
@synthesize noDeclaredIvar;
@end

the compiler for the legacy runtime would generate an error at @synthesize noDeclaredIvar; whereas the compiler for the modern runtime would add an instance variable to represent noDeclaredIvar.


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值