Apple/Classes
NSOperation Code Examples
아침엔커피한잔
2017. 7. 27. 16:07
https://www.objc.io/issues/2-concurrency/common-background-practices/
@interface ImportOperation : NSOperation - (id)initWithStore:(Store*)store fileName:(NSString*)name; @property (nonatomic) float progress; @property (nonatomic, copy) void (^progressCallback) (float); @end static const int ImportBatchSize = 250; @interface ImportOperation () @property (nonatomic, copy) NSString* fileName; @property (nonatomic, strong) Store* store; @property (nonatomic, strong) NSManagedObjectContext* context; @end @implementation ImportOperation { } - (id)initWithStore:(Store*)store fileName:(NSString*)name { self = [super init]; if(self) { self.store = store; self.fileName = name; } return self; } - (void)main { // TODO: can we use new in the name? I think it's bad style, any ideas for a better name? self.context = [self.store newPrivateContext]; self.context.undoManager = nil; [self.context performBlockAndWait:^ { [self import]; }]; } - (void)import { NSString* fileContents = [NSString stringWithContentsOfFile:self.fileName encoding:NSUTF8StringEncoding error:NULL]; NSArray* lines = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]; NSInteger count = lines.count; NSInteger progressGranularity = count/100; __block NSInteger idx = -1; [fileContents enumerateLinesUsingBlock:^(NSString* line, BOOL* shouldStop) { idx++; if (idx == 0) return; // header line if(self.isCancelled) { *shouldStop = YES; return; } NSArray* components = [line csvComponents]; if (components.count < 5) { NSLog(@"couldn't parse: %@", components); return; } [Stop importCSVComponents:components intoContext:self.context]; if (idx % progressGranularity == 0) { self.progressCallback(idx / (float) count); } if (idx % ImportBatchSize == 0) { [self.context save:NULL]; } }]; self.progressCallback(1); [self.context save:NULL]; } @end @interface ImportViewController () @property (nonatomic, strong) NSOperationQueue* operationQueue; @property (nonatomic, strong) FetchedResultsTableDataSource* dataSource; @end - (id)init { self = [super initWithNibName:@"ImportViewController" bundle:nil]; if(self) { self.operationQueue = [[NSOperationQueue alloc] init]; } return self; } - (IBAction)startImport:(id)sender { self.progressIndicator.progress = 0; NSString* fileName = [[NSBundle mainBundle] pathForResource:@"stops" ofType:@"txt"]; ImportOperation* operation = [[ImportOperation alloc] initWithStore:self.store fileName:fileName]; operation.progressCallback = ^(float progress) { [[NSOperationQueue mainQueue] addOperationWithBlock:^ { self.progressIndicator.progress = progress; }]; }; [self.operationQueue addOperation:operation]; } - (IBAction)cancel:(id)sender { [self.operationQueue cancelAllOperations]; }