Поиск…


Синтаксис

  • Идентификатор типа @property ( optional_attributes, ... );
  • @synthesize identifier = optional_backing_ivar ;
  • @dynamic identifier ;

параметры

атрибут Описание
atomic Неявные. Включает синхронизацию в синтезированных методах доступа.
nonatomic Отключает синхронизацию в синтезированных методах доступа.
readwrite Неявные. Синтезирует геттер, сеттер и поддержку ivar.
readonly Синтезирует только метод геттера и поддержку ivar, которые могут быть назначены напрямую.
getter= name Указывает имя метода getter, неявное имя propertyName .
setter= name Задает имя метода setter, implicity is setPropertyName: Колон : должен быть частью имени.
strong Неявно для объектов в ARC . Поддерживающий ivar синтезируется с использованием __strong , что предотвращает освобождение ссылочного объекта.
retain Синоним strong .
copy То же, что и strong , но синтезированный сеттер также вызывает -copy для нового значения.
unsafe_unretained Неявно, за исключением объектов в ARC. Подкрепляющий ivar синтезируется с использованием __unsafe_unretained , который (для obejcts) приводит к зависанию указателя, когда ссылочный объект освобождается.
assign Синоним для unsafe_unretained . Подходит для не-объектов.
weak Обратный ivar синтезируется с использованием __weak , поэтому значение будет __weak после того, как ссылочный объект будет освобожден.
class Атрибуты доступа к ресурсам синтезируются как методы класса, а не методы экземпляра. Синтезировано хранилище резервных копий.
nullable Свойство принимает значения nil . В основном используется для моста Swift.
nonnull Свойство не принимает значения nil . В основном используется для моста Swift.
null_resettable Свойство принимает значения nil в setter, но никогда не возвращает значения nil из getter. Ваша пользовательская реализация getter или setter должна обеспечить такое поведение. В основном используется для моста Swift.
null_unspecified Неявные. Свойство не указывает обработку значений nil . В основном используется для моста Swift.

Что такое свойства?

Вот примерный класс, который имеет пару переменных экземпляра без использования свойств:

@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, Apple представила свойства, которые автоматически генерируют какой-либо или весь шаблонный код.

Ниже приведен класс, переписанный со свойствами:

@interface TestClass

@property NSString *someString;
@property int someInt;

@end


@implementation testClass

@end

Свойство - это переменная экземпляра, объединенная с автогенераторами и сеттерами. Для свойства, называемого 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

Доступ к свойствам можно получить, вызвав геттеры и сеттеры:

[testObject setSomeString:@"Foo"];
NSLog(@"someInt is %d", [testObject someInt]);

Их также можно получить с помощью точечной нотации:

testObject.someString = @"Foo";
NSLog(@"someInt is %d", testObject.someInt);

Пользовательские геттеры и сеттеры

По умолчанию свойства getters и seters могут быть переопределены:

@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;
}

Вы также можете создать свойство, которое вычисляет его значение в getter:

@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 ), метод сеттер setProperty: называется. Этот сеттер, даже если он предоставлен @synthesize , может быть переопределен, как в этом случае для numberOfSides и sideWidth . Однако, если вы установите свойство ivar напрямую (через property если объект является self или object->property ), он не вызывает getter или setter, позволяя вам делать такие вещи, как несколько наборов свойств, которые вызывают только одно обновление или побочные побочные эффекты, вызванные установщиком.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow