Как объявить свойства уровня класса в Objective-C? - PullRequest
195 голосов
/ 30 марта 2009

Может быть, это очевидно, но я не знаю, как объявить свойства класса в Objective-C.

Мне нужно кэшировать словарь для каждого класса и задаться вопросом, как поместить его в класс.

Ответы [ 10 ]

184 голосов
/ 30 марта 2009

свойства имеют определенное значение в 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;
}
108 голосов
/ 04 апреля 2013

Я использую это решение:

@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);
71 голосов
/ 16 июня 2016

Как видно из 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
63 голосов
/ 30 марта 2009

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

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

21 голосов
/ 26 сентября 2013

Вот безопасный способ сделать это:

// 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 - выполняет объект блока один раз и только один раз за время существования приложения."

11 голосов
/ 14 ноября 2016

Начиная с 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;
7 голосов
/ 30 марта 2009

Свойства имеют значения только в объектах, а не в классах.

Если вам нужно что-то хранить для всех объектов класса, вы должны использовать глобальную переменную. Вы можете скрыть это, объявив его static в файле реализации.

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

Другой вариант - создать объект выделенного класса, который состоит из вашего словаря 'class' и набора всех объектов, связанных с этим словарем. Это что-то вроде NSAutoreleasePool в Какао.

5 голосов
/ 15 августа 2018

Начиная с Xcode 8, вы можете использовать атрибут свойства class , как ответил Берби.

Однако в реализации вам необходимо определить и класс getter, и сеттер для свойства класса, используя статическую переменную вместо iVar.

Sample.h

@interface Sample: NSObject
@property (class, retain) Sample *sharedSample;
@end

Sample.m

@implementation Sample
static Sample *_sharedSample;
+ ( Sample *)sharedSample {
   if (_sharedSample==nil) {
      [Sample setSharedSample:_sharedSample];
   }
   return _sharedSample;
}

+ (void)setSharedSample:(Sample *)sample {
   _sharedSample = [[Sample alloc]init];
}
@end
2 голосов
/ 09 сентября 2014

Если у вас много свойств на уровне класса, то может быть в порядке одиночный шаблон Примерно так:

// 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;
0 голосов
/ 04 января 2017

[Попробуйте это решение, это просто] Вы можете создать статическую переменную в классе Swift, а затем вызвать ее из любого класса Objective-C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...