Browse files

MXSaveQueue

  • Loading branch information...
1 parent a7e1813 commit d5678a114035be775eb3db35a75f8e3e0c9fe67e @mxcl committed Nov 30, 2012
Showing with 52 additions and 0 deletions.
  1. +21 −0 MXSaveQueue.h
  2. +31 −0 MXSaveQueue.m
View
21 MXSaveQueue.h
@@ -0,0 +1,21 @@
+#import <Foundation/Foundation.h>
+
+/** Save your data in the background on a serial queue.
+ * When you add your job, any existing jobs in the queue are canceled. This is
+ the main point of this class, that is: to avoid resource starvation because
+ of situations where your save function is called way more than you expected.
+ * NOTE that obviously the block is called in the background, so: be thread-safe.
+ * NOTE you probably want to waitUntilAllOperationsAreFinished in your class’s
+ dealloc selector.
+ */
+
+@interface MXSaveQueue : NSOperationQueue
+
+// relative paths will be made absolute relative to ApplicationSupport
+- (id)initWithSaveFilename:(NSString *)path;
+
+// return an NSData object in your block
+- (void)addOperationWithBlock:(NSData *(^)(void))returnTheDataToSave;
+
+@property (nonatomic, readonly) NSString *path;
+@end
View
31 MXSaveQueue.m
@@ -0,0 +1,31 @@
+#import "MXSaveQueue.h"
+#import "NSFileManager+DirectoryLocations.h"
+
+
+@implementation MXSaveQueue
+
+- (id)initWithSaveFilename:(NSString *)path {
+ self = [super init];
+ self.maxConcurrentOperationCount = 1;
+ if (self) {
+ _path = [path hasPrefix:@"/"]
+ ? path
+ : [[[NSFileManager defaultManager] applicationSupportDirectory] stringByAppendingPathComponent:path];
+ }
+ return self;
+}
+
+- (void)addOperationWithBlock:(NSData *(^)(void))dataFeederBlock {
+ [self cancelAllOperations];
+
+ NSBlockOperation *op = [NSBlockOperation new];
+ [op addExecutionBlock:^{
+ NSData *data = dataFeederBlock();
+ if (!op.isCancelled)
+ [data writeToFile:_path atomically:YES];
+ }];
+
+ [self addOperation:op];
+}
+
+@end

0 comments on commit d5678a1

Please sign in to comment.