Hey, I am making a imageloading system with my tablecells and I need each cell to share the same instance of my imageloader class. Sorry if this is a nooby question, but is it possible to archieve this? So what I am meaning is that if I have int variable in other instance of the same class, the value of the int variable is same in both classes.
Thanks in advance!
For a "single instance for everything", you need a singleton:
+(SomeClass *)sharedInstance {
static SomeClass *instance = nil;
if (instance == nil) {
instance = [[self alloc] init];
}
return instance;
}
Then wherever you need the shared instance, just do:
SomeClass *obj = [SomeClass sharedInstance];
The static variable is basically what makes it work, when coupled with the "is nil" test, since static variables are only ever initialized once.
Incidentally, I think due to the way UITableViewCells are used (i.e. copied) you may already have what you need without any further work such as creating a singleton. Just provide the correct shallow-copy logic in copyWithZone:.
Related
When i was going through Singleton design pattern in Objective C, I found lot of people using the below code to create it.
#interface Base : NSObject {}
+(id)instance;
#end
#implementation Base
+(id) instance
{
static id theInstance = nil;
if (theInstance == nil)
{
theInstance = [[self alloc] init];
}
return theInstance;
}
#end
Here i did not get the why do we have to assign the static variable to nil in a method instead it can be declared outside the method and assigned to nil.
Because everytime this +instance() method is called, theInstance variable will be assigned to nil.
Will it not lose its previous object to which it was pointing to?
I have tried debugging it, surprisingly , it will not point to nil when +instance() method is called.
Can anyone explain me whats happening here?
static variables only get initialized once, regardless of if they're at global or local scope. In this case, you don't even need the nil - static storage class variables are zero-initialized by default. This declaration:
static id theInstance;
is enough to be the same as what you have there.
I saw a singleton example on objective-c book. However, I don't know if there is difference of meaning of 'singleton' definition between objective-c and other langs. Can this [[SingletonClass alloc] init] still be used to create a new object? If yes, how to guarantee there is only one object in the memory?
#import "SingletonClass.h"
#implementation SingletonClass
static SingletonClass *sharedInstance = nil;
// Get the shared instance and create it if necessary.
+ (SingletonClass*)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}
// We can still have a regular init method, that will get called the first time the Singleton is used.
- (id)init
{
self = [super init];
if (self) {
// Work your initialising magic here as you normally would
}
return self;
}
If you want a true singleton, i.e. an object that can be instantiated only once, take a look at Apple's documentation: Creating a Singleton Instance.
Basically, the idea is to override a number of methods related to allocating and managing objects: +allocWithZone (which is called by +alloc), -retain, -release, -copyWithZone, etc., so that it becomes quite difficult to create more than one instance of your singleton class. (It's still possible to create a second instance by calling the runtime directly, but this should be enough to get the point across.)
Pretty much every blogger who has ever written about Objective-C in any capacity has offered an opinion on how to implement singletons. Many of those opinions seem pretty good, and most of them are fairly similar. It's clear that Dave DeLong knows what he's talking about, and his piece on singletons is short, sweet, and gets straight to the point.
I don't know if there is difference of meaning of 'singleton' definition between objective-c and other langs.
It follows the common definition of languages derived from C.
Can this [[SingletonClass alloc] init] still be used to create a new object?
Yes
If yes, how to guarantee there is only one object in the memory?
Avoid enforcing the pattern (e.g. do not force it to be a singleton). Just make a normal object. Then if you really want only one instance, create an instance and save it someplace for reuse (your app delegate is one typical place for this, because it is typically created once per execution).
In practice, most (>95%) ObjC singleton implementations i've seen in the wild are used for the wrong reasons, and would have been better or as good as normal objects.
Every solution linked in the answers so far has (at minimum) subtle problems, dangers, or undesirable side-effects.
There is no language support for singletons, but you can do it by hand. Look at the singleton example here. It doesn't look like it is thread-safe, though. I would allocate the object in +initialize instead of +sharedManager.
You can create a singleton in Objective-C by doing the following:
+(MyAPI *)shared {
static dispatch_once_t queue;
static MyAPI *singleton = nil;
dispatch_once(&queue, ^{
singleton = [[MyAPI alloc] init];
});
return singleton;
}
This will also ensure that it is thread safe. Without using the dispatch_once you run the risk of multiple threads trying to access it at the same time when one is in the middle of allocating it, and the other is trying to use it.
Singleton class is used to save the data for use anywhere in app.
//SingletonObject
#define saveDataSingletonObject ((SaveDataSingleton*)[SaveDataSingleton sharedManager])
#interface SaveDataSingleton : NSObject
#property (nonatomic,strong) NSMutableArray *DataArr;
+ (id)sharedManager;
-(void)clearAllSaveData;
#end
#implementation SaveDataSingleton
#synthesize DataArr;
+ (id)sharedManager {
static SaveDataSingleton *sharedManager;
if(!sharedManager) {
#synchronized(sharedManager) {
sharedManager = [SaveDataSingleton new];
}
}
return sharedManager;
}
-(void)clearAllSaveData{
DataArr=nil;
}
- (id)init {
if (self = [super init]) {
DataArr = [[NSMutableArray alloc]init];
}
return self;
}
// using setter getter save and retrieve data
+(void)setDataArr:(NSMutableArray *)Dataarr
{
self.DataArr = [[NSMutableArray alloc]initWithArray:Dataarr];
}
+(NSMutableArray *)DataArr
{
return self.DataArr;
}
#end
Save and Retrieve data // Use singleton Object
// save data using setter function.
[saveDataSingletonObject setDataArr:Array];
//fetch data using getter function.
NSArray *arr=[saveDataSingletonObject DataArr];
I have a function that is synchronized, but it seems that I can't directly change the value of my instance variables in that block.
+(id)allocWithZone:(NSZone *)zone
{
#synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [super allocWithZone:zone];
//This is not allowed
something = #"hello";
//This is allowed
self.something = #"hello world!";
return sharedInstance;
}
}
return nil;
}
Why is this the case? I have a variable that I need to access directly (and I don't want to synthesize that variable). How do I get around this?
You can't change instance variables because this isn't an instance method. The value of self is, in fact, the class itself. Your line of code self.something = #"hello world!" won't work either. What you really want is sharedInstance.something = #"hello world!", and that will only work if something is a property. Even better would be to set up the ivars in the init method.
Oh, and you have no business setting ivars in +allocWithZone: anyway. The object has not been initialized yet.
Assuming you're trying to create a singleton here (as that's what it looks like), you may want to read this blog post on singletons in Obj-C.
This question already has answers here:
What does #synchronized() do as a singleton method in objective C?
(6 answers)
Closed 3 years ago.
After reading the responses to a question about singletons in Objective C it appears that each solution makes some tradeoff in regards to threading in the instance accessor. i.e.
#synchronized(self)
{
if (sharedInstance == nil)
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
This essentially single-threads access to the singleton, and if it's something that's used frequently in an operation, seems like something that could cause threads to unnecessarily contend.
What's the downside to simply using the class object as the singleton instance, and exposing functionality via class methods, i.e.
#interface MySingleton : NSObject {
}
+ (void)doSomething;
#end
#implementation MySingleton
+ (void)initialize {
//do some setup if necessary
}
+ (void)doSomething {
//do something
}
#end
In this way we avoid doing the lock + check every time we want to reference the singleton object and we can also eliminate having to store it in a local or method ivar.
This approach also lets the runtime guarantee that only one instance (the Class object) exists in the system at any given time.
EDIT
There's more here than just threading, with a traditional singleton you usually write code like this:
MySingleton *instance = [MySingleton getSharedInstance];
NSObject *someResult = [instance getResult];
//or
if (instance.someProperty) {
//do something
}
However if your singleton is a class instance, you essentially eliminate the need call getSharedInstance all the time. Consider this code:
NSObject *someResult = [MySingleton getResult];
//or
if ([MySingleton someProperty]) {
//do something
}
I hear the point that you have to store your data in file local static variables, or in global variables (yuck). But it's really not all that different from a traditional singleton with the exception that you lose Objective-C 2.0 properties (instead you have to use traditional accessor methods).
Here's one key tradeoff for me that seems like a win. In a traditional singleton you end up overriding -copyWithZone, +allocWithZone, -retain, -retainCount, -release and -autorelease if you really want to get things right.
This seems like an awful lot of work to do every time you want to write a simple Singleton object (they happen to be pretty useful). So why not simply just replace it with this:
#implementation MySingleton
+ (void)initialize {
//do your setup
}
- (id)init {
NSAssert(NO, #"You should read the documentation on singletons.");
}
#end
It's a lot lighter in terms of code, and unless your consumers are really sneaky they won't ever create two instances.
Get to the point already
My question is really this:
Is there any drawback to using the Class object as the instance of your singleton?
It seems like you can take all the same steps in terms of threadsafety, memory efficiency etc. without having to remember to override so many methods and accessors or litter your code with instance checks.
With iOS 4.0 or later, by far the best solution is to just use dispatch_once, as in
+ (id)sharedInstance {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedInstance = [[MyClass alloc] init];
});
return sharedInstance;
}
You may also want to consider using a single dispatch_queue to serialize access to the internals of a class. If all your public methods just run a block on the same dispatch_queue then you won't have to worry about concurrency issues.
This is my first post on Stack Overflow... (so prepare for stupidity)
I think there is a hybrid solution that might be useful.
I want to set and get (global) values out of a singleton class without having calling "getSharedInstance". I'd want the code to look like this...
frameRate = Singleton.frameRate;
Singleton.frameRate = 42;
To achieve this, each variable we need to store in the singleton has a getter and setter class method. The class method then goes to an instance to store the data in an ivar. The instance isn't directly accessed by the main program.
The getter looks like this:
+ (int) frameRate
{
return [[Singleton instance] ivarFrameRate];
}
The (ugly) instance call is hidden inside the class code.
By calling the instance method here, the class method will automatically instantiate an object when first used. Once the singleton is instantiated, the instance stores ivars conventionally. Here, I am prefixing with "ivar" make the ivar explicit.
#property int ivarFrameRate;
and
#synthesize ivarFrameRate;
This automatically creates conventional getter (and setter) methods to access the ivar.
(edit - here is a complete example)
// Singleton.h
#import <Foundation/Foundation.h>
#interface Singleton : NSObject
{
float ivarFrameRate
}
#property float ivarFrameRate;
- (id) init;
+ (Singleton *) instance;
+ (float) frameRate;
+ (void) setFrameRate:(float)fr;
#end
and
// Singleton.m
#import "Singleton.h"
#implementation Singleton
#synthesize ivarFrameRate;
static Singleton* gInstance = NULL;
+ (Singleton*)instance
{
#synchronized(self)
{
if (gInstance == NULL)
gInstance = [[self alloc] init];
}
return(gInstance);
}
- (id)init
{
self = [super init];
return self;
}
+ (float) frameRate
{
return [[Singleton instance] ivarFrameRate];
}
+ (void) setFrameRate:(float)fr;
{
[[Singleton instance] setIvarFrameRate:fr];
}
This is fine, but still just changes your circumstances rather than fixes your problems. Unless you don't have any actual data tied to your singleton, in which case this will work just fine. Anytime you access central data you will need to properly make it thread-safe.
Additionally, without some kind of iVar I don't know of a way to store data (that is intended) directly in a class.
In the example above I would code it in this way, getting the same result as you are proposing and only taking the performance hit if we are creating/re-creating the singleton:
if (sharedInstance)
return sharedInstance;
#synchronized(self)
{
if (sharedInstance == nil)
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
Keep in mind that either way, if you are accessing data that is potentially changing on different threads then you'll have to make that code thread-safe anyway, either with very careful planning or using code to ensure there are no problems. I'd recommend a mix, but when in doubt the latter when at all possible. =)
If you use a class as your singleton, the only way to store data would be to use static file variables and global variables. If you are going to go so far that you make a class you don't plan to instantiate, you might as well just use standard C functions:
void doSomething(void);
void doSomething() {
//do something
}
I've found this snippet of code on the net. It sets up an NSMutableArray in a way I've not seen before ( I'm an Obj-C newb). Can someone explain what it's doing and why you would do it this way? Particularly the #syncronized, static and little plus sign on the method signature.
add the following to the .h file:
+(NSMutableArray *)allMySprites;
add the following to he .m file after implementation:
static NSMutableArray * allMySprites = nil;
+(NSMutableArray *)allMySprites {
#synchronized(allMySprites) {
if (allMySprites == nil)
allMySprites = [[NSMutableArray alloc] init];
return allMySprites;
}
return nil;
}
Adding to the other responses ... the posted code is wrong. It should be more like this:
#implementation SpriteManager
+ (NSMutableArray*) allMySprites {
#synchronized(self) {
if (allMySprites == nil) {
allMySprites = [[NSMutableArray alloc] init];
}
}
return allMySprites;
}
#end
It makes no sense to #synchronize on nil. Using self in a class method refers to the class and not the instance. Also the 'return nil' in the original code is pointless.
A better approach where the #synchronized can be completely avoided is to use a class initializer method:
#implementation SomeClass
+ (void) initialize
{
allMySprites = [[NSMutableArray alloc] init];
}
#end
The initialize methods are guaranteed to be called before the class is used.
The + sign indicates the method is static as opposed to instance methods. It means the method belongs to the class rather than each instance of a class (just like static things in Java and C#). #synchronized acquires a lock on the object specified (like lock statement in C#). It means no other thread can enter a #synchronized block with that object.
The code as a whole is trying to initialize a singleton collection the first time (when it's not initialized yet) and cache it for use in subsequent calls to that method. The synchronized block creates a critical section to make the initialization part safe in case of a race condition where two threads try to get the value roughly the same time while it's still doing the initialization.
It's an implementation of the Singleton design pattern, basically a way of making sure that you only have one copy of your MySprites.
The details:
The + means that this is a class method
The #syncyronize makes access to the allMySprites variable thread-safe (there are a few caveats but that's the one line summary)
I believe that the static limits the scope of the variable only to the file