В чем смысл @property и @synthesize?

Я не смог понять это, и нет веб-сайтов, которые объясняют это достаточно ясно... каковы цели @property и @synthesize?

Заранее спасибо!


person esqew    schedule 03.07.2010    source источник


Ответы (4)


Руководство по программированию среды выполнения Objective-C: Заявленные свойства

@property объявляет методы получения и установки для общедоступного свойства, которое вы хотите реализовать. Например, это объявление свойства:

@property float value;

эквивалентно:

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

@synthesize обеспечивает реализацию по умолчанию для этих двух методов доступа.

Обновление. Вышеизложенное объясняет, что делают эти два элемента. Это не объясняет, какова их цель. :-)

  • @property добавляет член в общедоступный интерфейс, который действует как переменная данных для ваших клиентов класса, но читается и записывается с использованием методов. Это дает вам лучший контроль над данными, которыми обмениваются клиент и ваш код, например, вы можете выполнять расширенную проверку значений, заданных вашему коду.
  • @synthesize позволяет вам не писать явно код, который будет вызываться клиентом, а фактически обрабатывать свойство как переменную данных самостоятельно.
person Franci Penov    schedule 03.07.2010
comment
Я не знаю, полностью ли я это понял... почему бы просто не сделать: value = 0.0; - person esqew; 03.07.2010
comment
@seanny94 См. этот вопрос: stackoverflow.com/questions/1568091 /зачем использовать геттеры и сеттеры - person Tobias Cohen; 03.07.2010
comment
Ответ частично неверный. @property объявляет геттер (и/или сеттер). Он также объявляет некоторые аспекты поведения геттера/сеттера (например, сохранение, копирование, назначение, неатомарность). @synthesize обеспечивает реализацию по умолчанию средств доступа на основе @property. Ни один из них не позволяет вам обращаться со свойством как с членом данных больше, чем запись объявлений и определений стандартных методов. - person JeremyP; 03.07.2010
comment
С точки зрения клиентского кода, обращающегося к классу, свойство действует как член данных и имеет семантику члена данных. И да, @property действительно объявляет некоторые аспекты поведения методов доступа, которые, как мне кажется, можно смело опустить, поскольку они описаны в полной документации, на которую я ссылался. - person Franci Penov; 03.07.2010
comment
@Франциск. Нет. Свойства не ведут себя как элементы данных. Вы не можете получить доступ к свойствам с помощью оператора -> извне класса, и вы не можете опустить self. / self-> внутри класса. Кроме того, нет никакой функциональной разницы между свойством, объявленным с помощью @property, и свойством, объявленным путем полного написания методов доступа. - person JeremyP; 04.07.2010
comment
Конечно, если вы хотите быть педантичным, существуют определенные синтаксические различия между свойством и элементом данных. В конце концов, это две разные языковые конструкции (и тот факт, что Objective-C плохо спроектирован :-)). Тем не менее, семантика свойства с точки зрения клиентского кода такая же, как и член данных - это представление значения, а не представление действия. - person Franci Penov; 04.07.2010
comment
Ссылка мертва (и комментарии должны быть более 15 символов) - person Rog; 30.07.2015
comment
Обновлено более актуальной ссылкой. (Надеюсь, Apple когда-нибудь изучит концепцию постоянных ссылок.) - person Franci Penov; 31.07.2015

Символ «@» интерпретируется компилятором как директива. Это одно из «дополнений» Objective-C к языку C. Когда вы объявляете @property, а затем @synthesize, вы даете компилятору указание создать для вас инструкции и соответствующие символы для геттеров и сеттеров. Помните, что в языке C оператор "=" означает "назначить". Большую часть времени в объектно-ориентированном контексте, предоставляемом расширениями Objective-C, мы работаем с указателями (также известными как ссылки) на структуры данных isa (классы в Objective-C).

