Objective-C Language
プロパティ
サーチ…
構文
- @property( optional_attributes、... ) タイプ 識別子 。
- @シンセシスの識別子 = optional_backing_ivar ;
- @動的識別子 。
パラメーター
属性 | 説明 |
---|---|
atomic | 暗黙。合成されたアクセサメソッドでの同期を有効にします。 |
nonatomic | 合成されたアクセサメソッドの同期を無効にします。 |
readwrite | 暗黙。 getter、setter、backing ivarを合成します。 |
readonly | getterメソッドとバッキングivarのみを合成します。これは直接割り当てることができます。 |
getter= 名前 | getterメソッドの名前を指定しpropertyName 。暗黙的にはpropertyName です。 |
setter= 名前 | setterメソッドの名前を指定しますsetPropertyName: はsetPropertyName: 。結腸: 名前の一部でなければならない。 |
strong | ARCの下にあるオブジェクトに暗黙のうちに 。バッキングivarは__strong を使用して合成され、参照オブジェクトの割り当て解除を防ぎます。 |
retain | strong 同義語。 |
copy | 同じstrong が、合成されたセッターも呼び出す-copy 新しい値に。 |
unsafe_unretained | 暗黙のうちに、ARCの下のオブジェクトを除きます。バッキングivarは、 __unsafe_unretained unsafe_unretainedを__unsafe_unretained 合成されます。これは、(obejctsの場合)参照されたオブジェクトの割り当てが解除されると、ぶら下がりポインタになります。 |
assign | unsafe_unretained 同義語です。非オブジェクト型に適しています。 |
weak | バッキング__weak を使用して合成されるため、参照されたオブジェクトの割り当てが解除されると値は無効になります。 |
class | プロパティアクセサは、インスタンスメソッドの代わりにクラスメソッドとして合成されます。バッキングストレージは合成されません。 |
nullable | このプロパティはnil 値を受け入れます。主にスウィフトブリッジングに使用されます。 |
nonnull | このプロパティはnil 値を受け入れません。主にスウィフトブリッジングに使用されます。 |
null_resettable | このプロパティはsetterでnil 値を受け取りますが、getterからnil 値を返すことはありません。 getterまたはsetterのカスタム実装では、この動作を保証する必要があります。主にスウィフトブリッジングに使用されます。 |
null_unspecified | 暗黙。このプロパティは、 nil 値の処理を指定しません。主にスウィフトブリッジングに使用されます。 |
プロパティとは何ですか?
プロパティを使用せずに、いくつかのインスタンス変数を持つクラスの例を次に示します。
@interface TestClass : NSObject {
NSString *_someString;
int _someInt;
}
-(NSString *)someString;
-(void)setSomeString:(NSString *)newString;
-(int)someInt;
-(void)setSomeInt:(NSString *)newInt;
@end
@implementation TestClass
-(NSString *)someString {
return _someString;
}
-(void)setSomeString:(NSString *)newString {
_someString = newString;
}
-(int)someInt {
return _someInt;
}
-(void)setSomeInt:(int)newInt {
_someInt = newInt;
}
@end
これは単純なインスタンス変数を作成するための非常に多くの定型コードです。インスタンス変数を作成し、インスタンス変数を設定または返す以外は何もしないアクセサメソッドを作成する必要があります。したがって、Objective-C 2.0では、ボイラープレートコードの一部または全部を自動的に生成するプロパティが導入されました。
上記のクラスはプロパティで書き換えられます:
@interface TestClass
@property NSString *someString;
@property int someInt;
@end
@implementation testClass
@end
プロパティは、自動生成されたgetterおよびsetterと組み合わされたインスタンス変数です。 someString
というプロパティの場合、getterとsetterはそれぞれsomeString
とsetSomeString:
と呼ばれます。インスタンス変数の名前は、デフォルトでは、アンダースコアで始まるプロパティ(の名前であるので、用インスタンス変数someString
呼ばれ_someString
が、これはで無効にすることができます@synthesize
中にディレクティブ@implementation
セクション:
@synthesize someString=foo; //names the instance variable "foo"
@synthesize someString; //names it "someString"
@synthesize someString=_someString; //names it "_someString"; the default if
//there is no @synthesize directive
プロパティはgettersとsetterを呼び出すことでアクセスできます:
[testObject setSomeString:@"Foo"];
NSLog(@"someInt is %d", [testObject someInt]);
ドット表記を使用してアクセスすることもできます。
testObject.someString = @"Foo";
NSLog(@"someInt is %d", testObject.someInt);
カスタムゲッターとセッター
デフォルトのプロパティgettersおよびsetterはオーバーライドできます。
@interface TestClass
@property NSString *someString;
@end
@implementation TestClass
// override the setter to print a message
- (void)setSomeString:(NSString *)newString {
NSLog(@"Setting someString to %@", newString);
// Make sure to access the ivar (default is the property name with a _
// at the beginning) because calling self.someString would call the same
// method again leading to an infinite recursion
_someString = newString;
}
- (void)doSomething {
// The next line will call the setSomeString: method
self.someString = @"Test";
}
@end
これは、例えば、まだ初期化されていない場合にゲッターをオーバーライドして初期値を設定することによって、遅延初期化を行うのに便利です:
- (NSString *)someString {
if (_someString == nil) {
_someString = [self getInitialValueForSomeString];
}
return _someString;
}
ゲッターでその値を計算するプロパティを作成することもできます。
@interface Circle : NSObject
@property CGPoint origin;
@property CGFloat radius;
@property (readonly) CGFloat area;
@end
@implementation Circle
- (CGFloat)area {
return M_PI * pow(self.radius, 2);
}
@end
更新を引き起こすプロパティ
このオブジェクトは、 Shape
財産持っているimage
に依存numberOfSides
とsideWidth
。どちらか一方が設定されている場合は、 image
を再計算する必要があります。しかし、再計算はおそらく長く、両方のプロパティが設定されている場合は一度だけ実行する必要があるため、 Shape
は両方のプロパティを設定して一度だけ再計算する方法を提供します。これは、プロパティivarsを直接設定することによって行われます。
Shape.h
@interface Shape {
NSUInteger numberOfSides;
CGFloat sideWidth;
UIImage * image;
}
// Initializer that takes initial values for the properties.
- (instancetype)initWithNumberOfSides:(NSUInteger)numberOfSides withWidth:(CGFloat)width;
// Method that allows to set both properties in once call.
// This is useful if setting these properties has expensive side-effects.
// Using a method to set both values at once allows you to have the side-
// effect executed only once.
- (void)setNumberOfSides:(NSUInteger)numberOfSides andWidth:(CGFloat)width;
// Properties using default attributes.
@property NSUInteger numberOfSides;
@property CGFloat sideWidth;
// Property using explicit attributes.
@property(strong, readonly) UIImage * image;
@end
Shape.m
@implementation AnObject
// The variable name of a property that is auto-generated by the compiler
// defaults to being the property name prefixed with an underscore, for
// example "_propertyName". You can change this default variable name using
// the following statement:
// @synthesize propertyName = customVariableName;
- (id)initWithNumberOfSides:(NSUInteger)numberOfSides withWidth:(CGFloat)width {
if ((self = [self init])) {
[self setNumberOfSides:numberOfSides andWidth:width];
}
return self;
}
- (void)setNumberOfSides:(NSUInteger)numberOfSides {
_numberOfSides = numberOfSides;
[self updateImage];
}
- (void)setSideWidth:(CGFloat)sideWidth {
_sideWidth = sideWidth;
[self updateImage];
}
- (void)setNumberOfSides:(NSUInteger)numberOfSides andWidth:(CGFloat)sideWidth {
_numberOfSides = numberOfSides;
_sideWidth = sideWidth;
[self updateImage];
}
// Method that does some post-processing once either of the properties has
// been updated.
- (void)updateImage {
...
}
@end
プロパティが( object.property = value
を使用して)割り当てられると、setterメソッドsetProperty:
が呼び出されます。このセッターは、が提供する場合でも@synthesize
それがために、この場合にあるように、オーバーライドすることができnumberOfSides
とsideWidth
。しかし、プロパティのivarを直接(オブジェクトがselfまたはobject->property
property
場合はproperty
を介して)設定すると、getterまたはsetterが呼び出されず、1つの更新を呼び出す複数のプロパティセットやセッターによって引き起こされるバイパス副作用。