Xcode 4.2'de otomatik başvuru sayımı (ARC) kullanırken doğru bir şekilde derlenen ve davranan tek bir sınıfı nasıl dönüştürebilirim (veya oluşturabilirim)?
Xcode 4.2'de otomatik başvuru sayımı (ARC) kullanırken doğru bir şekilde derlenen ve davranan tek bir sınıfı nasıl dönüştürebilirim (veya oluşturabilirim)?
Yanıtlar:
Tam olarak aynı şekilde yapmalısınız (zaten):
+ (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
Yöntem / işlev içinde bildirilen değişken değişkenler, yöntem / işlev static
dışında bildirilen bir değişkenle aynıdır , yalnızca bu yöntem / işlev kapsamında geçerlidir. +sharedInstance
Yöntemdeki her ayrı işlem (farklı evrelerde bile) aynı sharedInstance
değişkeni "görür" .
gerektiği gibi başka bir örnek oluşturmak istiyorsanız bunu yapın:
+ (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;
}
aksi takdirde, bunu yapmalısınız:
+ (id)allocWithZone:(NSZone *)zone
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
dispatch_once()
Bit, ilk örnekte bile ek örnekler almayacağınız anlamına gelir ...?
[[MyClass alloc] init]
ve sharedInstance
erişimi atlayabilir . DongXu, Peter Hosey'in Singleton makalesine bakmalısın . Daha allocWithZone:
fazla örneğin oluşturulmasını init
önlemek için geçersiz kılmanız gerekiyorsa, paylaşılan örneğin yeniden başlatılmasını önlemek için de geçersiz kılmanız gerekir .
allocWithZone:
versiyon. Teşekkürler.
Bu ARC ve ARC olmayan bir sürümdür
Nasıl kullanılır:
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 kapsamındaki kalıbım bu. GCD kullanarak yeni kalıbı ve Apple'ın eski örnekleme önleme kalıbını da tatmin eder.
@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
, bir AAA
üst sınıf örneği olmakla sonuçlanmaz mı? Sen buna gerek +alloc
üzerinde self
olmamasına, super
.
super
, süper sınıf nesne anlamına gelmez. Süper sınıf nesnesi elde edemezsiniz Sadece mesajların yöntemin süper sınıf versiyonuna yönlendirilmesi anlamına gelir. super
hala self
sınıfı gösteriyor. Süper sınıf bir nesne almak istiyorsanız, çalışma zamanı yansıma işlevlerine sahip olmanız gerekir.
-allocWithZone:
yöntemi, geçersiz kılma noktası sunmak için çalışma zamanının ayırma işlevine basit bir zincirdir. Sonuçta, self
pointer == geçerli sınıf nesnesi ayırıcıya iletilecek ve son olarak AAA
örnek tahsis edilecektir.
super
sınıf yöntemlerinde nasıl çalıştığının inceliklerini unuttum .
Bu yanıtı okuyun ve sonra diğer yanıtı okuyun.
Önce bir Singleton'un ne anlama geldiğini ve gerekliliklerini bilmelisiniz, eğer anlamadıysanız, çözümü anlamadığınızdan - hiç!
Başarılı bir Singleton oluşturmak için aşağıdakileri yapabilmeniz gerekir 3:
dispatch_once_t
çözmenize yardımcı olur engellemesinin yalnızca bir kez gönderilmesine izin vererek yarış durumunu .
Static
herhangi bir sayıda çağrının değerini “hatırlamanıza” yardımcı olur. Nasıl hatırlıyor? SharedInstance öğenizin tam adıyla yeni bir örneğin yeniden oluşturulmasına izin vermez, yalnızca orijinal olarak oluşturulan örnekle çalışır.
SharedInstance sınıfımızda çağrı kullanmamakalloc
init
(yani alloc
init
bir NSObject alt sınıfı olduğumuz için hala yöntemlerimiz var) , ancak bunu yapmak zorundayız +(instancetype)sharedInstance
. bir kez başlatılan farklı parçacığı birden fazla girişimleri bakılmaksızın, ve değerini hatırlayın.
Kakao ile birlikte gelen en yaygın sistem Singletonlarından bazıları şunlardır:
[UIApplication sharedApplication]
[NSUserDefaults standardUserDefaults]
[NSFileManager defaultManager]
[NSBundle mainBundle]
[NSOperations mainQueue]
[NSNotificationCenter defaultCenter]
Temel olarak merkezi bir etkiye sahip olması gereken her şeyin bir çeşit Singleton tasarım modelini izlemesi gerekir.
Alternatif olarak Objective-C, NSObject ve tüm alt sınıfları için + (void) başlatma yöntemini sağlar. Her zaman sınıfın herhangi bir yönteminden önce çağrılır.
İOS 6'da bir kez bir kesme noktası belirledim ve yığın çerçevelerinde dispatch_once belirdi.
Singleton Sınıfı: Hiç kimse hiçbir durumda veya herhangi bir yolla birden fazla sınıf nesnesi oluşturamaz.
+ (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];
}
Kabul edilen cevapta, amacınızla ilgili olan veya olmayan iki sorun vardır.
Aşağıdaki kod, bu sorunların her ikisine de bakar:
+ (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
Yukarıdaki kod umut yardımcı olacaktır.
hızlı bir şekilde singleton oluşturmanız gerekiyorsa,
class var sharedInstance: MyClass {
struct Singleton {
static let instance = MyClass()
}
return Singleton.instance
}
veya
struct Singleton {
static let sharedInstance = MyClass()
}
class var sharedInstance: MyClass {
return Singleton.sharedInstance
}
bu şekilde kullanabilirsiniz
let sharedClass = LibraryAPI.sharedInstance