Synchronized NSKeyedArchiver or NSUserDefaults
I have a singleton delayed-transaction manager class, which is responsible for enqueueing and dequeueing iphone-to-app-server transactions that cannot complete due to a variety of factors (network reac开发者_StackOverflow社区hability, proximity, etc). When reachability/proximity is restored, it attempts to dequeue the the transactions. It is also possible that another transaction would be enqueued at the same time that dequeueing is happening.
My understanding is that NSUserDefaults is a thread-safe wrapper of a mutable dictionary SO link which is exactly what I want. That same SO link opines that NSUserDefaults is for user preferences.These transactions are not user preferences but that's the functionality I want. So, here's the question, can I read/write/synchronize an NSMutableDictionary of transactions in NSUserDefaults without corrupting the dictionary, or do I need to implement my own locking mechanism with reading and writing with NSKeyed(Un)Archiver (see below)?
Some code:
- (void) queThing:(Thing *)aThing {
// @synchronized this block?
NSMutableDictionary * QD = [self readFile];
[QD setObject:aThing forKey:aThing.thingId];
[self writeFile: QD];
// @ sync?
}
- (void) writeFile:(NSMutableDictionary *)theData {
BOOL status = [NSKeyedArchiver archiveRootObject: theData toFile:archivePath];
if ( !status) {
DebugLog(@"Write to archive failed.");
} else {
DebugLog(@"Write to archive SUCCEEDED.");
}
}
- (NSMutableDictionary *) readFile {
NSMutableDictionary *Q =[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];
if ( ! Q ) {
Q = [NSMutableDictionary dictionaryWithCapacity:2];
}
return Q;
}
Dequeue:
// @synchronized this block?
NSMutableDictionary * QD = [self readFile];
[QD removeObjectForKey:thing.thingId];
[self writeFile: QD];
// @ sync?
It's true that NSUserDefaults
is thread safe (it says so in the docs). But conceptually, it's really not the place to be doing stuff like you're doing. It will work, but you'll end up with your transaction IDs potentially polluting a preferences namespace that you may find you want to use later with a preferences bundle, etc.
Doing locking around the reads/writes should work. Putting locks around file ops feels weird to me; you could also keep the queue object in memory (with locking) and only flush it periodically from e.g. the main thread. Or use a lockfile on disk to protect the writes/reads.
精彩评论