Setup UILocalNotification with information from another object in applicationDidEnterBackground - ios

I'm making an app that is essential a timer (counts down to zero).
I have a class tracking the time, left to zero. Lets call it TimeBack.
When the user sends the app to the background via applicationDidEnterBackground, i would like to setup a UILocalNotification with a fireDate of data+timeBack.
How do i get the information from a object, to my AppDelegate so i can configure a localNotification based on the state of an object?

You can create a singleton by exposing a class method and using the dispatch_once method to make sure it only gets created once.
Like so:
+ (id)sharedInstance
{
static myObject *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
});
return shared;
}

Related

Reset singleton instance to nil after each test case

I am using OCMock 3 to unit test my iOS project.
I use dispatch_once() created a singleton class MyManager :
#implementation MyManager
+ (id)sharedInstance {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
I have a method in School class which uses the above singleton:
#implementation School
...
- (void) createLecture {
MyManager *mgr = [MyManager sharedInstance];
[mgr checkLectures];
...
}
#end
Now, I want to unit test this method, I use a partial mock of MyManager:
- (void) testCreateLecture {
// create a partially mocked instance of MyManager
id partialMockMgr = [OCMockObject partialMockForObject:[MyManager sharedInstance]];
// run method to test
[schoolToTest createLecture];
...
}
- (void)tearDown {
// I want to set the singleton instance to nil, how to?
[super tearDown];
}
In tearDown phase, I want to set the singleton instance to nil so that the following test case could start from clean state.
I know on internet, some people suggest to move the static MyManager *sharedMyManager outside the +(id)sharedInstance method. But I would like to ask, is there any way to set the instance to nil without moving it outside +(id)sharedInstance method? (Any solution like java reflection?)
You can't achieve what you want with a local static variable. Block-scoped statics are only visible inside their lexical context.
We do this by making the singleton instance a static variable scoped to the class implementation and adding a mutator to override it. Generally that mutator is only called by tests.
#implementation MyManager
static MyManager *_sharedInstance = nil;
static dispatch_once_t once_token = 0;
+(instancetype)sharedInstance {
dispatch_once(&once_token, ^{
if (_sharedInstance == nil) {
_sharedInstance = [[MyManager alloc] init];
}
});
return _sharedInstance;
}
+(void)setSharedInstance:(MyManager *)instance {
once_token = 0; // resets the once_token so dispatch_once will run again
_sharedInstance = instance;
}
#end
Then in your unit test:
// we can replace it with a mock object
id mockManager = [OCMockObject mockForClass:[MyManager class]];
[MyManager setSharedInstance:mockManager];
// we can reset it so that it returns the actual MyManager
[MyManager setSharedInstance:nil];
This also works with partial mocks, as in your example:
id mockMyManager = [OCMockObject partialMockForObject:[MyManager sharedInstance]];
[[mockMyManager expect] checkLectures];
[MyManager setSharedInstance:mockMyManager];
[schoolToTest createLecture];
[mockMyManager verify];
[mockMyManager stopMocking];
// reset it so that it returns the actual MyManager
[MyManager setSharedInstance:nil];
Here's a full breakdown of the approach.
The answer is no, because you use dispatch_once(&onceToken, ^{ so even if you added another method which could reset the variable to nil you'd never be able to initialise it again.
So you already have one solution and the best solution is to not access the singleton directly (use dependency injection instead).
It is an easier way to solute your issue.
Your class have a singleton. you can add a method that is destroy this class instance. So when you call shareManager method again , it will create a new instance.
Such as:
static MyManager *sharedMyManager = nil;
+ (void)destroy
{
sharedMyManager = nil;
}
As others have stated, what you should really do is refactor your code to use dependency injection. This means that if the School class needs a MyManager instance to operate, then it should have an initWithManager:(MyManager *)manager method which should be the designated initializer. Or if the MyManager is only needed in this particular method, it should be a method parameter, e.g. createLectureWithManager:(MyManager *)manager.
Then in your tests, you could just do School *schoolToTest = [[School alloc] initWithManager:[[MyManager alloc] init]], and each test would have a new MyManager instance. You could drop the singleton pattern entirely, removing the sharedInstance method on MyManager and your application's logic would be responsible to ensure that there is only one instance that you pass around.
But sometimes, you have to work with legacy code that you can't just refactor. In these cases, you need to stub the class method. That is, you need to replace the implementation of -[MyManager sharedInstance] with an implementation that returns [[MyManager alloc] init]. This can be accomplished using the runtime to swizzle the class method, which would be the equivalent of Java reflection that you are looking for. See this for an example of how to use the runtime.
You can also do it with OCMock, which uses the runtime behind the scenes, just like mocking frameworks in Java are based on the reflection API :
MyManager *testManager = [[MyManager alloc] init];
id mock = [[OCMockObject mockForClass:[MyManager class]];
[[[mock stub] andReturn:testManager] sharedInstance];
If you don't want to refactor your code for easier unit testing then there is another solution (not perfect but works):
Create a local property of MyManager type
In setUp instantiate the property from above and swizzle the sharedInstance method with your local method (e.g. swizzle_sharedInstance)
Inside the swizzle_sharedInstance return the local property
In tearDown swizzle back to original sharedInstance and nullify the local property
I suggest a little bit different approach. You can create a mock of your sharedInstance using OCMock:
id myManagerMock = OCMClassMock([MyManager class]);
OCMStub([myManagerMock sharedManager]).andReturn(myManagerMock);
Now School implementation will use myManagerMock object, and you can stub this object to return anything you want under you test case. For example:
OCMStub([myManagerMock someMethodThatReturnsBoolean]).andReturn(YES);
It's important that after your tests, you will perform cleaning of your mock object by calling (at the end of your test method or in -tearDown):
[myManagerMock stopMocking];

A singleton with delegates?

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.

Singleton class static variable set to nil each time

I am making a singleton class for my use . I have seen code for singleton class is like this:
//First Example
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
//Second Example
static SingletonSample *sharedObject;
+ (SingletonSample*)sharedInstance {
if (sharedObject == nil) {
sharedObject = [[super allocWithZone:NULL] init];
}
return sharedObject;
}
The seconds seems fine and understandable. But i am confused in First example where sharedMyManager is set to nil each time and also there is a allocation of shared manager each time, my doubt is that how will first example return the same reference of the class(Singleton).
Thanks.
First of all when static is declared with in function, it is declared only once. So, the line
static MyManager *sharedMyManager = nil;
Will be executed only once when the function gets called for first time.
In the next line when you use dispath_once, it will be executed for only once. So the creation of sharedMyManager will be done once only. So, thats a perfect way to create a single ton class.
As it's static it will initially be set to nil, but in subsequent calls the value will remain to whatever you have set it to in previous calls.
The first example is better as it is thread safe. The second example doesn't even initialise sharedObject which is dangerous (I don't believe there is a guarantee that global variables are initialised to zero).
sharedMyManager is set to nil each time
static variables are set only once.
there is a allocation of shared manager each time
You use dispatch_once, so it's incorrect too.
Read about dispatch_once here.
And using GCD is faster and thread safe.

Accessing method on self from init?

I am using a singleton that I have setup that I am using to both preload and access my audio files (both sfx and music) I started out running [[FGAudio sharedInstance] preload]; from the AppDelegate but was concerned about having to remember to call preload before using the singleton. My question is to make things automatic, can I access a method on the singleton to do my setup and preload in init, or is it not wise to access a method init as things are still starting up?
+ (FGAudio *)sharedInstance {
static FGAudio *sharedAudio = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedAudio = [[FGAudio alloc]init];
});
return sharedAudio;
}
.
- (id)init {
self = [super init];
if(self) {
[self preload];
}
return self;
}
+ (FGAudio *)sharedInstance {
static FGAudio *sharedAudio = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedAudio = [[FGAudio alloc]init];
[sharedAudio preload];
});
return sharedAudio;
}
Referencing the method from init isn't bad if you can guarantee that subclasses won't mess with it or the objects it relies upon and in the future you won't mess up the preloading period by requiring objects that get inited after you call preload. If you use the above snippet you don't even have to worry about any of that and you also get a preloaded singleton.
Calling a method from the init method?
"Yes. Just be very careful (your object may not have been fully initialised, it shouldn't use accessor methods so as to comply with the previous restriction, et cetera)"