До Objective-C 2.0 все методы получения и установки должны были быть закодированы разработчиком для каждого атрибута, что в большинстве случаев представляло собой код копирования/вставки. Чтобы быть полностью совместимым с KVC/KVO, требуется много очень утомительного кода... операторы willAccessValueForKey, didUpdateValueForKey и т. д., которые новый компилятор автоматически добавляет за вас, когда вы используете синтаксис @property/@synthesize. Это огромный прирост производительности для разработчиков. Дополнения к синтаксису с точками в языке вызывают немного больше споров в сообществе, поскольку это скрывает магию, которую компилятор делает от вашего имени, чтобы интерпретировать оператор object.property = anotherObject.property; как [object setProperty:[anotherObject property]];

Из документации Apple, упомянутой в других ответах

Атрибуты объявления свойства

Вы можете украсить свойство атрибутами, используя форму @property(attribute [, attribute2, ...]). Как и методы, свойства ограничены включающим их объявлением интерфейса. Для объявлений свойств, в которых используется список имен переменных, разделенных запятыми, атрибуты свойств применяются ко всем именованным свойствам.

Если вы используете директиву @synthesize, чтобы указать компилятору создать метод(ы) доступа, сгенерированный им код соответствует спецификации, заданной ключевыми словами. Если вы реализуете методы доступа самостоятельно, вы должны убедиться, что они соответствуют спецификации (например, если вы укажете копию, вы должны убедиться, что вы копируете входное значение в методе установки).

person falconcreek    schedule 03.07.2010

Я надеюсь, что это поможет вам.

@property и @synthesize используются для доступа к объекту или переменной в другой класс.

Вот небольшой пример: Это первый класс.

#import <UIKit/UIKit.h>
#import "ClassB.h"
@interface ViewController : UIViewController
@property(nonatomic, retain) NSString *FirstName;
@property(nonatomic, retain) NSString *LastName;


#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize FirstName, LastName;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.FirstName = @"Ashvin";
    self.LastName  = @"Ajadiya";
    ClassB *ClassBOb = [[ClassB alloc] init];
    ClassBOb.ViewCntrlrOb = self;
    [ClassBOb CallMe];
}
@end

А это еще один класс:

#import <UIKit/UIKit.h>
@class ViewController;
@interface ClassB : UIViewController
@property(nonatomic, retain) ViewController *ViewCntrlrOb;
-(void) CallMe;
@end

#import "ClassB.h"
#import "ViewController.h"
@interface ClassB ()
@end
@implementation ClassB
@synthesize ViewCntrlrOb;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

-(void) CallMe
{
   NSLog(@"FirstName = %@",ViewCntrlrOb.FirstName);
   NSLog(@"LastName = %@",ViewCntrlrOb.LastName); 
}

Таким образом, вы можете получить доступ к имени и фамилии в ClassB.

И они печатают:

25.05.2012 14:38:10.766 МойПример[8751:c07] Имя = Ашвин 25.05.2012 14:38:10.768 МойПример[8751:c07] Фамилия = Аджадия

person Ashvin A    schedule 25.05.2012

Просто быстрый пример того, почему вы можете не захотеть делать просто «переменная = 0»:

Скажем, у вас есть это свойство:

@property (nonatomic, retain) id <MyDelegate> theDelegate;

Всякий раз, когда вы заменяете этот делегат новым, ваши синтезированные сеттеры и геттеры будут обрабатывать выпуск/сохранение для вас каждый раз, когда вы устанавливаете его следующим образом:

self.theDelegate = newObject;

На самом деле произошло следующее:

[self setTheDelegate:newObject];

- (void)setTheDelegate:(id <MyDelegate>)anObject {
    [theDelegate release];
    theDelegate = [anObject retain];
}

(это упрощенно конечно)

Вы можете делать очень мощные вещи в своих собственных сеттерах и геттерах, синтезировать те, которые происходят снова и снова, например, сохраняемые свойства и т. д. При компиляции он смотрит на ваше @property и соответствующим образом строит методы.

person v01d    schedule 03.07.2010