Im doing a small test project with SocketRocket on ios. But i can't seem to wrap my head around the logic.
Here's the thing: I have need to have a sort of "global" function to call the sockets. When my app opens it should connect using the websockets.
_webSocket.delegate = nil;
[_webSocket close];
_webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"ws://localhost:12345/connectr"]]];
_webSocket.delegate = self;
self.title = #"Opening Connection...";
[_webSocket open];
However, i need to get the logic on connecting to a delegate function. I already thought of a singleton but i read that the singleton functions are quite cpu expensive.
So basically my question is:
What is the best way to initiate a global accesable function that uses the (appdelegate) initalized SocketRocket instance.
You can use a singleton without trouble. Really. It's way better than making your AppDelegate with 50000 LOC. Also, your AppDelegate should know only about app events, not sockets.
I don't know how you assume singletons are cpu expensive. The only expense of singleton is lazily initialising the object once in the first call.
In the other hand, singleton pattern is usually considered a bad practice because of accessing an object statically because you are referring the singleton class instead of a reference to the instance. But it's certainly better to use a singleton instead of accessing the app delegate.
you declare variable in appdelegate with property and synthesis
you import appdelegate class in your requirement class
AppDelegate *objappdel=(AppDelegate*)[[UIApplication sharedApplication]delegate];
objappdel.variablename;
Related
I have doubts regarding the creation of singleton class in Objective-C/iOS.
Where ever I see the trick to create a singleton class in objective-C is this code
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
Whenever I call [MyManager sharedManager] of course I get the same address. However, I can also write [MyManager new] in which case the address is different.
1.Isn't the concept of singleton class is that it restricts the instantiation of a class to one object?
2.If we can create another object its not a singleton anymore, is it?
In my iOS app I tried [UIApplication new]. I got an exception in runtime. Now this I get. You cannot make another instance of UIApplication since its a singleton class.
So why the use of shared instance considered to be the way of creating a singleton class or have I got this all wrong?
The sharedManager is the convenience method you'd use to access the singleton instance. While this doesn't guarantee that there will be only one instance of that manager over the app, if everyone is using sharedManager then there will practically exist only one instance of that manager.
This kind of singletons are singletons by convenience, not by implementation. You should use them, for multiple reasons:
you can unit test them, by calling alloc init in your unit tests and making use of that brand new allocated object
it makes your life easier if decide to later refactor the manager and no longer use it as a singleton if you consider it from the begging like a regular object to work with
Of-course, you can make a singleton by-the-book by overriding the init and allocWithZone: to either return the only instance or by raising an exception, however I'm not sure they'd worth the effort.
There's a very good tech talk regarding singletons held by Misko Hevery in the Google clean code talks playlist, the link to the video: here. This kind of singletons are referred as lower case S singletons, not capital S ones in the video, and Misko explains very well why they are preferred.
It doesn't break singleton concept. You choose your way to implement what you want. If you want to create only singleton instance, you can make run error by override init function:
[NSException exceptionWithName:NSInternalInconsistencyException
reason:#"bla bla bla..." userInfo:nil];
or
you can override it to force return to shared instance.
Of course, you can. But it not recommend if you are using singleton.
Objective-C uses a pragmatic approach. Your +sharedManager method returns a singleton. If someone is stupid enough to call [SingletonClass new] or [[SingletonClass alloc] init], that's their problem. They'll get what they deserve. There is no reason to prevent people from shooting themselves in the foot if that is what they want to do.
There are millions of programming errors that people can make and that the developer of a class or the compiler cannot prevent. No point wasting effort on preventing this particular error.
I have a single ton which is working fine, but i don't want to use singleton instead any alternative best way
find my code for reference
Myclass.h
+ (instancetype)shareInformation;
Myclass.m
+ (instancetype)shareInformation
{
static Myclass *manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[Myclass alloc] init];
});
return manager;
}
MyNextClass.m
[[Myclass shareInformation] methodofMyclass:^(NSDictionary *results, NSError *error) {
//my code
}];
i have a class Myclass in which i am using a singleton to init manager = [[Myclass alloc] init]; and i am calling this in other class MyNextClass but i don't want to do this in this way i mean i don't want to use singleton pattern i need some this alternative for what i do here
I'm guessing you want to avoid using the singleton as it's considered an anti-pattern.
A solution would be to use a dependency injection container to wire up your application and configure it to resolve your object as a single instance.
I'm not familiar with ios development but Typhoon looks like popular choice.
You can use a singleton or you can use a normal instance, it's up to you. One of the major benefits of a singleton is so that you can get a reference to it anywhere without difficulty.
You could always create a class, and pass a reference of it anywhere you want to use it. For example in your view controller you create it, make sure you create a property of it in your following view controllers and then pass that same reference to the new view controller.
It's best to use a singleton if that's what you're trying to accomplish and you only need one instance though.
Another option, for "global" data, is to make use of the AppDelegate. You can place simple properties in the AppDelegate itself, or define a property (or explicit "getter" method) which returns a pointer to some more complex "global" object.
Note that using the AppDelegate this way is considered "bad form" by many, but there's really not that much bad about it, other than accessing the AppDelegate itself is a bit awkward. (And it upsets the sensibilities of those who are sure they know what "separation of concerns" really means.)
I've been thinking about using a singleton on my data class in my current app. I've also been thinking of reasons not to use the pattern and currently I am stuck in the middle.
The reason I am for the singleton in this case is due to accessibility to methods and properties easily that I need to use more than once throughout the app. I could use the appDelegate for this but that muddles up the area of concern as these methods / variables have nothing to do with the app state - more to do with user input. The data will be persisted with eventually with NSUserDefaults - which is a singleton already.
The reason I am against it is because its another singleton to an app that already bass one (The appDelegate)
My question:
Would using another Singleton to access the data model be the correct way / acceptable way of doing it - or should I look at another approach?
I personally think there would be nothing wrong with a singleton as a data model - using the app delegate to instantiate it when the app starts and then access its various methods / properties when I need them throughout the app. This would be the only other singleton in the app (Maybe another one for user management - e.g.; logging in / out / profile / credentials, etc? )
Any thoughts?
Thanks all!
There is no problem having multiple singleton classes within ios, in fact in many of my projects most of the classes are singletons. Normally I have the data access logic and control within a singleton and then actual object classes as instances.
As you have already identified you really do not want to be putting something into AppDelegate that does not apply to the whole app.
From my point of view do not instanciate the class from AppDelegate, simply have the class instanciate itself on first access.
Whenever I am explaining singleton Objective-C to people I always direct them to this site, it may be worth a view for you:
http://www.galloway.me.uk/tutorials/singleton-classes/
It explains only what you need in a really easy to understand way. The bit that does the 'self-instanciating' is this bit:
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
You could use singleton in these case. Don't use delegate to hold values for your app. You may use same singleton for user management also.
Note : Don't use globals unless you need to do so. Singletons and top-level data should be used only when the data they contain truly belongs at the top level.
I've got a test project to use the private data object on several view controller.
(I've downloaded it from web & git-hub)
- (ExampleAppDataObject*) theAppDataObject;
{
id<AppDelegateProtocol> theDelegate = (id<AppDelegateProtocol>) [UIApplication sharedApplication].delegate;
ExampleAppDataObject* theDataObject;
theDataObject = (ExampleAppDataObject*) theDelegate.theAppDataObject;
return theDataObject;
}
First question is, theDelegate was casted with AppDelegateProtocol, even this applications UIApplication delegate name was ViewControllerDataSharingAppDelegate, and there's no warning. I can't under stand why, maybe it's because that was a id type?
(AppDelegateProtocol is a custom delegate protocol he declared in the AppDelegate.)
Second, it shows this kind of code on every view controller, and it seems like just a single-ton pattern.
I don't think this is not the best way to transfer data between view controller.
Which is the best way to transfer object data type?
Thanks.
Creating a protocol decouples the code somewhat from the specific implementation. You could conceivably have several applications, each of which uses its own custom class as an app delegate, but all implementations conform to the AppDelegateProtocol.
I used to use the app delegate to hold global data and methods a lot when I first started in iOS.
However, that fills your app delegate with app-specific code.
I've shifted away from that approach recently, and use a data container singleton (and perhaps a utility methods singleton as well.) As is typical for a singleton, I define a class method that lets me fetch the singleton. I add properties to my singleton as needed to store data, and then just use the class method to get a pointer to the singleton. I write my class method to lazy load the singleton.
Its also easy to make your data container singleton persistent by making it conform to NSCoding. Then every time you get moved to the background, just save your singleton somewhere. On app launch, read it in.
I'm creating a wrapper class for an existing singleton class. Since I'll be accessing the singleton several times, I'd like to store it as an ivar in my wrapper class...
#interface WrapperClass ()
#property (nonatomic, strong) SingletonClass singletonObj;
#end
...so that I don't have to constantly write [[SingletonClass sharedInstance] methodName]. Instead I can write [singletonObj methodName]. It just feels cleaner to me.
I'm new to iOS development, so I'm wondering if there's anything fundamentally wrong with this approach.
Also, with ARC, should I be storing the singleton with a strong reference?
Unless your doing something crazy the likelihood is the extra retain/release should cause no issue.
Therefore there is no real issue with storing it in an ivar...
A better reason for doing this would not be to save your typing but to improve the testability /reusability of the class. By making it an ivar it allows you to inject a different class in to change the behaviour.
I would consider making an accessor that will by default give me the singleton but still allow me to inject a different class if I choose like this
- (SingletonClass *)singletonObj;
{
return _singletonObj = _singletonObj ?: [SingletonClass sharedInstance];
}
Update:
It's also worth thinking about "why would you make using this singleton different from using an ivar?". If you use it throughout your class like it was an ivar then why do you access it in a completely different way?
For example often when I use a managedObjectContext there is only one in my whole app. A lot of people use the app delegate as a singleton and access it that way but I prefer to pass it along as an ivar. Conceptually the managedObjectContext is just another object that I am using like any other ivar so why should I have to mentally switch how I access it?
This is bad
[(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
Good
self.managedObjectContext;
This now gives me two advantages.
If my class is littered with calls to [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; then it is hard to rip it out of this project and place it in another without a risky search and replace. If I access the singleton in one place the "accessor" then I only have one place to change the code.
In my production app I probably want my data to be persistant so I would give the object access to a managedObjectContext with a persistant store, whereas in my tests I don't want state to be persisted between tests so I would give the object a non persistant store instead.
It makes sense.
Just initialize your singleton and store it in the ivar.
That said, your code is actually defining a property, which is not the same thing of an ivar.
For instance you could define your singleton i var like follows
#implementation WrapperClass {
SingletonClass * _singleton;
}
and then initialize the singleton in the default constructor
- (id)init {
self = [super init];
if (self) {
//...
_singleton = [SingletonClass sharedInstance];
//...
}
return self;
}
You can just define a macros, like this:
#define _SINGLETON(method) { [[SingletonClass sharedManager] method]; }
Then you can use it in your code like this:
_SINGLETON(methodName);
You can define this macros in the SingletonClass.h, and then you will have possibility to use it anywhere, there your header is imported.
This way you don't need to think about iVars.