Jak zaimplementować Objective-C singleton, który jest kompatybilny z ARC?
Jak przekonwertować (lub utworzyć) klasę singleton, która kompiluje i zachowuje się poprawnie przy użyciu automatycznego zliczania referencji (ARC) w Xcode 4.2?
10 answers
W dokładnie taki sam sposób jak ty (powinieneś) już to robić:
+ (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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-03 00:28:54
Jeśli chcesz utworzyć inną instancję jako needed.do to:
+ (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;
}
Else, you should do this:
+ (id)allocWithZone:(NSZone *)zone
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-08 09:19:32
Jest to wersja dla ARC i nie-ARC
Jak używać:
MySingletonClass.h@interface MySingletonClass : NSObject
+(MySingletonClass *)sharedInstance;
@end
MySingletonClass.m
#import "MySingletonClass.h"
#import "SynthesizeSingleton.h"
@implementation MySingletonClass
SYNTHESIZE_SINGLETON_FOR_CLASS(MySingletonClass)
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-18 14:23:28
To mój wzór pod łukiem. Spełnia nowy wzór za pomocą GCD, a także spełnia stary wzór zapobiegania instancjacji 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-17 03:57:29
Przeczytaj tę odpowiedź, a następnie idź i przeczytaj drugą odpowiedź.
Musisz najpierw wiedzieć, co oznacza Singleton i jakie są jego wymagania, jeśli tego nie rozumiesz, to nie zrozumiesz rozwiązania-w ogóle!
Aby utworzyć Singleton z powodzeniem, musisz wykonać następujące 3:
- jeśli istniał warunek race , to nie możemy pozwolić na tworzenie wielu instancji SharedInstance jednocześnie czas!
- Zapamiętaj i zachowaj wartość pomiędzy wieloma wywołaniami.
- utwórz go tylko raz. Kontrolując punkt wejścia.
dispatch_once_t
pomaga rozwiązać Stan rasy , pozwalając tylko na wysłanie jego bloku tylko raz.
Static
pomaga "zapamiętać" jego wartość w dowolnej liczbie
inwokacje. Jak to zapamiętuje? Nie pozwala na ponowne utworzenie nowej instancji o tej dokładnej nazwie sharedInstance, po prostu działa z tą, która powstała pierwotnie.
Nie używaj wywołania alloc
init
(czyli mamy jeszcze alloc
init
metody ponieważ jesteśmy podklasą NSObject, chociaż nie powinniśmy ich używać) na naszej klasie sharedInstance, osiągamy to używając +(instancetype)sharedInstance
, która jest ograniczona do zainicjowanej tylko raz, niezależnie od wielu prób z różnych wątków w tym samym czasie i zapamiętujemy jej wartość.
Niektóre z najczęstszych singletonów systemowych, które pochodzą z samego Cocoa są:
[UIApplication sharedApplication]
[NSUserDefaults standardUserDefaults]
[NSFileManager defaultManager]
[NSBundle mainBundle]
-
[NSOperations mainQueue]
[NSNotificationCenter defaultCenter]
W zasadzie wszystko, co musiałoby mieć scentralizowany efekt, musiałoby podążać za pewnego rodzaju wzorcem projektowym Singletona.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:43
Alternatywnie, Objective-C dostarcza metodę + (void)initialize dla NSObject i wszystkich jego podklas. Jest zawsze wywoływana przed jakimikolwiek metodami klasy.
Ustawiłem punkt przerwania w jednym raz w iOS 6 i dispatch_once pojawił się w ramkach stosu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-20 19:28:47
Klasa Singleton: nikt nie może utworzyć więcej niż jednego obiektu klasy w każdym przypadku lub w jakikolwiek sposób.
+ (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];
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-29 02:31:57
Istnieją dwa problemy z zaakceptowaną odpowiedzią, które mogą, ale nie muszą być istotne dla Twojego celu.
- Jeśli z metody INIT zostanie ponownie wywołana metoda sharedInstance (np. z powodu budowy innych obiektów, które używają singletonu) spowoduje to przepełnienie stosu.
- dla hierarchii klas istnieje tylko jeden singleton (mianowicie: pierwsza klasa w hierarchii, na której została wywołana metoda sharedInstance), zamiast jednego Singletona na konkretny klasy w hierarchii.
Poniższy kod rozwiązuje oba te problemy:
+ (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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-02 15:08:54
#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
Nadzieję, że powyższy kod pomoże.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-06 11:48:38
Jeśli chcesz utworzyć singleton w języku swift,
class var sharedInstance: MyClass {
struct Singleton {
static let instance = MyClass()
}
return Singleton.instance
}
Lub
struct Singleton {
static let sharedInstance = MyClass()
}
class var sharedInstance: MyClass {
return Singleton.sharedInstance
}
Możesz użyć tego sposobu
let sharedClass = LibraryAPI.sharedInstance
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 14:57:17