Как преобразовать (или создать) одноэлементный класс, который компилируется и ведет себя правильно при использовании автоматического подсчета ссылок (ARC) в Xcode 4.2?
Как преобразовать (или создать) одноэлементный класс, который компилируется и ведет себя правильно при использовании автоматического подсчета ссылок (ARC) в Xcode 4.2?
Ответы:
Точно так же, как вы (должны) уже делали это:
+ (instancetype)sharedInstance
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
static
Переменные @David, объявленные в методе / функции, аналогичны static
переменной, объявленной вне метода / функции, они действительны только в рамках этого метода / функции. Каждый отдельный прогон +sharedInstance
метода (даже в разных потоках) будет «видеть» одну и ту же sharedInstance
переменную.
если вы хотите создать другой экземпляр по мере необходимости. сделайте следующее:
+ (MyClass *)sharedInstance
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
иначе вы должны сделать это:
+ (id)allocWithZone:(NSZone *)zone
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
dispatch_once()
бит означает, что вы не получите дополнительные экземпляры, даже в первом примере ...?
[[MyClass alloc] init]
и обойти sharedInstance
доступ. DongXu, вы должны посмотреть на статью Питера Хоси Singleton . Если вы собираетесь переопределить, allocWithZone:
чтобы предотвратить создание большего количества экземпляров, вы также должны переопределить, init
чтобы предотвратить повторную инициализацию общего экземпляра.
allocWithZone:
версия. Спасибо.
Как пользоваться:
MySingletonClass.h
@interface MySingletonClass : NSObject
+(MySingletonClass *)sharedInstance;
@end
MySingletonClass.m
#import "MySingletonClass.h"
#import "SynthesizeSingleton.h"
@implementation MySingletonClass
SYNTHESIZE_SINGLETON_FOR_CLASS(MySingletonClass)
@end
Это мой шаблон под ARC. Удовлетворяет новый шаблон, используя GCD, а также удовлетворяет старый шаблон Apple по предотвращению создания экземпляров.
@implementation AAA
+ (id)alloc
{
return [self allocWithZone:nil];
}
+ (id)allocWithZone:(NSZone *)zone
{
[self doesNotRecognizeSelector:_cmd];
abort();
}
+ (instancetype)theController
{
static AAA* c1 = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
c1 = [[super allocWithZone:nil] init];
// For confirm...
NSLog(@"%@", NSStringFromClass([c1 class])); // Prints AAA
NSLog(@"%@", @([c1 class] == self)); // Prints 1
Class real_superclass_obj = class_getSuperclass(self);
NSLog(@"%@", @(real_superclass_obj == self)); // Prints 0
});
return c1;
}
@end
c1
что он станет AAA
суперклассом России? Вам нужно позвонить +alloc
на self
, а не на super
.
super
не означает объект суперкласса. Вы не можете получить объект суперкласса. Это просто означает маршрутизацию сообщений в версию метода суперкласса. super
все еще указывает self
класс. Если вы хотите получить объект суперкласса, вам нужно получить функции отражения во время выполнения.
-allocWithZone:
метод - это просто простая цепочка для функции выделения времени выполнения, чтобы предложить точку переопределения. В конечном итоге self
указатель == текущий объект класса будет передан распределителю, и, наконец, AAA
экземпляр будет выделен.
super
работает в методах класса.
Прочитайте этот ответ, а затем иди и прочитайте другой ответ.
Сначала вы должны знать, что означает синглтон и каковы его требования, если вы не понимаете его, тогда вы не поймете решение - вообще!
Чтобы успешно создать синглтон, вы должны выполнить следующие 3:
dispatch_once_t
помогает вам решить условие гонки , позволяя отправлять блок только один раз.
Static
помогает вам «запомнить» его значение при любом количестве вызовов. Как это запомнить? Он не позволяет создавать новый экземпляр с таким точным именем вашего sharedInstance, он просто работает с тем, который был создан изначально.
Не используя вызовы alloc
init
(т. alloc
init
Е. У нас все еще есть методы, поскольку мы являемся подклассом NSObject, хотя мы НЕ должны их использовать) в нашем классе sharedInstance, мы достигаем этого с помощью +(instancetype)sharedInstance
ограничения, которое может быть инициировано только один раз , независимо от нескольких попыток из разных потоков. в то же время и помните его значение.
Некоторые из наиболее распространенных системных синглетонов, которые поставляются вместе с Какао:
[UIApplication sharedApplication]
[NSUserDefaults standardUserDefaults]
[NSFileManager defaultManager]
[NSBundle mainBundle]
[NSOperations mainQueue]
[NSNotificationCenter defaultCenter]
По сути, все, что должно иметь централизованный эффект, должно следовать какому-то шаблону проектирования Singleton.
В качестве альтернативы Objective-C предоставляет метод инициализации + (void) для NSObject и всех его подклассов. Он всегда вызывается перед любыми методами класса.
Я установил точку останова один раз в iOS 6, и dispatch_once появился в кадрах стека.
Класс Singleton: Никто не может создать более одного объекта класса в любом случае или любым способом.
+ (instancetype)sharedInstance
{
static ClassName *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[ClassName alloc] init];
// Perform other initialisation...
});
return sharedInstance;
}
// You need need to override init method as well, because developer can call [[MyClass alloc]init] method also. that time also we have to return sharedInstance only.
-(MyClass)init
{
return [ClassName sharedInstance];
}
Есть два вопроса с принятым ответом, которые могут или не могут иметь отношение к вашей цели.
Следующий код решает обе эти проблемы:
+ (instancetype)sharedInstance {
static id mutex = nil;
static NSMutableDictionary *instances = nil;
//Initialize the mutex and instances dictionary in a thread safe manner
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mutex = [NSObject new];
instances = [NSMutableDictionary new];
});
id instance = nil;
//Now synchronize on the mutex
//Note: do not synchronize on self, since self may differ depending on which class this method is called on
@synchronized(mutex) {
id <NSCopying> key = (id <NSCopying>)self;
instance = instances[key];
if (instance == nil) {
//Break allocation and initialization into two statements to prevent a stack overflow, if init somehow calls the sharedInstance method
id allocatedInstance = [self alloc];
//Store the instance into the dictionary, one per concrete class (class acts as key for the dictionary)
//Do this right after allocation to avoid the stackoverflow problem
if (allocatedInstance != nil) {
instances[key] = allocatedInstance;
}
instance = [allocatedInstance init];
//Following code may be overly cautious
if (instance != allocatedInstance) {
//Somehow the init method did not return the same instance as the alloc method
if (instance == nil) {
//If init returns nil: immediately remove the instance again
[instances removeObjectForKey:key];
} else {
//Else: put the instance in the dictionary instead of the allocatedInstance
instances[key] = instance;
}
}
}
}
return instance;
}
#import <Foundation/Foundation.h>
@interface SingleTon : NSObject
@property (nonatomic,strong) NSString *name;
+(SingleTon *) theSingleTon;
@end
#import "SingleTon.h"
@implementation SingleTon
+(SingleTon *) theSingleTon{
static SingleTon *theSingleTon = nil;
if (!theSingleTon) {
theSingleTon = [[super allocWithZone:nil] init
];
}
return theSingleTon;
}
+(id)allocWithZone:(struct _NSZone *)zone{
return [self theSingleTon];
}
-(id)init{
self = [super init];
if (self) {
// Set Variables
_name = @"Kiran";
}
return self;
}
@end
Надеюсь, приведенный выше код поможет вам.
если вам нужно создать синглтон в Swift,
class var sharedInstance: MyClass {
struct Singleton {
static let instance = MyClass()
}
return Singleton.instance
}
или
struct Singleton {
static let sharedInstance = MyClass()
}
class var sharedInstance: MyClass {
return Singleton.sharedInstance
}
Вы можете использовать этот способ
let sharedClass = LibraryAPI.sharedInstance