Есть ли разница между "переменной экземпляра" и "свойством" в Objective-c?

Есть ли разница между "переменной экземпляра" и "свойством" в Objective-c?

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

Ответ 1

Свойство является более абстрактным понятием. Переменная экземпляра - это буквально только слот для хранения данных, такой как слот в структуре. Обычно другие объекты никогда не должны обращаться к ним напрямую. С другой стороны, свойство является атрибутом вашего объекта, к которому можно получить доступ (он звучит неопределенно и он должен). Обычно свойство возвращает или задает переменную экземпляра, но может использовать данные из нескольких или вообще ничего. Например:

@interface Person : NSObject {
    NSString *name;
}

    @property(copy) NSString *name;
    @property(copy) NSString *firstName;
    @property(copy) NSString *lastName;
@end

@implementation Person
    @synthesize name;

    - (NSString *)firstName {
        [[name componentsSeparatedByString:@" "] objectAtIndex:0];
    }
    - (NSString *)lastName {
        [[name componentsSeparatedByString:@" "] lastObject];
    }
    - (NSString *)setFirstName:(NSString *)newName {
        NSArray *nameArray = [name componentsSeparatedByString:@" "];
        NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
        self.name = [newNameArray componentsJoinedByString:@" "];
    }
    - (NSString *)setLastName:(NSString *)newName {
        NSArray *nameArray = [name componentsSeparatedByString:@" "];
        NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
        self.name = [newNameArray componentsJoinedByString:@" "];
    }
@end

(Примечание: приведенный выше код ошибочен в том смысле, что он предполагает, что имя уже существует и имеет как минимум два компонента (например, "Билл Гейтс", а не только "Гейтс" ). Я чувствовал, что фиксация этих предположений сделает фактическую точку кода менее ясны, поэтому я просто указываю на это, поэтому никто невинно повторяет эти ошибки.)

Ответ 2

Свойство - это дружественный способ реализации getter/setter для некоторого значения, с дополнительными полезными функциями и синтаксисом. Свойству может быть присвоена переменная экземпляра, но вы также можете определить геттер/сеттер, чтобы сделать что-то более динамичное, например. вы можете определить свойство lowerCase для строки, которая динамически создает результат, а не возвращает значение некоторой переменной-члена.

Вот пример:

// === In your .h ===

@interface MyObject {
    NSString *propertyName;

}

// ...

@property (nonatomic, retain) NSString *propertyName;

// === In your .m @implementation ===

@synthesize propertyName /* = otherVarName */;

Строка @property определяет свойство propertyName типа NSString *. Это можно получить/установить, используя следующий синтаксис:

myObject.propertyName = @"Hello World!";
NSLog("Value: %@", myObject.propertyName);

Когда вы назначаете или читаете из myObject.propertyName, вы действительно вызываете методы setter/getter на объекте.

Строка @synthesize сообщает компилятору генерировать эти getter/seters для вас, используя переменную-член с тем же именем свойства, чтобы сохранить значение (или otherVarName, если вы используете синтаксис в комментариях).

Наряду с @synthesize вы все равно можете переопределить один из элементов getter/setters, указав свой собственный. Соглашение об именах для этих методов setPropertyName: для сеттера и propertyName (или getPropertyName, а не стандартное) для получателя. Другой будет создан для вас.

В вашей строке @property вы можете определить несколько атрибутов в parens для свойства, которое может автоматизировать такие функции, как управление потоками и управление памятью. По умолчанию свойство атомарное означает, что компилятор будет обертывать @synthesiz ed get/set calls с соответствующими блокировками для предотвращения проблем concurrency. Вы можете указать атрибут nonatomic, чтобы отключить его (например, на iPhone, который вы хотите по умолчанию для большинства свойств, nonatomic).

Существует 3 значения атрибута, которые управляют управлением памятью для любых установщиков @synthesized. Первая - это retain, которая автоматически отправит release к старым значениям свойства и retain к новым значениям. Это очень полезно.

Второй copy, который сделает копию любых значений, переданных, а не сохраняя их. Рекомендуется использовать copy для NSString, потому что вызывающий может передать NSMutableString и изменить его из-под вас. copy создаст новую копию ввода, к которой у вас есть доступ.

Третий assign, который присваивает прямой указатель без вызова сохранения/освобождения на старом или новом объекте.

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

Ответ 3

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

Ответ 4

По умолчанию свойство readwrite будет поддерживаться переменной экземпляра, которая будет автоматически синтезироваться компилятором.

Переменная экземпляра - это переменная, которая существует и сохраняет свое значение для жизни объекта. Память, используемая для переменных экземпляра, выделяется, когда объект сначала создается (через alloc) и освобождается, когда объект освобождается.

Если вы не указали иначе, переменная синтезированного экземпляра имеет то же имя, что и свойство, но с префиксом подчеркивания. Например, для свойства, называемого firstName, синтезированная переменная экземпляра будет называться _firstName.

Ответ 5

Раньше люди публично использовали свойства и ivars для частного использования, но несколько лет назад вы также можете определить свойства в @implementation, чтобы использовать их конфиденциально. Но по-прежнему я использую ivars, так как набирается меньше букв, и он работает быстрее в соответствии с этой статьей. Это имеет смысл, поскольку свойства являются средними, чтобы быть "тяжелыми": к ним следует обращаться либо из сгенерированных геттеров/сеттеров, либо из написанных вручную.

Однако, в последних кодах от Apple, ivars больше не используются. Я думаю, потому что это больше похоже на objc, а не на C/C++, плюс его проще использовать свойства с assign, nullable и т.д.