在Xcode 4.2中使用自动引用计数(ARC)时,如何转换(或创建)编译和行为正确的单例类?
答案 0 :(得分:373)
与你(应该)已经完全相同的方式:
+ (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;
}
答案 1 :(得分:8)
如果你想根据需要创建其他实例。这个:
+ (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;
}
答案 2 :(得分:5)
This is a version for ARC and non-ARC
如何使用:
MySingletonClass.h
@interface MySingletonClass : NSObject
+(MySingletonClass *)sharedInstance;
@end
MySingletonClass.m
#import "MySingletonClass.h"
#import "SynthesizeSingleton.h"
@implementation MySingletonClass
SYNTHESIZE_SINGLETON_FOR_CLASS(MySingletonClass)
@end
答案 3 :(得分:2)
这是我在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
答案 4 :(得分:2)
阅读此答案然后去阅读其他答案。
你必须首先了解一个单身人士的意思,如果你不理解它的要求是什么,那么你根本不会理解这个解决方案!
要成功创建Singleton,您必须能够执行以下3:
dispatch_once_t
只允许分配一次}来帮助您解决竞争条件。
Static
可帮助您“记住”其中任意数量的值
调用。怎么记得?它不允许再次创建具有您的sharedInstance的确切名称的任何新实例,它只适用于最初创建的实例。
未使用调用alloc
init
(即我们仍有alloc
init
个方法,因为我们是NSObject子类,但我们不应该在我们的sharedInstance类上使用它们,我们通过使用+(instancetype)sharedInstance
来实现这一点,[UIApplication sharedApplication]
仅限一次启动,无论同时来自不同线程的多次尝试并记住它的值
Cocoa自带的一些最常见的系统单身人士是:
[NSUserDefaults standardUserDefaults]
[NSFileManager defaultManager]
[NSBundle mainBundle]
[NSOperations mainQueue]
[NSNotificationCenter defaultCenter]
基本上任何需要集中效果的东西都需要遵循某种单一的设计模式。
答案 5 :(得分:1)
或者,Objective-C为NSObject及其所有子类提供+(void)初始化方法。它总是在类的任何方法之前调用。
我在iOS 6中设置了一次断点,并且堆栈帧中出现了dispatch_once。
答案 6 :(得分:0)
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];
}
答案 7 :(得分:0)
接受的答案有两个问题,可能与您的目的相关或不相关。
以下代码解决了这两个问题:
+ (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;
}
答案 8 :(得分:-2)
function uploadFile(revision)
{
var file1 = _("fileToUpload").files[0];
// FIXME: Developer Option
alert(file1.name+" | "+file1.size+" | "+file1.type);
var formdata = new FormData();
formdata.append("fileToUpload", file1);
formdata.append("revision", revision);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "../file_upload_parser.php");
ajax.send(formdata);
}
希望上面的代码可以帮助它。
答案 9 :(得分:-2)
如果你需要在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