Ваш второй пример показывает, что вы не понимаете, почему у вас утечка в первом примере, поэтому вы решили поэкспериментировать, что кажется понятным подходом.
Во втором примере textViewAttrStr и tavs практически одинаковы. Они оба являются ссылками (или указателями) на один и тот же объект в памяти.
Итак, когда вы делаете:
textViewAttrStr = tvas;
[textViewAttrStr retain];
//...
[tvas release];
Призыв сохранить для этого объекта уравновешивается вызовом освобождения для этого объекта. Это в значительной степени ничего не делает. Удаление сохраняющих и освобождающих вызовов здесь обеспечивает ту же функциональность. После того, как вы удалите их, у вашего объекта счетчик ссылок 1, потому что вы вызвали alloc, а когда dealloc ударит, он достигнет 0 и будет освобожден.
Теперь, в вашем первом примере, ваш объект выделяется (счетчик ссылок 1), затем сохраняется (счетчик ссылок 2), и, когда Deloc ударит, он достигнет счетчика ссылок 1, а ваш объект не будет быть освобожден и, таким образом, утечка. Таким образом, решение здесь состоит в том, чтобы удалить вызов, чтобы сохранить.
Кстати, проверка того, что объекты не равны нулю, перед отправкой им сообщения о выпуске не нужна, потому что отправка сообщения на ноль ничего не делает.