Objective-C 编程语言官网文档(五)-属性的声明
2012-06-04 18:22
435 查看
声明:本文档仅为个人学习过程中顺手翻译之作,方便开发的同胞借鉴参考。如有觉得译的不好不到位的地方,欢迎指正,将及时做出更正
尽量尊重原文档,因为首次Objective-C,有些地方可能直译了没有注意该语言的专有词,希望指正。如需转载,请注明出处
我的编程环境:
IDE:XCODE4.3.1
OS:MACOSX10.7.4
文章来译自:http://developer.apple.com/
属性声明
Objective-C声明属性特性提供了一个简单的方式来声明以及实现一个变量访问其方法。
概述
通常你会通过一对访问器方法(getter/setter)来访问对象的属性(inthesenseofitsattributesandrelationships)。通过使用访问器方法,你很好的遵循了封装的原则(可以参考Object-OrientedProgrammingwithObjective-C中的“Mechanisms
OfAbstraction”)。当API的客户端与实现的改变保持隔离时,你可以有效的控制getter/setter方法的以及对基本状态管理的行为。
尽管使用访问器方法显然有着重要的好处,但写这些访问器方法无疑是件枯燥的活儿。除此之外,对于API的使用者很重要的属性方面变的含混不清—例如是否访问器方法是线程安全的或者当设值时是否新值被复制。
声明的属性通过提供以下特性来解决上述问题:
属性声明为访问器方法的行为提供了清晰,显式的配置。
编译器可以按照你在声明中的配置为你合成访问器方法。
属性语法上表示标示符,加上作用域限制,因此,编译器可以检测到未声明的属性的使用。
属性声明以及实现
声明的属性包含两个部分,声明以及实现。
属性声明
属性声明以关键词@property开头。
@property可以出现在类的
@interface块中方法声明的任何地方。
@property还可以出现在protocol或者category声明中。
@property(attributes)typename; |
@property指令声明了一个属性。括号内的可选参数提供了有关语义存储以及其它行为的额外细节—可用值可以参考“Property
DeclarationAttributes”。像其它的Objective-C类型,每个属性都有类型配置和名字。
4-1展示了一个简单的属性声明
4-1
@interfaceMyClass:NSObject |
@propertyfloatvalue; |
@end |
@propertyfloatvalue; |
-(float)value; |
-(void)setValue:(float)newValue; |
DeclarationAttributes”中描述的那样).
你也可以把属性声明放在类扩展中(参见
例如,你可以把之前看到过的
value属性声明如下:
@interfaceMyClass:NSObject |
@end |
@interfaceMyClass() |
@propertyfloatvalue; |
@end |
属性(Property)声明中的额外属性(Attribute)
Property跟Attribute都可翻译为属性,但两者在这里是不同的,Property只类范围的属性,而Attributes是额外属性,作用域比Property小。为避免混淆,额外属性指代Attribute,如果没有加额外二字,则默认指Property。通过@property(attribute可以使用带有额外属性的属性。像方法一样,属性作用域限定在它们的包装借口声明中。属性使用逗号来分隔一系列变量名,属性的额外属性会应用于所有的命名属性。
[,attribute2,...])
如果你使用
@synthesize指令来告诉编译器去创建访问器方法(参见“Property
ImplementationDirectives”),自动生成的代码与所给的关键词是匹配的。如果你自己来实现访问器方法,你应当确保访问器方法与配置相匹配(例如,要是你指定了
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
CodingProgrammingGuide)—通常我们使用
getter修饰器的原因是为了遵循布尔值的属性命名约定.
可写性
这些额外属性指定了是否一个属性与set访问器关联了。这些选项是互斥的。readwrite
知名属性属性是read/write.默认是这个选项。
getter跟setter方法都要放在
@implementation块中.要是你在实现块中使用
@synthesize指令,
getter和setter方法则将被集成。
readonly
指明属性是只读的。
如果你指定了
readonly,那么
@implementation块中只需要一个getter方法.要是你在实现块中使用
@synthesize指令,
那么只有getter方法会被集成。除此之外,假设你试图使用逗点语法给一个只读属性赋值,编译器将会报错。
Setter语法
这些额外属性指明了set访问器的语法。这些选项是互斥的。strong
指明此属性跟目标对象有着紧密的(拥有)关系。
weak
指明与目标对象是松散的(非拥有)关系。
假如目标对象被释放了,属性值将自动被设为
nil.
(OSXv10.6和iOS4不支持弱属性;取而代之的是
assign.)
copy
指明对象的副本应当用于赋值操作。
之前的值发送给一个
消息.release
副本通过调用
方法被创建.copy
除了对象类型(实现了
NSCopying协议),对其它类型这个额外属性是无效的。
assign
指明setter使用简单赋值。这个额外属性是默认选项。
在标量类型中你会用到这个额外属性,例如
NSInteger和
CGRect.
retain
指明对象赋值时执行
。retain
之前的值将发给一个
消息。release
在OSXv10.6以及更新的版本中,你可以使用
__attribute__关键字来指定一个CoreFoundation属性应当被当做一个用于内存管理的Objective-C对象对待。
@property(retain)__attribute__((NSObject))CFDictionaryRefmyDictionary; |
原子性
你可以使用这个额外属性来指明访问器方法是非原子的。(没有关键词可以表示原子的)nonatomic
指明访问器是非原子的。默认情况下,访问器是原子的。
属性默认是原子的,这种情况下生成的访问器提供了多线程环境下对属性的安全访问/存取互斥互斥,同一时刻,只有一个线程可以访问属性。
要是你指定了
strong,
copy或者
retain并且没有指定
nonatomic那么在一个引用计数环境中,为属性生成的get访问器将使用lock,
retain,自动释放返回的值,然后才返回结果。实现与下面的代码类似:
[_internallock];//lockusinganobject-levellock |
idresult=[[valueretain]autorelease]; |
[_internalunlock]; |
returnresult; |
nonatomic,该对象属性生成的访问器会直接返回值。
标记和弃用
属性支持所有C形式的修饰符。属性可以被启用并支持__attribute__风格的标记:
@propertyCGFloatx |
***AILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4; |
@propertyCGFloaty__attribute__((...)); |
OSX),你可以使用
IBOutlet标示符:
@property(nonatomic,weak)IBOutletNSButton*myButton; |
尽管IBOutlet不是这些额外属性列表中的正式成员。更多有关声明outlet属性的信息,可以参见“Nib
Files”.
属性的实现指令
你可以在@implementation块中使用
@synthesize和
@dynamic指令来触发特定的编译器动作。这些对
@property声明的属性都是可选的。
[b]注意如果你没有为一个特定的属性指定
@synthesize或者
@dynamic,那么你就必须提供属性的
getter及setter方法实现(或者在
readonly情况下提供getter),否则,编译器就会给出一个警告。
@synthesize
你可以使用
@synthesize指令来告诉编译器,要是你没有在
@implementation块中提供setter/getter方法,则它应当为一个该属性生成它们。
@synthesize指令还可以为它生成一个实例变量。
Listing4-2使用@synthesize
@interfaceMyClass:NSObject |
@property(copy,readwrite)NSString*value; |
@end |
@implementationMyClass |
@synthesizevalue; |
@end |
property=ivar的形式来为一个属性指定一个特定的实例变量,例如
@synthesizefirstName,lastName,age=yearsOld; |
DeclarationAttributes”).
你指定的实例变量的名字,
@synthesize指令只能使用来自当前类的实例变量,而不是父类中的。
访问器方法的生成行为可能因运行时环境而异(可以参考“Runtime
Difference”):
对于legacy运行时环境,实例变量必须已经声明在当前类的
@interface块中了.如果有跟属性同名的一个实例变量存在,并且类型也与属性类型一致,它将被使用,否则,你将看到一个编译器错误。
而对于modern运行时(参考Objective-C
RuntimeProgrammingGuide中的“Runtime
VersionsandPlatforms”),实例变量将按需生成。如果一个同名实例变量存在,它将被使用。
@dynamic
你可以使用
@dynamic关键字来告诉编译器,属性的获取与赋值方法由用户自己实现,不自动生成,不在这个类中,可能在父类或者别的地方。只有在你确信运行时这些访问器方法将可用时才使用这个关键字。
例如:
4-3
@interfaceMyClass:NSManagedObject |
@property(nonatomic,retain)NSString*value; |
@end |
@implementationMyClass |
@dynamicvalue; |
@end |
NSManagedObject是由CoreData框架提供的,一个托管的对象类有它自己相应的架构,定义有类的属性及关系。运行时,CoreData框架会为它们按需生成访问器方法。
使用属性
支持类型
你可以为任何Objective-C类声明属性,CoreFoundation数据类型,或者“plainolddata”(POD)类型(参见C++LanguageNote:PODTypes).使用CoreFoundation类型的约束,可以参看“Core
Foundation.”
属性的重定义
你可以在子类中对一个属性进行重定义,但是(withtheexceptionofreadonlyversus
readwrite)
你必须在子类中同样重复它的所有额外属性。对于类别或者协议中的属性也是一样的—当属性可能在类别或者协议中被重定义式,属性的所有额外属性也要被完整重复。
如果你在一个类中声明了一个
readonly属性,你可以在一个类扩展(参见
协议或者子类中(参见“Subclassing
withProperties”)中把它声明为
readwrite。重声明一个只读属性的能力使两种常见的实现模式成为可能:一个不可变父类的可变的子类(例如
NSString,
NSArray,
和
NSDictionary)以及一个作用域声明为public的只读属性有着一个作用域为私有的可读写的属性实现。例如:
//publicheaderfile |
@interfaceMyObject:NSObject |
@property(readonly,copy)NSString*language; |
@end |
//privateimplementationfile |
@interfaceMyObject() |
@property(readwrite,copy)NSString*language; |
@end |
@implementationMyObject |
@synthesizelanguage; |
@end |
CoreFoundation
就像在“PropertyDeclarationAttributes,”一节中提到的,MacOSXv10.6之前不能为非对象类型指定
retain额外属性。假设,你要声明一个类型为CFT的属性,并且像下面的例子中这样自动生成访问器。
@interfaceMyClass:NSObject |
@property(readwrite)CGImageRefmyImage; |
@end |
@implementationMyClass |
@synthesizemyImage; |
@end |
属性子类化
你可以重写一个readonly属性,并用可写来替换它。例如,下面定义了一个类
MyInteger,它有一个只读的属性
value:
@interfaceMyInteger:NSObject |
@property(readonly)NSIntegervalue; |
@end |
@implementationMyInteger |
@synthesizevalue; |
@end |
MyMutableInteger,它重定义了这个属性并把它设为可写
@interfaceMyMutableInteger:MyInteger |
@property(readwrite)NSIntegervalue; |
@end |
@implementationMyMutableInteger |
@dynamicvalue; |
-(void)setValue:(NSInteger)newX{ |
value=newX; |
} |
@end |
运行时差异
一般情况下属性在modern和legacy运行时环境下的行为是一致的(参见Objective-CRuntimeProgrammingGuide中的“Runtime
VersionsandPlatforms”)。有个关键的区别是,modern运行时支持实例变量的访问器方法自动生成而legacy运行时不支持。
要让
@synthesize在legacy运行时能够工作,你就必须提供一个跟该属性有相同名字以及类型的实例变量或者指定另外一个已经存在于
@synthesize块中的实例变量。在
modern运行时下,如果你不提供实例变量,编译器会为你自动添加一个。例如,
@interfaceMyClass:NSObject |
@propertyfloatnoDeclaredIvar; |
@end |
@implementationMyClass |
@synthesizenoDeclaredIvar; |
@end |
@synthesizenoDeclaredIvar处报错,而在modern运行时下,编译器会添加一个实例变量来代替
noDeclaredIvar.
英文原文:
DeclaredProperties
TheObjective-Cdeclaredpropertiesfeatureprovidesasimplewaytodeclareandimplementanobject’saccessormethods.
Overview
Youtypicallyaccessanobject’sproperties(inthesenseofitsattributesandrelationships)throughapairofaccessor(getter/setter)methods.Byusingaccessormethods,youadheretotheprincipleofencapsulation(see“MechanismsOfAbstraction”inObject-Oriented
ProgrammingwithObjective-C).Youcanexercisetightcontrolofthebehaviorofthegetter/setterpairandtheunderlyingstatemanagementwhileclientsoftheAPIremaininsulatedfromtheimplementationchanges.
Althoughusingaccessormethodsthereforehassignificantadvantages,writingaccessormethodsisatediousprocess.Moreover,aspectsofthepropertythatmaybeimportanttoconsumersoftheAPIareleftobscured—such
aswhethertheaccessormethodsarethread-safeorwhethernewvaluesarecopiedwhenset.
Declaredpropertiesaddresstheseissuesbyprovidingthefollowingfeatures:
Thepropertydeclarationprovidesaclear,explicitspecificationofhowtheaccessormethodsbehave.
Thecompilercansynthesizeaccessormethodsforyou,accordingtothespecificationyouprovideinthedeclaration.
Propertiesarerepresentedsyntacticallyasidentifiersandarescoped,sothecompilercandetectuseofundeclaredproperties.
PropertyDeclarationandImplementation
Therearetwopartstoadeclaredproperty,itsdeclarationanditsimplementation.
PropertyDeclaration
Apropertydeclarationbeginswiththekeyword@property.
@propertycan
appearanywhereinthemethoddeclarationlistfoundinthe
@interfaceblockofaclass.
@propertycan
alsoappearinthedeclarationofaprotocolorcategory.
@property(attributes)typename; |
@propertydirectivedeclaresaproperty.Anoptionalparenthesizedsetofattributesprovidesadditionaldetailsaboutthe
storagesemanticsandotherbehaviorsoftheproperty—see“Property
DeclarationAttributes”forpossiblevalues.LikeanyotherObjective-Ctype,eachpropertyhasatypespecificationandaname.
Listing4-1illustratesthedeclarationofasimpleproperty.
Listing4-1Declaringasimpleproperty
@interfaceMyClass:NSObject |
@propertyfloatvalue; |
@end |
@propertyfloatvalue; |
-(float)value; |
-(void)setValue:(float)newValue; |
DeclarationAttributes”).
Youcanalsoputpropertydeclarationsinclassextensions(see
Forexample,youcoulddeclarethe
valuepropertyshownpreviouslyasfollows:
@interfaceMyClass:NSObject |
@end |
@interfaceMyClass() |
@propertyfloatvalue; |
@end |
PropertyDeclarationAttributes
Youcandecorateapropertywithattributesbyusingtheform@property(attribute[,attribute2,...]).Likemethods,properties
arescopedtotheirenclosinginterfacedeclaration.Forpropertydeclarationsthatuseacomma-delimitedlistofvariablenames,thepropertyattributesapplytoallofthenamedproperties.
Ifyouusethe
@synthesizedirectivetotellthecompilertocreatetheaccessormethods(see“Property
ImplementationDirectives”),thecodeitgeneratesmatchesthespecificationgivenbythekeywords.Ifyouimplementtheaccessormethodsyourself,youshouldensurethatitmatchesthespecification(forexample,ifyouspecify
copyyou
mustmakesurethatyoudocopytheinputvalueinthesettermethod).
AccessorMethodNames
ThedefaultnamesforthegetterandsettermethodsassociatedwithapropertyarepropertyNameandsetPropertyName
:respectively—for
example,givenaproperty“foo”,theaccessorswouldbe
fooand
setFoo:.Thefollowingattributes
allowyoutospecifycustomnamesinstead.Theyarebothoptionalandcanappearwithanyotherattribute(exceptfor
readonlyinthecaseof
setter=).
getter=getterName
Specifiesthenameofthegetaccessorfortheproperty.Thegettermustreturnatypematchingtheproperty’stypeandtakenoparameters.
setter=setterName
Specifiesthenameofthesetaccessorfortheproperty.Thesettermethodmusttakeasingleparameterofatypematchingtheproperty’stypeandmustreturn
void.
Ifyouspecifythatapropertyis
readonlyandalsospecifyasetterwith
setter=,
yougetacompilerwarning.
Typicallyyoushouldspecifyaccessormethodnamesthatarekey-valuecodingcompliant(seeKey-Value
CodingProgrammingGuide)—acommonreasonforusingthe
getterdecoratoristoadheretothe
isPropertyNameconvention
forBooleanvalues.
Writability
Theseattributesspecifywhetherornotapropertyhasanassociatedsetaccessor.Theyaremutuallyexclusive.readwrite
Indicatesthatthepropertyshouldbetreatedasread/write.Thisattributeisthedefault.
Bothagetterandsettermethodarerequiredinthe
@implementationblock.Ifyouusethe
@synthesizedirective
intheimplementationblock,thegetterandsettermethodsaresynthesized.
readonly
Indicatesthatthepropertyisread-only.
Ifyouspecify
readonly,onlyagettermethodisrequiredinthe
@implementationblock.
Ifyouusethe
@synthesizedirectiveintheimplementationblock,onlythegettermethodissynthesized.Moreover,ifyouattempttoassignavalueusingthedotsyntax,you
getacompilererror.
SetterSemantics
Theseattributesspecifythesemanticsofasetaccessor.Theyaremutuallyexclusive.strong
Specifiesthatthereisastrong(owning)relationshiptothedestinationobject.
weak
Specifiesthatthereisaweak(non-owning)relationshiptothedestinationobject.
Ifthedestinationobjectisdeallocated,thepropertyvalueisautomaticallysetto
nil.
(WeakpropertiesarenotsupportedonOSXv10.6andiOS4;use
assigninstead.)
copy
Specifiesthatacopyoftheobjectshouldbeusedforassignment.
Thepreviousvalueissenta
message.release
Thecopyismadebyinvokingthe
method.copy
Thisattributeisvalidonlyforobjecttypes,whichmustimplementthe
NSCopyingprotocol.
assign
Specifiesthatthesetterusessimpleassignment.Thisattributeisthedefault.
Youusethisattributeforscalartypessuchas
NSIntegerand
CGRect.
retain
Specifiesthat
shouldretain
beinvokedontheobjectuponassignment.
Thepreviousvalueissenta
message.release
InOSXv10.6andlater,youcanusethe
__attribute__keywordtospecifythataCoreFoundationpropertyshouldbetreated
likeanObjective-Cobjectformemorymanagement:
@property(retain)__attribute__((NSObject))CFDictionaryRefmyDictionary; |
Atomicity
Youcanusethisattributetospecifythataccessormethodsarenotatomic.(Thereisnokeywordtodenoteatomic.)nonatomic
Specifiesthataccessorsarenonatomic.Bydefault,accessorsareatomic.
Propertiesareatomicbydefaultsothatsynthesizedaccessorsproviderobustaccesstopropertiesinamultithreadedenvironment—thatis,thevaluereturnedfromthegetterorsetviathesetterisalwaysfully
retrievedorsetregardlessofwhatotherthreadsareexecutingconcurrently.
Ifyouspecify
strong,
copy,or
retainand
donotspecify
nonatomic,theninareference-countedenvironment,asynthesizedgetaccessorforanobjectpropertyusesalockandretainsandautoreleasesthereturnedvalue—the
implementationwillbesimilartothefollowing:
[_internallock];//lockusinganobject-levellock |
idresult=[[valueretain]autorelease]; |
[_internalunlock]; |
returnresult; |
nonatomic,asynthesizedaccessorforanobjectpropertysimplyreturnsthevaluedirectly.
MarkupandDeprecation
PropertiessupportthefullrangeofC-styledecorators.Propertiescanbedeprecatedandsupport__attribute__stylemarkup:
@propertyCGFloatx |
***AILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4; |
@propertyCGFloaty__attribute__((...)); |
OSX),youusethe
IBOutletidentifier:
@property(nonatomic,weak)IBOutletNSButton*myButton; |
IBOutletisnot,though,aformalpartofthelistofattributes.Formoreaboutdeclaringoutletproperties,see“Nib
Files”.
PropertyImplementationDirectives
Youcanusethe@synthesizeand
@dynamicdirectives
in
@implementationblockstotriggerspecificcompileractions.Notethatneitherisrequiredforanygiven
@propertydeclaration.
ImportantIfyoudonotspecifyeither
@synthesizeor
@dynamicfor
aparticularproperty,youmustprovideagetterandsetter(orjustagetterinthecaseofa
readonlyproperty)methodimplementationforthatproperty.Ifyoudonot,the
compilergeneratesawarning.
@synthesize
Youusethe
@synthesizedirectivetotellthecompilerthatitshouldsynthesizethesetterand/orgettermethodsforaproperty
ifyoudonotsupplythemwithinthe
@implementationblock.The
@synthesizedirectivealso
synthesizesanappropriateinstancevariableifitisnototherwisedeclared.
Listing4-2Using@synthesize
@interfaceMyClass:NSObject |
@property(copy,readwrite)NSString*value; |
@end |
@implementationMyClass |
@synthesizevalue; |
@end |
property=ivartoindicatethataparticularinstancevariableshouldbeusedfortheproperty,forexample:
@synthesizefirstName,lastName,age=yearsOld; |
firstName,
lastName,
and
ageshouldbesynthesizedandthattheproperty
ageisrepresentedbytheinstancevariable
yearsOld.
Otheraspectsofthesynthesizedmethodsaredeterminedbytheoptionalattributes(see“Property
DeclarationAttributes”).
Whetherornotyouspecifythenameoftheinstancevariable,the
@synthesizedirectivecanuseaninstancevariableonly
fromthecurrentclass,notasuperclass.
Therearedifferencesinthebehaviorofaccessorsynthesisthatdependontheruntime(seealso“Runtime
Difference”):
Forthelegacyruntimes,instancevariablesmustalreadybedeclaredinthe
@interfaceblockofthecurrent
class.Ifaninstancevariableofthesamenameasthepropertyexists,andifitstypeiscompatiblewiththeproperty’stype,itisused—otherwise,yougetacompilererror.
Forthemodernruntimes(see“Runtime
VersionsandPlatforms”inObjective-C
RuntimeProgrammingGuide),instancevariablesaresynthesizedasneeded.Ifaninstancevariableofthesamenamealreadyexists,itisused.
@dynamic
Youusethe
@dynamickeywordtotellthecompilerthatyouwillfulfilltheAPIcontractimpliedbyapropertyeitherby
providingmethodimplementationsdirectlyoratruntimeusingothermechanismssuchasdynamicloadingofcodeordynamicmethodresolution.Itsuppressesthewarningsthatthecompilerwouldotherwisegenerateifitcan’tfindsuitableimplementations.You
shoulduseitonlyifyouknowthatthemethodswillbeavailableatruntime.
TheexampleshowninListing4-3illustratesusing
@dynamicwith
asubclassof
.NSManagedObject
Listing4-3Using@dynamicwithNSManagedObject
@interfaceMyClass:NSManagedObject |
@property(nonatomic,retain)NSString*value; |
@end |
@implementationMyClass |
@dynamicvalue; |
@end |
NSManagedObjectisprovidedbytheCoreDataframework.Amanagedobjectclasshasacorrespondingschemathatdefinesattributes
andrelationshipsfortheclass;atruntime,theCoreDataframeworkgeneratesaccessormethodsfortheseasnecessary.Youthereforetypicallydeclarepropertiesfortheattributesandrelationships,butyoudon’thavetoimplementtheaccessormethodsyourself
andshouldn’taskthecompilertodoso.Ifyoujustdeclaredthepropertywithoutprovidinganyimplementation,however,thecompilerwouldgenerateawarning.Using
@dynamicsuppresses
thewarning.
UsingProperties
SupportedTypes
YoucandeclareapropertyforanyObjective-Cclass,CoreFoundationdatatype,or“plainolddata”(POD)type(seeC++LanguageNote:PODTypes).ForconstraintsonusingCoreFoundationtypes,however,see“Core
Foundation.”
PropertyRedeclaration
Youcanredeclareapropertyinasubclass,but(withtheexceptionofreadonlyversus
readwrite)
youmustrepeatitsattributesinwholeinthesubclasses.Thesameholdstrueforapropertydeclaredinacategoryorprotocol—whilethepropertymayberedeclaredinacategoryorprotocol,the
property’sattributesmustberepeatedinwhole.
Ifyoudeclareapropertyinoneclassas
readonly,youcanredeclareitas
readwritein
aclassextension(see
inaprotocol,orinasubclass(see“Subclassing
withProperties”).Inthecaseofaclassextensionredeclaration,thefactthatthepropertywasredeclaredpriortoany
@synthesizestatementcausesthesetter
tobesynthesized.Theabilitytoredeclarearead-onlypropertyasread/writeenablestwocommonimplementationpatterns:amutablesubclassofanimmutableclass(
NSString,
NSArray,
and
NSDictionaryareallexamples)andapropertythathasapublicAPIthatis
readonlybut
aprivate
readwriteimplementationinternaltotheclass.Thefollowingexampleshowsusingaclassextensiontoprovideapropertythatisdeclaredasread-onlyinthepublic
headerbutisredeclaredprivatelyasread/write.
//publicheaderfile |
@interfaceMyObject:NSObject |
@property(readonly,copy)NSString*language; |
@end |
//privateimplementationfile |
@interfaceMyObject() |
@property(readwrite,copy)NSString*language; |
@end |
@implementationMyObject |
@synthesizelanguage; |
@end |
CoreFoundation
Asnotedin“PropertyDeclarationAttributes,”priortoMacOSXv10.6youcannotspecifythe
retainattributefornon-objecttypes.If,therefore,youdeclareapropertywhosetypeis
aCFTypeandsynthesizetheaccessorsasillustratedinthefollowingexample:
@interfaceMyClass:NSObject |
@property(readwrite)CGImageRefmyImage; |
@end |
@implementationMyClass |
@synthesizemyImage; |
@end |
istypicallyincorrectforCoreFoundationobjects;youshouldnotsynthesizethemethodsbutratherimplementthemyourself.
SubclassingwithProperties
Youcanoverrideareadonlypropertytomakeitwritable.Forexample,youcoulddefineaclass
MyIntegerwith
a
readonlyproperty,
value:
@interfaceMyInteger:NSObject |
@property(readonly)NSIntegervalue; |
@end |
@implementationMyInteger |
@synthesizevalue; |
@end |
MyMutableInteger,whichredefinesthepropertytomakeitwritable:
@interfaceMyMutableInteger:MyInteger |
@property(readwrite)NSIntegervalue; |
@end |
@implementationMyMutableInteger |
@dynamicvalue; |
-(void)setValue:(NSInteger)newX{ |
value=newX; |
} |
@end |
RuntimeDifference
Ingeneralthebehaviorofpropertiesisidenticalonbothmodernandlegacyruntimes(see“RuntimeVersionsandPlatforms”inObjective-C
RuntimeProgrammingGuide).Thereisonekeydifference:themodernruntimesupportsinstancevariablesynthesiswhereasthelegacyruntimedoesnot.
For
@synthesizetoworkinthelegacyruntime,youmusteitherprovideaninstancevariablewiththesamenameandcompatible
typeofthepropertyorspecifyanotherexistinginstancevariableinthe
@synthesizestatement.Withthemodernruntime,ifyoudonotprovideaninstancevariable,thecompiler
addsoneforyou.Forexample,giventhefollowingclassdeclarationandimplementation:
@interfaceMyClass:NSObject |
@propertyfloatnoDeclaredIvar; |
@end |
@implementationMyClass |
@synthesizenoDeclaredIvar; |
@end |
@synthesizenoDeclaredIvar;whereasthecompilerforthemodern
runtimewouldaddaninstancevariabletorepresent
noDeclaredIvar.
[/b]
相关文章推荐
- Objective-C 编程语言官网文档(五)-属性的声明
- Objective-C 编程语言官网文档(五)-属性的声明
- Objective-C 编程语言官网文档(十二)-线程
- Objective-C 编程语言官网文档(十三 终结篇)-词汇表
- Objective-C 编程语言官网文档(十)-选择器
- Objective-C 编程语言官网文档(十三 终结篇)-词汇表
- Objective-C 编程语言官网文档(六)-类别以及扩展
- Objective-C 编程语言官网文档(十)-选择器
- Objective-C 编程语言官网文档(一)-简介
- Objective-C 编程语言官网文档(四)-协议
- Objective-C 编程语言官网文档(一)-简介
- Objective-C 编程语言官网文档(九)-静态行为
- Objective-C 编程语言官网文档(九)-静态行为
- Objective-C 编程语言官网文档(十一)-异常的处理
- Objective-C 编程语言官网文档(七)-关联引用
- Objective-C 编程语言官网文档(十一)-异常的处理
- Objective-C 编程语言官网文档(二)-对象,类以及消息
- Objective-C 编程语言官网文档(三)-如何定义类
- Objective-C 编程语言(5)属性----属性的声明与实现
- Objective-C 编程语言官网文档(三)-如何定义类