我在 XCode 8.2、Objective-C、OSX(不是 iOS)上,启用了 ARC。
我正在使用 DaveDelongs CHCSV 解析器在自定义 NSBlockOperation 中导入一个大型 CSV 文件。我的问题:操作完成后内存没有释放。即使我不保存解析的 NSArray* 也会发生同样的情况。
这是代码的基本部分:
SHimportDataOperation.m(自定义 NSBlockOperation)
// CHCSV parser delegate
@interface Delegate : NSObject <CHCSVParserDelegate>
@property (readonly) NSArray *lines; // <-- parsing result is stored here
@property (readonly) NSString *errorMessage;
@property unsigned long long filesize;
@property SHGlobalAppData* global;
@end
@implementation SHImportDataOperation
@synthesize finished = _finished;
@synthesize executing = _executing;
- (void)main
{
// ###############################
// UI stuff
dispatch_async(dispatch_get_main_queue(), ^{
// Hide controls
[_global.dataFile setFileDropped:NO]; // _global.dataFile is an NSObject with relevant fileInformation
});
// ###############################
// Import CSV
if (![self importCSV:_global.dataFile])
{
[self breakImportData]; // Cleanup
return;
}
}
// ###############################
// Finishing Import Data
// UI stuff
dispatch_async(dispatch_get_main_queue(), ^{
// Show controls
[_global.dataFile setFileDropped:YES];
// Show OK
[_global.dataFile setImported:YES];
// Cleanup
[self finishOperation];
});
}
// ################################################
// cleanup
- (void)finishOperation
{
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
_executing = NO;
_finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
// ################################################
- (BOOL)importCSV:(SHDataModelData *)dataFile
{
encoding = NSMacOSRomanStringEncoding;
NSString* delimiter = @",";
unichar delimiterUnichar = [delimiter characterAtIndex:0];
// ###############################
NSInputStream* stream = [NSInputStream inputStreamWithFileAtPath:dataFile.filePath];
CHCSVParser* p = [[CHCSVParser alloc] initWithInputStream:stream usedEncoding:&encoding delimiter:delimiterUnichar];
Delegate * d = [[Delegate alloc] init];
[d setGlobal:_global]; // Reference needed for UI progress bar
[p setDelegate:d];
[p setFilepath:dataFile.filePath];
[p parse];
//NSLog(@"Result: %@",d.lines);
// Save imported data
//[dataFile setImportData:d.lines]; // Even if not saved, memory is not free'd after operation
// Even if i nil everything, memory is not freed.
[d setGlobal:nil];
[p setDelegate:nil];
d = nil;
p = nil;
return true;
}
这就是操作的开始方式:
NSOperationQueue* operationImportQueue = [NSOperationQueue new];
SHImportLayoutOperation *importLayoutOperation = [[SHImportLayoutOperation alloc] init];
[importLayoutOperation setGlobal:[self theAppDataObject]];
SHImportDataOperation *importDataOperation = [[SHImportDataOperation alloc] init];
[importDataOperation setGlobal:[self theAppDataObject]];
NSBlockOperation *importDoneCompletionOperation = [NSBlockOperation blockOperationWithBlock:^{
[self continueWithStuff];
}];
[importDoneCompletionOperation addDependency:importDataOperation];
[importDoneCompletionOperation addDependency:importLayoutOperation];
[operationImportQueue addOperation:importDoneCompletionOperation];
[operationImportQueue addOperation:importDataOperation];
[operationImportQueue addOperation:importLayoutOperation];
编辑1:
经过进一步测试,我可以确认 NSBlockOperation 已成功执行并从内存中删除。