In my app I have Singleton object, which should save its state through app launches. So I need to save it somehow.
I see only two options: 1) save it on app termination (plus, maybe, going background); 2) save it each time any property changed.
First option looks bad, because app can be killed, for example, because of some bug, memory limits or device power-off (low battery). So I expect state won't be saved.
Second option needs either manual notifications about each change, or KVO + observing of each property.
Seems that I do something wrong here. Maybe, you can give me some advice or there is some well-known pattern (I've tried to google, but found nothing particular).
UPDATE:
Yes, there is NSUserDefaults, but to improve its usability (smth. more than just key-values) I would write wrapper-methords, so I will end with the same problem (lines of manual coding).
UPDATE2:
CoreData is also bad choice for me: just one object to store + inserting there also needs some more lines of code.
UPDATE3:
It's not a question about "how to save". It's about "how to call this saving automatically (or with less of coding)". So in NSUserDefault way we need to manually implement each property as wrapper. In NSCoding - call save or post notification (to catch & save from one place) from each property also.
The simplest way to save user states in iOS is through NSUserDefaults.
Here is an example which keeps track of all changed made to your singleton:
#interface MySingleton : NSObject
{
}
+ (MySingleton *)sharedSingleton;
#property (copy) NSString *userName;//the variable to track
#end
#implementation MySingleton
#synthesize userName;
+ (MySingleton *)sharedSingleton
{
static MySingleton *sharedSingleton;
#synchronized(self)
{
if (!sharedSingleton)
sharedSingleton = [[MySingleton alloc] init];
return sharedSingleton;
}
}
- (void)setUserName:(NSString*)userName
{
//update the variable
self.userName = userName;
//saves the new value to NSUserDefaults
[[NSUserDefaults standardUserDefaults] setObject:userName forKey:#"userName"];
//forces instantaneous synchronization, not needed, would be updated after a periodic interval anyways
[[NSUserDefaults standardUserDefaults] synchronize];
}
#end
Optionally you can implement the NSCoding protocol and save the whole class to NSUserDefaults, take a look at this question.
I think the first option is the better way to do it. The OS always informs the app when it will be killed for example for memory warnings the didReceiveMemoryWarning method will be called where you can save the states to the singleton object. (Device power off is same as go to background so the applicationWillEnterForeground method will be called).
Related
I have a class with a property
#property (nonatomic) double* myDoubles
This property has 3 doubles in it
myDoubles[0]; //0.02
myDoubles[1]; //0.42
myDoubles[2]; //0.99
If the values change, I'd like the following method to be called
[self setNeedsDisplay];
I tried using FBKVOController, but that didn't work..
_observer = [FBKVOController controllerWithObserver:self];
[_observer observe:self
keyPath:#"myDoubles"
options:NSKeyValueObservingOptionNew
action:#selector(setNeedsDisplay)];
I don't want to start an NSTimer and just check for changes.
This is not possible.
Notifications work because the code making changes does so through some method that knows to notify listeners of the change. If that same code were simply to write to the memory location backing the data, the notification would never be triggered.
What you want to do is simply declare a memory location that code will write to; no notification can happen from this (unless you have very system-dependent support making it possible - a memory watchpoint - and then your question changes significantly. Such support, when available, is very limited and not of good generic value).
I read somewhere that if i have delegates in my app, i should keep a weak reference to them
however, when i debug the app, the app doesnt want to move on, when i call on a delegate
because my delegate has already been deallocated by the time it reached that method
why ?
If i put the reference to be "strong" everything works just fine, though i am not sure what are the consequences of that on my memory allocations and the fact that those delegates are not in "sharedInstance" classes....
code:
#interface LoginProcessListener()
#property (nonatomic,weak)id<UserSettingsDelegate>userSettings;
#property (nonatomic,weak)id<DisclaimerDelegate>disclaimerDelegate;
#end
#implementation LoginProcessListener
-(instancetype)initWithUserSettings:(id<UserSettingsDelegate>)userSettings andDisclaimerDelegate:(id<DisclaimerDelegate>)disclaimerDelegate{
self = [super init];
if (self){
[self setUserSettings:userSettings];
[self setDisclaimerDelegate:disclaimerDelegate];
}
return self;
}
-(void)onLoginAuthenticationProcessFinished{
User *user = [_userSettings getUserDetails];
if(user && [_disclaimerDelegate isConfirmedDisclaimer:[user disclaimerInfo]]){
[_disclaimerDelegate confirmedDisclaimer];
}else {
[_disclaimerDelegate needDisplayDisclaimer];
}
}
-(void)onLoggedInUserDetailsReceived:(User *)user{
[_userSettings saveUserDetails:user]; <== here my _userSettings is already nil;
}
when i debug the app, the app doesnt want to move on, when i call on a delegate because my delegate has already been deallocated by the time it reached that method
But that is your bug, which you must track down. The whole point of a delegate is that you must not permit it to die before the thing whose delegate it is. In general, if a delegate dies before the other thing does, you are doing something wrong; it is the job of a delegate to live as long as it is needed.
On the other hand (there is always an "other hand") it may be that what you are calling a delegate is not really a delegate. It is a delegate more or less if it is an object with a primary existence of its own. If it's just a packet of values or a purely ancillary object whose only purpose is in connection with the object keeping a reference to it, then it is not a delegate and a strong reference is correct.
Yours architecture is wrong. It's should be:
#interface UserSettings
#property (nonatomic,weak)id<UserSettingsDelegate>userSettingsDelegate;
#end
#interface Disclaimer
#property (nonatomic,weak)id<DisclaimerDelegate>disclaimerDelegate;
#end
Actually yours userSettings not real delegate, it just member of LoginProcessListener, so you may use strong references.
Commonly id<UserSettingsDelegate> creates UserSettings and own reference on it. If UserSettings will own reference at id<UserSettingsDelegate, then there will be retain loop.
when i debug the app, the app doesnt want to move on, when i call on a
delegate because my delegate has already been deallocated by the time
it reached that method
What's your seeking is how a weakly defined property behaves.
Via the docs: https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html#/apple_ref/doc/uid/TP40011210-CH5-SW30)
Because a weak reference doesn’t keep an object alive, it’s possible for the referenced
object to be deallocated while the reference is still in use. To avoid a dangerous
dangling pointer to the memory originally occupied by the now deallocated object, a weak
reference is automatically set to nil when its object is deallocated.
Simply put, if the delegate is no longer allocated, it's being released elsewhere.
With that said, your bug is likely not there at all, but elsewhere. You're going to have to backtrace _userSession to verify where it's being created and what objects have strong references to it.
Using a strong reference to a delegate is permissible, but you need to understand what is going on as it has risks that you should be aware of.
Apple's documentation kind of glosses over this, just saying that delegate users keep a weak link to the delegate, and in general this is true, but there are cases, and yours may be one of them, where it makes sense to keep a strong reference. In general, this happens in asynchronous code where the delegate might otherwise be released before it is used.
Too much hand waving: here is a concrete example. NSURLConnection needs a delegate to do asynchronous IO. In order to make this reliable and to greatly simplify it's usage, NSURLConnection keeps a strong reference to it's delegate as long as it needs one. Here is a quote from the NSURLConnection documentation :-
"Note: During a request, the connection maintains a strong reference to its delegate. It releases that strong reference when the connection finishes loading, fails, or is canceled"
In simple terms, under ARC, "releases that strong reference" probably means setting the property to nil.
Summary: If you know what you're doing, use strong references when you have to, and document well so that the next person to see that code understands why you did it.
You can temoprarily make a strong reference to the delegate object, which is excatly what NSURLConnectionDelegate protocol does. I do it like this:
Let's say i have a protocol for downloading images.
#implementation AsyncImageLoadManager <NSURLConnectionDelegate>
static char delegateStrongReferenceKey;
.......
-(void)startDownload {
....
objc_setAssociatedObject(self, &delegateStrongRefernceKey, _delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
_imageConnection = [NSURLConnection connectionWithRequest:request delegate:self];
objc_setAssociatedObject(self, &delegateStrongRefernceKey, _delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
_downloadTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ //I use tihs instead of [connection start]; so that download continues if app goes to background
[_imageConnection cancel];
[[UIApplication sharedApplication] endBackgroundTask:_downloadTaskID];
_downloadTaskID = UIBackgroundTaskInvalid;
objc_setAssociatedObject(self, &delegateStrongRefernceKey, nil, OBJC_ASSOCIATION_ASSIGN);
}];
}
..../// and in connectionDidFinishLoading and connectionDidFailWithError you release the strong reference with:
[[UIApplication sharedApplication] endBackgroundTask:_downloadTaskID];
_downloadTaskID = UIBackgroundTaskInvalid;
objc_setAssociatedObject(self, &delegateStrongRefernceKey, nil, OBJC_ASSOCIATION_ASSIGN);
I made a class, called Timer. Its designated initializer starts a timer with a value in seconds. It works great. However I am having trouble updating the controller w/e the timer ticks.
Right now, for every tick I am sending a NSNotificationCenter with a userInfo that is a simple dictionary with the current time, which does not sound the best way to do it...
NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:self.timerCount] forKey:#"timerCount"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"TimerCountChanged"
object:self
userInfo:dict];
Should I be using some other technique or am I doing it the right way?
Thank you in advance!
EDIT:
I need to initialize different Timers, using different values. I tried to use Delegates, but I only had one method in my controller to update the UI for all those Timers!
Would it be bad if I do something like? Passing a UIButton to my Model also does not seem to be the best solution but it works.
-(void)timer:(Timer *)timer didTriggerAt:(NSTimeInterval)time andButton:(UIButton *)button
{
[button setTitle:[NSString stringWithFormat:#"%.0f", time] forState:UIControlStateNormal];
}
- (IBAction)startCountDown:(UIButton *)sender
{
self.timer1 = [[Timer alloc] initWithTimeInSeconds:10 andButton:sender];
self.timer1.delegate = self;
}
I have 3 Timers in my MainView, the user can start them whenever he wants. They can also have different times, which is also defined by the user.
Sending Notifications is good, but you may not observe it as in regular time.
Sometimes it gets delayed and you may observe them in irregular time interval.
You can use
Delegate Pattern.
Call method by selector
EDIT:
From
Apple documentation on Performance CodeSpeed on Notifications.
The fewer notifications you send, the smaller the impact on your
application’s performance. Depending on the implementation, the cost
to dispatch a single notification could be very high. For example, in
the case of Core Foundation and Cocoa notifications, the code that
posts a notification must wait until all observers finish processing
the notification. If there are numerous observers, or each performs a
significant amount of work, the delay could be significant.
If you only have one client object for each Timer instance, then you should use the delegate pattern. You would define a TimerDelegate protocol with a method that a Timer object can call whenever the timer ticks.
e.g.
#class Timer;
#protocol TimerDelegate
- (void) timer:(Timer *)timer didTriggerAt:(NSTimeInterval)time;
#end
#interface Timer
...
#property (assign) id<TimerDelegate> delegate;
...
#end
If you indeed require multiple listeners each time a Timer instance ticks, then the NSNotificationCenter approach would be a better fit. Instead of passing info in the userInfo dictionary, I probably would expose an #property on Timer called currentTime, so that when a client object gets the notification, they could simply access currentTime on the notifying Timer, instead of (IMO clunkily) reading data out of userInfo.
I have an application that downloads information from a web service and caches it in memory. Specifically, my singleton cache class contains an instance variable NSMutableDictionary *memoryDirectory which contains all of the cached data. The data in this cache can be redownloaded easily, so when I receive a UIApplicationDidReceiveMemoryWarningNotification I call a method to simply invoke
- (void) dumpCache:(NSNotification *)notification
{
memoryDirectory = nil;
}
I’m a little worried about the thread safety here. (I’ll admit I don’t know much about threads in general, much less in Cocoa’s implementation.) The cache is a mutable dictionary whose values are mutable dictionaries, so there are two levels of keys to access data. When I write to the cache I do something like this:
- (void) addDataToCache:(NSData *)data
forKey:(NSString *)
subkey:(NSString *)subkey
{
if (!memoryDirectory)
memoryDirectory = [[NSMutableDictionary alloc] init];
NSMutableDictionary *methodDictionary = [memoryDirectory objectForKey:key];
if (!methodDictionary) {
[memoryDirectory setObject:[NSMutableDictionary dictionary] forKey:key];
methodDictionary = [memoryDirectory objectForKey:key];
}
[methodDictionary setObject:data forKey:subkey];
}
I’m worried that sometime in the middle of the process, dumpCache: is going to nil out the dictionary and I’m going to be left doing a bunch of setObject:forKey:s that don’t do anything. This isn’t fatal but you can imagine the problems that might come up if this happens while I’m reading the cache.
Is it sufficient to wrap all of my cache reads and writes in some kind of #synchronized block? If so, what should it look like? (And should my dumpCache: be similarly wrapped?) If not, how should I ensure that what I’m doing is safe?
Instead of using an NSMutableDictionary, consider using NSCache, which is thread safe. See this answer for example usage. Good luck!
I have a question about thread safety of the following code example from Apple (from GameKit programming guide)
This is to load achievements from game center and save it locally:
Step 1) Add a mutable dictionary property to your class that report achievements. This dictionary stores the collection of achievement objects.
#property(nonatomic, retain) NSMutableDictionary *achievementsDictionary;
Step 2) Initialize the achievements dictionary.
achievementsDictionary = [[NSMutableDictionary alloc] init];
Step 3) Modify your code that loads loads achievement data to add the achievement objects to the dictionary.
{
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error)
{
if (error == nil)
{
for (GKAchievement* achievement in achievements)
[achievementsDictionary setObject: achievement forKey: achievement.identifier];
}
}];
My question is as follows - achievementsDictionary object is being modified in the completion handler, without any locks of sort. Is this allowed because completion handlers are a block of work that will be guaranteed by iOS to be executed as unit on the main thread? And never run into thread safety issues?
In another Apple sample code (GKTapper), this part is handled differently:
#property (retain) NSMutableDictionary* earnedAchievementCache; // note this is atomic
Then in the handler:
[GKAchievement loadAchievementsWithCompletionHandler: ^(NSArray *scores, NSError *error)
{
if(error == NULL)
{
NSMutableDictionary* tempCache= [NSMutableDictionary dictionaryWithCapacity: [scores count]];
for (GKAchievement* score in scores)
{
[tempCache setObject: score forKey: score.identifier];
}
self.earnedAchievementCache= tempCache;
}
}];
So why the different style, and is one way more correct than the other?
Is this allowed because completion handlers are a block of work that will be guaranteed by iOS to be executed as unit on the main thread? And never run into thread safety issues?
This is definitely not the case here. The documentation for -loadAchievementsWithCompletionHandler: explicitly warns that the completion handler might be called on a thread other than the one you started the load from.
Apple's "Threading Programming Guide" classifies NSMutableDictionary among thread-unsafe classes, but qualifies this with, "In most cases, you can use these classes from any thread as long as you use them from only one thread at a time."
So, if both apps are designed such that nothing will be working with the achievement cache till the worker task has finished updating it, then no synchronization would be necessary. This is the only way in which I can see the first example as being safe, and it's a tenuous safety.
The latter example looks like it's relying on the atomic property support to make the switcheroo between the old cache and the new cache. This should be safe, provided all access to the property is via its accessors rather than direct ivar access. This is because the accessors are synchronized with respect to each other, so you do not risk seeing a half-set value. Also, the getter retains and autoreleases the returned value, so that code with the old version will be able to finish working with it without crashing because it was released in the middle of its work. A nonatomic getter simply returns the object directly, which means that it could be deallocated out from under your code if a new value were set for that property by another thread. Direct ivar access can run into the same problem.
I would say the latter example is both correct and elegant, though perhaps a bit over-subtle without a comment explaining how crucial the atomicity of the property is.