Решение этой проблемы только с одним открытым:
f = open("target.txt","r+")
d = f.readlines()
f.seek(0)
for i in d:
if i != "line you want to remove...":
f.write(i)
f.truncate()
f.close()
Это решение открывает файл в режиме r / w («r +») и использует поиск для сброса f-указателя, тогда truncate, чтобы удалить все после последней записи.
Представьте, что вы реализуете метод в терминах нескольких других методов:
-(BOOL)sendCachedRequestReturningError: (NSError**)err {
BOOL success = [self readCachedRequestReturningError:err];
if (!success && (*err).domain == MYFileDomain && (*err).errorCode == MYFileNotFoundCode) {
success = [self sendUncachedRequestReturningError:err];
}
return success;
}
Теперь здесь есть 4 пути кода:
success == YES
и все хорошо. readCachedRequestReturningError:
установит err
и установит success == NO
, и вызывающий абонент вызовет presentError:
или что-то еще err
и success == NO
. readCachedRequestReturningError:
установит err
в допустимое значение NSError{MYFileDomain, MYFileNotFoundCode}
, но затем sendUncachedRequestReturningError:
выполнится успешно и установит success == YES
, а не коснется err
вообще, оставив в нем предыдущую ошибку. Если вы теперь проверяете err
вместо проверки возвращаемого значения, вы будете думать, что произошла ошибка, когда все прошло хорошо. Примечание: приведенный выше код сильно упрощен, потому что мы заботимся только об ошибках. Конечно, в реальной программе методы могли бы иметь другой возвращаемый параметр для фактического ответа на запрос или возвращать ответ или nil
вместо success
BOOL
. Это также, вероятно, проверит, является ли err
NULL
. [Тысяча сто двадцать семь]
Этот дизайн не очень необычный, сравните также ошибочно в стандартном C.
Дизайн имеет ряд потенциальных преимуществ:
Функция не должна писать через указатель на успех. Это не только делает реализацию таких функций более легкой и менее подверженной ошибкам, но также может быть небольшим преимуществом в производительности (например, это предотвращает аннулирование кэшей ЦП при успешном выполнении функции).
Если мы всегда проверяем, что функция не сработала, прежде чем получить доступ к ошибке, мы можем использовать один и тот же указатель ошибки для нескольких функций. В противном случае мы можем получить предыдущий сбой, а не сбой самой последней функции.
Это облегчает написание кода проверки. Например. функция может установить ошибку по умолчанию. Если все проверки пройдены, функция может просто вернуть успех вместо того, чтобы сбрасывать переменную ошибки.
Функция может использовать тот же указатель ошибки при вызове других функций, но сбой этих помощников не обязательно означает сбой верхней функции.
В вашем конкретном случае переменная NSError *theError;
не была инициализирована. Доступ к этой переменной без ее назначения вначале вызовет неопределенное поведение. Документация только гарантирует, что переменная будет установлена в случае ошибки.