Why does Apple recommend to use dispatch_once for implementing the singleton pattern under ARC?

What's the exact reason for using dispatch_once in the shared instance accessor of a singleton under ARC?
+ (MyClass *)sharedInstance
{
// Static local predicate must be initialized to 0
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
Isn't it a bad idea to instantiate the singleton asynchronously in the background? I mean what happens if I request that shared instance and rely on it immediately, but dispatch_once takes until Christmas to create my object? It doesn't return immediately right? At least that seems to be the whole point of Grand Central Dispatch.
So why are they doing this?
dispatch_once() is absolutely synchronous. Not all GCD methods do things asynchronously (case in point, dispatch_sync() is synchronous). The use of dispatch_once() replaces the following idiom:
+ (MyClass *)sharedInstance {
static MyClass *sharedInstance = nil;
#synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [[MyClass alloc] init];
}
}
return sharedInstance;
}
The benefit of dispatch_once() over this is that it's faster. It's also semantically cleaner, because it also protects you from multiple threads doing alloc init of your sharedInstance--if they all try at the same exact time. It won't allow two instances to be created. The entire idea of dispatch_once() is "perform something once and only once", which is precisely what we're doing.
Because it will only run once. So if you try and access it twice from different threads it won't cause a problem.
Mike Ash has a full description in his Care and Feeding of Singletons blog post.
Not all GCD blocks are run asynchronously.

Resources