Відповіді:
властивості мають конкретне значення в Objective-C, але я думаю, ви маєте на увазі щось еквівалентне статичній змінній? Наприклад, лише один екземпляр для всіх типів Foo?
Для оголошення функцій класу в Objective-C ви використовуєте префікс + замість - щоб ваша реалізація виглядала приблизно так:
// Foo.h
@interface Foo {
}
+ (NSDictionary *)dictionary;
// Foo.m
+ (NSDictionary *)dictionary {
static NSDictionary *fooDict = nil;
if (fooDict == nil) {
// create dict
}
return fooDict;
}
.
Синтаксис -accessor не прив'язаний до властивостей в Objective-C, це просто скомпільований ярлик для будь-якого методу , який повертає то , що без прийняття будь - яких Арга. У цьому випадку я вважаю за краще - я особисто віддаю перевагу .
синтаксису для будь-якого використання, коли клієнтський код має намір отримати щось, а не виконувати дію (навіть якщо код реалізації може щось створити один раз або виконувати дії з побічними ефектами) . .
Синтаксис великого використання також призводить до більш читабельного коду: наявність […]
s означає, що щось істотне робиться, коли .
замість них використовується синтаксис.
Я використовую це рішення:
@interface Model
+ (int) value;
+ (void) setValue:(int)val;
@end
@implementation Model
static int value;
+ (int) value
{ @synchronized(self) { return value; } }
+ (void) setValue:(int)val
{ @synchronized(self) { value = val; } }
@end
І я вважав це надзвичайно корисним як заміна шаблону Singleton.
Щоб скористатись цим, просто отримайте доступ до своїх даних за допомогою крапки:
Model.value = 1;
NSLog(@"%d = value", Model.value);
self
означає метод класу?
self
- це об'єкт, який отримав повідомлення . А оскільки заняття також є об’єктами , то в цьому випадку self
означаєModel
@synchronized
?
Як видно з WWDC 2016 / XCode 8 ( що нового в сесії LLVM @ 5: 05). Властивості класу можна оголосити наступним чином
@interface MyType : NSObject
@property (class) NSString *someString;
@end
NSLog(@"format string %@", MyType.someString);
Зауважте, що властивості класу ніколи не синтезуються
@implementation
static NSString * _someString;
+ (NSString *)someString { return _someString; }
+ (void)setSomeString:(NSString *)newString { _someString = newString; }
@end
static
змінна ( ) все одно повинна бути оголошена та використана, а методи реалізовані явно, як і раніше. Синтаксис точок вже працював і раніше. Загалом, це звучить як більша справа, ніж насправді.
Якщо ви шукаєте еквівалент рівня класу @property
, тоді відповідь "такого не існує". Але пам’ятайте @property
, у будь-якому випадку це лише синтаксичний цукор; він просто створює відповідно названі об'єктні методи.
Ви хочете створити методи класу, які мають доступ до статичних змінних, які, як говорили інші, мають лише дещо інший синтаксис.
UIDevice.currentDevice.identifierForVendor
працює для мене.
Ось безпечний спосіб зробити це:
// Foo.h
@interface Foo {
}
+(NSDictionary*) dictionary;
// Foo.m
+(NSDictionary*) dictionary
{
static NSDictionary* fooDict = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
// create dict
});
return fooDict;
}
Ці редагування гарантують, що fooDict створюється лише один раз.
З документації Apple : "dispatch_once - виконує об'єкт блоку один раз і лише один раз протягом життя програми."
Initializer element is not a compile-time constant
.
Станом на Xcode 8 Objective-C тепер підтримує властивості класу:
@interface MyClass : NSObject
@property (class, nonatomic, assign, readonly) NSUUID* identifier;
@end
Оскільки властивості класу ніколи не синтезуються, вам потрібно написати власну реалізацію.
@implementation MyClass
static NSUUID*_identifier = nil;
+ (NSUUID *)identifier {
if (_identifier == nil) {
_identifier = [[NSUUID alloc] init];
}
return _identifier;
}
@end
Ви отримуєте доступ до властивостей класу, використовуючи звичайний синтаксис крапок у назві класу:
MyClass.identifier;
Властивості мають значення лише в об'єктах, а не в класах.
Якщо вам потрібно зберігати щось для всіх об'єктів класу, вам доведеться використовувати глобальну змінну. Ви можете приховати його, оголосивши його static
у файлі реалізації.
Ви також можете розглянути можливість використання конкретних відносин між вашими об'єктами: ви присвоюєте роль майстра певному об'єкту вашого класу та зв'язуєте інші об'єкти з цим майстром. Майстер буде мати словник як просту властивість. Я думаю про дерево, подібне до того, яке використовується для ієрархії подання в додатках какао.
Інший варіант - створити об’єкт виділеного класу, який складається як зі словника вашого класу, так і з набору всіх об'єктів, пов'язаних із цим словником. Це щось на кшталт NSAutoreleasePool
какао.
Починаючи з Xcode 8, ви можете використовувати атрибут властивості класу , на який відповів Бербі.
Однак у реалізації вам потрібно визначити як getter class, так і setter для властивості класу, використовуючи статичну змінну замість iVar.
Зразок.h
@interface Sample: NSObject
@property (class, retain) Sample *sharedSample;
@end
Зразок м
@implementation Sample
static Sample *_sharedSample;
+ ( Sample *)sharedSample {
if (_sharedSample==nil) {
[Sample setSharedSample:_sharedSample];
}
return _sharedSample;
}
+ (void)setSharedSample:(Sample *)sample {
_sharedSample = [[Sample alloc]init];
}
@end
Якщо у вас є багато властивостей рівня класу, тоді може бути порядковий однотонний візерунок. Щось на зразок цього:
// Foo.h
@interface Foo
+ (Foo *)singleton;
@property 1 ...
@property 2 ...
@property 3 ...
@end
І
// Foo.m
#import "Foo.h"
@implementation Foo
static Foo *_singleton = nil;
+ (Foo *)singleton {
if (_singleton == nil) _singleton = [[Foo alloc] init];
return _singleton;
}
@synthesize property1;
@synthesize property2;
@synthesise property3;
@end
Тепер перейдіть до таких властивостей на рівні класу, як цей:
[Foo singleton].property1 = value;
value = [Foo singleton].property2;
dispatch_once
.
[Спробуйте це рішення просто] Ви можете створити статичну змінну в класі Swift, а потім викликати її з будь-якого класу Objective-C.