I have couple of classes that should be inherited from some A class.
Each of them should be a Singleton.
Can this be achieved?
This realization of Singleton-pattern allows the inheritance:
+ (instancetype)sharedInstance {
static dispatch_once_t once;
static NSMutableDictionary *sharedInstances;
dispatch_once(&once, ^{ /* This code fires only once */
// Creating of the container for shared instances for different classes
sharedInstances = [NSMutableDictionary new];
});
id sharedInstance;
#synchronized(self) { /* Critical section for Singleton-behavior */
// Getting of the shared instance for exact class
sharedInstance = sharedInstances[NSStringFromClass(self)];
if (!sharedInstance) {
// Creating of the shared instance if it's not created yet
sharedInstance = [self new];
sharedInstances[NSStringFromClass(self)] = sharedInstance;
}
}
return sharedInstance;
}
You never, ever inherit from a Singleton class. That completely breaks the concept of a Singleton in a bad way.
Having multiple singleton classes inheriting from the same base class: No problem whatsoever. In fact, most singletons have the common superclass NSObject, but you can use any other superclass.
Yes. I'm not sure if you're familiar with Obj-C singleton patterns, but here is a guide:
http://www.galloway.me.uk/tutorials/singleton-classes/
There shouldn't be any more complications in subclassing. Just create a subclass of the singleton, and it will inherit it's singleton abilities as well. I think each subclass will create it's own unique singleton, but if not, override the singleton generator so it's unique for that subclass.
Keep in mind, singletons are falling out of favor on iOS, so they should be used sparingly. I try to only use them when attempting to create multiple instances is simply not possible (i.e. a class for accessing a hardware resource that must be reserved exclusively by a class.)
Related
In Objective-C one can make a singleton that does not have a sharedInstance or similar class call simply by making the -init method reference the status singleton variable, like so
static MyObject *sharedObject;
/*
* The init will return the actual singleton instance if called directly.
* The first time called it will create it and intialize it.
*/
- (instancetype)init
{
static dispatch_once_t once;
dispatch_once(&once, ^{
id myself = [super init];
if (nil != myself) {
[self initialize];
sharedObject = myself;
}
});
return sharedObject;
}
So a user could call this MyObject *myObject = [[MyObject alloc] init]; as many times as he wanted and would get the same object back each time. But it is not obviously, from syntax, a singleton.
I am trying to get a similar functionality in Swift, where I can return the same object each time (an NSObject subclass) but so that it is not obviously a singleton.
I would call it var myObject = MyObject() or when bridging to Objective-C as above but they would all reference the same object.
I am familiar with the normal sharedInstance method of singleton in Swift.
Suggestions on how to do this would be appreciated.
This is not the same as the dispatch_once in Swift answers as that still uses a sharedInstance
In Objective-C an initialiser is just like any other method that is called on an instance
[[alloc SomeClass] init]
You first alloc an instance and then explicitly invoke its initialiser.
init is able to return any object; returning self is just a convention that can be ignored in special cases, such as the one you have shown.
In Swift, init is special. An initialiser is invoked implicitly as part of the allocation
let x = SomeClass()
A Swift init implicitly returns self (or it can return nil in the case of failable initialiser that has failed). As a result, you cannot implement a "hidden singleton" in Swift by returning some other object.
I think you can do something similar to what you're looking for using Objective-C's associated objects. You can see a blog post about how to use it in Swift here: http://en.swifter.tips/associated-object/
I don't really understand the purpose of this though, necessarily- I think it would be desirable to make a singleton look like a singleton.
You can technically use these associated objects to create a function that always returns the same associated object, eg, func giveMeTheSameObjectEveryTime() -> AssociatedObjectType, which would be similar in syntax to init() -> AssociatedObjectType, but I think you're getting a similar effect to a singleton, since you'll have to create some boilerplate variables to hold the association, which is quite a bit more work than a simple static let sharedInstance property.
I have some bluetooth class that needs to be alive during all views .
That means, that i have to call functions in this class from different views, and ALSO get delegates from this class to different views .
So , i have to initialise it once to create connection, than later, i have to use it again from different views(classes) and register to get notifications from it.
I was thinking about a singleton, that HE will create an instance of that bluetooth class, and i can access him from anywhere .
But, i would also like that any view can get delegates from it .
How would i do that ?
i have read What should my Objective-C singleton look like?
But maybe singleton is not what i need ?
How can you create a class to always be alive, and register to get delegates from it from anywhere ?
(how can it be done with app delegate class ? )
I have had the similar query a while back
Problem : Multiple Classes need to receive delegate calls from single instance
Solution: I used a combination of sharedInstance , delegates and NSNotifications to handle the problem
SharedInstance
+ (SomeBluetoothClass *) sharedInstance {
static dispatch_once_t once;
static SomeBluetoothClass *sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Delegate
#property (weak, nonatomic) id <SomeBluetoothClassDelegate> delegate;
Since delegate can respond to only one class at a time. Assign class in focus based on your logic. Then whenever you want send info to all send it across using NSNotificationCenter from the sharedInstance. Send the info through using userInfo dictionary of NSNotifications
Notifications
[[NSNotificationCenter defaultCenter] postNotificationName:SomeBluetoothClassNotification
object:self
userInfo:info];
Model the structure of SomeBluetoothClass to be thread safe and handle all notifications along with the delegates and it should work fine.
Have a lots way for your situation. Firstly, you should understand that creating object is not too heavy.
So if you want to use Delegate, you can create a Factory method
Ex:
+ (instancetype)bluetoothManagerWithDelegate:(id<delegate>)delegate {
return [self alloc] initWithDelegate:delegate];
}
So that you also don't care about conflict of concurrence. Because you have separate Bluetooth class.
If you still want to use Singleton, in this situation, it depends on how many object you want to notify.
Only 1 views, just use delegate, and set new delegate when you present new view.
More than one, you can use NSNotificationCenter or Observer, you can google these keywords, it have a lot of tutorial and document on the internet help you use it.
I think you can create NSMutableArray in your singleton with links on your views and call someMethod for all objects when is needed. Don't forget remove views from array when its don't need anymore. That is simple realization of pattern called "Observer".
You need to create a class that should be allocated memory once in a lifetime
I am posting a small code snippet which can help you.
In your .m file
#pragma mark - Shared Instance
static BlootoothClass *_sharedblootoothclass = nil;
+ (BlootoothClass *) sharedClass {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedblootoothclass = [[self alloc] init];
// DO YOUR STUFF TO INTIALISE YOUR CLASS
});
return _sharedblootoothclass;
}
in Your .h file
+ (BlootoothClass *) sharedClass
dispatch_once is the queue with dispatch the instance of your class one in a lifetime and you can access its function all over in the app any time.
Now to get any data from it you can get it from instance from any where like
[BlootoothClass sharedClass].anyObject
And you also can send post notification from here in any of its function
- (void)detectedBlootoothdevice{
[[NSNotificationCenter defaultCenter] postNotificationName:#"newdevicedetected" object:nil];
}
You should not use delegates as you cant call same delegate function at multiple class because last delegate get overwritten.
I havea Utility class that uses class methods. I am trying to refer to self in the class method but can't. I was wondering how would I declare the following in a class method:
[MRProgressOverlayView showOverlayAddedTo:self.window animated:YES];
self.window it says member reference type struct objc_class *' is a pointer; maybe you meant to use '->'
Another problem that relates to not being able to call self is how would I refer to a declared #property in my .h in a class method in my .m.
Here is my class method:
.m
+ (void)showHUD
{
[UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
[MRProgressOverlayView showOverlayAddedTo:self.window animated:YES];
//I would preferably like to call my property here instead
}
.h
#property (nonatomic) MRProgress * mrProgress;
The whole point of a class method is that it is not part of a specific instance. Inside of a class method, self is the class.
If you need to be tied to a specific instance, then it should be an instance method. If you want a static method that accesses a specific instance, then pass that instance (self) to it (though it's hard to imagine many cases where that makes sense).
In the above example, showHUD should be an instance method almost certainly. If that doesn't make sense for some reason, then it should be:
+ (void)showHUDForWindow:(UIWindow *)window;
You can then call it as showHUDForWindow:self.window and use that as needed.
You can use a singleton pattern. Singleton pattern assumes that the only instance of your class exists. Since it's the only instance, you can then use it from class methods.
Example implementation:
+ (MyClass*)sharedInstance {
static dispatch_once_t once;
static MyClass *sharedMyClass;
dispatch_once(&once, ^ {
sharedMyClass = [[self alloc] init];
});
return sharedMyClass;
}
Then you can access the shared instance via [MyClass sharedInstance], for example:
+ (void)doSomethingCool {
[[self sharedMyClass] doSomething];
}
I have a class where I keep utility methods; one of those methods takes the values in some textboxes stored in a ViewController and saves those values to a plist.
The problem is the utility methods class is not a ViewController and therefore I can't "hook up" the outlet properties of the textboxes tothe Utility class.
Is there a way I can pass the ViewController as a parameter to the Utility class method?
Just make the utilities class a Singleton inheriting just from NSObject. That way you can easily access the methods wherever you'd like and you'll only have one instance of it.
https://developer.apple.com/library/ios/documentation/general/conceptual/DevPedia-CocoaCore/Singleton.html
Matt Gallagher wrote a great helper file to create Singletons. Check it out here:
http://www.cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html
If these utility methodes are class methods use a singleton. Something like this:
+ (__CMMotionManager__ *)__sharedMotionManager__ {
static __CMMotionManager__ *shared = nil;
if (!shared) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ // all threads will block here until the block executes
shared = [[__CMMotionManager__ alloc] init]; // this line of code can only ever happen once
});
}
return shared;
}
(it's my CoreMotionManager snippet)
I have my main app delegate
I have a few UIViewController derived instances driven by a Storyboard
Say I'd like to provide a centralized persistence layer for my application - perhaps Core Data of SQLite. Where would I put those objects? I'm missing some centrally accessible "Application" class you can access from all the UIViewController instances.
Is there a pattern to follow here?
you should check the singleton pattern:
In software engineering, the singleton pattern is a design pattern
that restricts the instantiation of a class to one object. This is
useful when exactly one object is needed to coordinate actions across
the system. The concept is sometimes generalized to systems that
operate more efficiently when only one object exists, or that restrict
the instantiation to a certain number of objects. The term comes from
the mathematical concept of a singleton.
here is a source for a example implementation: What should my Objective-C singleton look like?
and here is the direct link for the modern solution:
https://stackoverflow.com/a/145395/644629
What you're describing is your model layer. There are two main ways to manage the model:
At application startup, create the main model object and hand it to the first view controller.
Make the main model object a Singleton.
The "main model object" in both cases is generally some kind of object manager. It could be a document, or it could be a PersonManager if you have a bunch of Person objects. This object will vend model objects from your persistence store (generally Core Data).
The advantage of a Singleton here is that it's a little easier to implement and you don't have to pass around the manager. The advantage of a non-Singleton is that it's easier to have more than one (for a document-based system), and it's easier to test and reason about non-singletons than singletons. That said, probably 80% of my projects use a singleton model manager.
As a side note, that you appear to already understand: never store the model in the application delegate, and never use the application delegate as a "rendezvous point" to get to the model. That is, never have a sharedModel method on the application delegate. If you find yourself calling [[UIApplication sharedApplication] delegate] anywhere in your code, you're almost always doing something wrong. Hanging data on the application delegate makes code reuse extremely difficult.
Go with a singleton pattern, which has scope of application lifetime.
#interface DataManager ()
#end
#pragma mark -
#implementation DataManager
#pragma mark - Shared Instance
static DataManager* sharedInstance = nil;
#pragma mark - Singleton Methods
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
+ (DataManager*)sharedInstance
{
#synchronized([DataManager class])
{
if (!sharedInstance) {
//[[self alloc] init];
sharedInstance = [[DataManager alloc] init];
}
return sharedInstance;
}
return nil;
}
+ (id)alloc
{
#synchronized([DataManager class])
{
NSAssert(sharedInstance == nil, #"Attempted to allocate a second instance \
of a singleton.");
sharedInstance = [super alloc];
return sharedInstance;
}
return nil;
}
#end
Declare your properties in .h file and synthesize them here in .m file.
To use that property just call:
// set value
[[DataManager sharedInstance] setSharedProperty:#"ABC"]; // If its a string
// get Value
NSLog(#"value : %#", [[DataManager sharedInstance] sharedProperty]);
Hope this is what you required.
Enjoy Coding :)