Подходящо време за използване на съобщението за запазване?

благодаря, че гледахте тази публикация, ще бъде страхотно, ако можете да ми помогнете. Правих нещо object-c и научих за object-c начина за управление на паметта, като например да се уверя, че извиквам освобождаване, когато притежавам обекта, кога да извиквам autorelease и т.н. Също така не искам да използвам ARC или нововъведен GC, тъй като обичам да управлявам собствената си памет, планирам да напредна по-късно в разработката на iOS и знам, че е добра практика да управлявам собствената си памет. Но все още има един малък детайл, в който изглежда съм се натъкнал. Това е свързано с изпращането на обекти на съобщението -retain. Научих, че изпращането на съобщението -retain увеличава броя на препратките с 1. Но дали това е подходящ момент за изпращане на -retain? :

      - (void) setName : (NSString* ) theName 
      {
          // name is an instance variable of type NSString
          [theName retain]; // Must release this
          name = [theName copy]; // Must release this in dealloc
          [theName release]; // decrement the reference count because of retain
      }

Трябва ли да извикам retain тук, за да притежавам аргумента временно и да се уверя, че няма да бъде освободен по някакъв начин, преди да мога да го използвам?

Всяка помощ ще бъде оценена! Благодаря!


person Alejandro    schedule 17.11.2012    source източник


Отговори (1)


Не. Вие, обектът, предоставен като аргумент на метода, обикновено ще съществува, докато вашият метод не се върне. Нямате нужда от съобщения за запазване там. Копирате низа тук, за да го запазите, след като методът се върне.

Това е документирано в документацията на Apple на тази страница в раздела „Избягвайте да причинявате освобождаване на обекти, които използвате“. По-конкретно:

Политиката за собственост на Cocoa уточнява, че получените обекти обикновено трябва да останат валидни в целия обхват на извикващия метод. Също така трябва да е възможно да се върне получен обект от текущия обхват без страх, че ще бъде освободен. За вашето приложение не би трябвало да има значение, че методът за получаване на обект връща кеширана променлива на екземпляр или изчислена стойност. Важното е обектът да остане валиден за времето, което ви трябва.

Като настрана, наистина трябва да обмислите използването на ARC. Не е добра практика да управлявате собствената си памет. Без значение колко добър може да бъде човек в управлението на собствената си памет, компилаторът LLVM е все още по-добър. Управлението на вашата собствена памет ще доведе до трудни за отстраняване проблеми, причинени само от вас самите. Това е допълнително ниво на когнитивно натоварване, с което наистина не трябва да се справяте, и когато най-накрая се откажете от ръчното управление на паметта, ще въздъхнете с облекчение при цялото умствено натоварване, което дори не сте подозирали, че съществува.

person jackslash    schedule 17.11.2012
comment
arc вече не е „не се интересувам от управлението на паметта“. наистина опростява много неща, но също така създава нови проблеми понякога.. както и да е, само една предпазливост, за да не изпаднете в еуфория :D -- все пак заслужава си дъгата е страхотна! - person Daij-Djan; 17.11.2012
comment
Не, вие не притежавате аргументите. И не е вярно, че няма да бъде пуснат поне докато вашият метод не се върне. Гарантирано е само, че обектът е валиден, когато методът е извикан. Но вашият метод все пак може да направи нещо, което косвено да причини освобождаването му. - person newacct; 19.11.2012
comment
На практика, ако аргументът към метод бъде освободен и впоследствие освободен по време на метода без вашата изрична инструкция, бих казал, че го правите погрешно - person jackslash; 19.11.2012
comment
@jackslash: Не знам какво имате предвид под изрична инструкция, но много пъти не е очевидно, че това, което прави методът, може по някакъв начин да доведе до освобождаване на неговия аргумент. - person newacct; 19.11.2012
comment
@newacct Желая да бъда просветлен. Имате ли примери? Или връзка? - person jackslash; 19.11.2012
comment
Помислете за нещо подобно: -(void)doSomethingWith:(NSMutableArray *)arr andPrint:(id)x { NSLog(@"%@", x); [arr removeLastObject]; NSLog(@"%@", x); // Uh oh } -(void)test { id foo = [[NSObject alloc] init]; NSMutableArray *arr = [NSMutableArray arrayWithObject:foo]; [foo release]; id x = [arr lastObject]; [self doSomethingWith:arr andPrint:x]; } - person newacct; 19.11.2012
comment
Технически правилният модел, който да използвате там, би бил [foo autorelease] или да направите [foo release] след извикване на -doSomethingWith:andPrint:, тъй като -(void)test все още използва тази препратка към foo, когато прави извикването на метода и следователно все още трябва да го притежава. Това е пример за погрешно правене. Препращам ви към документацията в моя актуализиран отговор. - person jackslash; 20.11.2012