Когда вы выделяете объекты с использованием заводских методов, объекты добавляются в autoreleasepool. Автореферат удаляется только при прохождении цикла событий после того, как ваш IBAction
вернулся.
Трюк здесь состоял бы в том, чтобы поместить содержимое вашей петли в свой собственный autorelasepool.
Но давайте сначала рассмотрим самую большую проблему. Существует класс NSMutableString, который вы должны использовать здесь, что резко сократило бы количество объектов, которые вам нужно создать.
Мы поменяемся completeFile к NSMutableString, построенная с использованием метода фабрики, а затем добавить к нему:
-(void) writeToFile: (NSString*)filePath withSeparator:(NSString*) fieldSep{
NSMutableString* completeFile = [NSMutableString string];
for(int i=0;i<[self numberOfRows];i++){
printf("im at line number... %i of %i\n",i,[self numberOfRows]);
for(int j=0;j<[self numberOfColumns];j++){
[completeFile appendString:[self objectInRow:i column:j]];
if(j<[self numberOfColumns]-1){
//separator for all columns except last one
completeFile appendString:fieldSep];
}
}
[completeFile appendString:@"\n"];
}
NSError *error = nil;
[completeFile writeToFile:filePath atomically:NO
encoding:NSStringEncodingConversionAllowLossy error:&error];
if(error){
NSLog(@"Error writing file at %@\n%@",
filePath, [error localizedFailureReason]);
}
}
Это оставляет еще одна проблема, хотя. Смотрите, что [self objectInRow:i column:j]
? Это все еще (предположительно) автореализованный объект. Это не будет очищено.
Возможно, мы сделали свой код, выполняемый без сбоев, в зависимости от размера данных, но это вопрос о том, когда он выходит из строя не если.
Чтобы исправить это, нам необходимо ввести autoreleasepools. Давайте сделаем одну строку в строке и за столбец. Это может показаться чрезмерным (и, действительно, именно в этом случае, поскольку мы исключили использование autoreleasepool во внешнем цикле), но autoreleasepools довольно дешевы. Если вы делаете цикл над большим количеством данных, это просто хорошая практика.
Вы можете заменить каждый из ваших для блоков с @autorelease
блоков, например:
for(int i=0;i<[self numberOfRows];i++){
С:
for(int i=0;i<[self numberOfRows];i++) @autoreleasepool {
Это дает нам этот код:
-(void) writeToFile: (NSString*)filePath withSeparator:(NSString*) fieldSep{
NSMutableString* completeFile = [NSMutableString string];
for(int i=0;i<[self numberOfRows];i++) @autoreleasepool {
printf("im at line number... %i of %i\n",i,[self numberOfRows]);
for(int j=0;j<[self numberOfColumns];j++) @autoreleasepool {
[completeFile appendString:[self objectInRow:i column:j]];
if(j<[self numberOfColumns]-1){
//separator for all columns except last one
completeFile appendString:fieldSep];
}
}
[completeFile appendString:@"\n"];
}
NSError *error = nil;
[completeFile writeToFile:filePath atomically:NO
encoding:NSStringEncodingConversionAllowLossy error:&error];
if(error){
NSLog(@"Error writing file at %@\n%@",
filePath, [error localizedFailureReason]);
}
}
Заключительное обратите внимание. Ваша ошибка здесь небезопасна. Что происходит с указателем ошибки, переданным таким образом на Успех не определен.
[completeFile writeToFile:filePath atomically:NO
encoding:NSStringEncodingConversionAllowLossy error:&error];
if(error){
NSLog(@"Error writing file at %@\n%@",
filePath, [error localizedFailureReason]);
}
Вместо этого, вы хотите:
BOOL ok = [completeFile writeToFile:filePath atomically:NO
encoding:NSStringEncodingConversionAllowLossy error:&error];
if(!ok){
NSLog(@"Error writing file at %@\n%@",
filePath, [error localizedFailureReason]);
}
Это, то должен делать то, что вы хотите.
Это пример [Schlemiel алгоритм художника] (http://en.wikipedia.org/wiki/Schlemiel_the_Painter's_algorithm) в действии. –
Ну, не пример Спольского; 'NSString' не работает как' strcat'. :) –
@StevenFisher: здесь копия делается каждый раз, когда добавляется строка, а не линейный поиск 0 в примере Stratsky's 'strcat'. Но принцип тот же - добавление O (n), поэтому построение строки - O (n^2). –