Что именно делает @synthesize?

Я видел следующий фрагмент кода:

//example.h
MKMapView * mapView1;
@property (nonatomic, retain) MKMapView * mapView;

//example.m
@synthesize mapView = mapView1

Вопрос: Какая связь между mapView и mapView1? Создает ли метод set и get для mapView1?

Спасибо!

Ответ 1

В вашем примере mapView1 - это переменная экземпляра (ivar), часть памяти, принадлежащая экземпляру класса, определенного в example.h и example.m. mapView - это имя свойства. Свойства - это атрибуты объекта, который можно прочитать или установить с помощью точечной нотации: myObject.mapView. Свойство не обязательно должно основываться на ivar, но большинство свойств. Объявление @property просто сообщает миру, что существует свойство, называемое mapView.

@synthesize mapView = mapView1;

Эта строка сообщает компилятору создать сеттер и getter для mapView и что они должны использовать ivar, называемый mapView1. Без части = mapView1 компилятор предположил бы, что свойство и ivar имеют одинаковое имя. (В этом случае это приведет к ошибке компилятора, поскольку нет ivar под названием mapView.)

Результат этого оператора @synthesize аналогичен тому, как вы добавили этот код самостоятельно:

-(MKMapView *)mapView
{
   return mapView1;
}

-(void)setMapView:(MKMapView *)newMapView
{
  if (newMapView != mapView1)
  {
    [mapView1 release];
    mapView1 = [newMapView retain];
  }
}

Если вы добавите этот код в класс самостоятельно, вы можете заменить оператор @synthesize на

@dynamic mapView;

Главное - иметь очень четкое концептуальное различие между иварами и свойствами. Они действительно две совершенно разные концепции.

Ответ 2

@synthesize создает геттер и сеттер для переменной.

Это позволяет вам указать некоторые атрибуты для ваших переменных и когда вы @synthesize это свойство переменной, сгенерирующей getter и setter для переменной.

Имя свойства может быть таким же, как имя переменной. Иногда люди хотят, чтобы они были разными, чтобы использовать их в init или dealloc или когда параметр передается с тем же именем переменной.

Ответ 3

Из документация:

Вы используете ключевое слово @synthesize, чтобы сообщить компилятору, что он должен синтезировать методы setter и/или getter для свойства, если вы не предоставите их в блоке @implementation.

Ответ 4

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

Даже с более новой версией компилятора иногда имеет значение, если вы опускаете @synthesize propertyName или не.

В случае, если вы объявляете переменную экземпляра без подчеркивания при ее синтезе, например:

Заголовок:

@interface SomeClass : NSObject {
   int someInt;
}
@property int someInt;
@end

Реализация:

@implementation SomeClass
@synthesize someInt;
@end

self.someInt получит доступ к той же переменной, что и someInt. Не использовать лидирующий знак подчеркивания для ivars не следует соглашениям об именах, но я просто пришел в ситуацию, когда мне пришлось читать и модифицировать такой код.

Но если теперь вы думаете: "Эй, @synthesize больше не важна, поскольку мы используем новый компилятор", вы ошибаетесь! Затем ваш класс будет иметь два ivars, а именно someInt плюс автогенерированная переменная _someInt. Таким образом, self.someInt и someInt больше не будут обращаться к тем же переменным. Если вы не ожидаете такого поведения, как я, это может вызвать у вас головную боль, чтобы узнать.

Ответ 5

В соответствии с документацией на Apple @Synthesize используется только для переименования переменных экземпляра. Например

@property NSString *str;

@synthesize str = str2; 

Теперь в классе вы не можете использовать _str, поскольку указанная выше строка переименовывает переменную экземпляра в str2

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

Ответ 6

Смотрите яблочные документы

В основном синтез создает методы setMapView и mapView, которые устанавливают и получают mapView1

Ответ 7

Он создает getter и setter для вашего объекта. Вы можете получить доступ к чему-то вроде этого:

MKMapView* m = object.mapView;

или

object.mapView = someMapViewObject

mapView1 - это имя ivar в классе, mapView - это имя метода (ов) getter/setter.