Хотя в прошлом я много занимался C / C ++, я занимался Java с 2001 года, поэтому я практически забыл многое из того, что знал, и, кроме того, Objective-C во многом не похож на C ++. В результате вы чувствуете, что умылись на чужом берегу, не в состоянии говорить на этом языке, и вы вооружены не более чем загаром и словарем.
Изучая все эти новые вещи, я понял, что Java — ОЧЕНЬ хороший язык, и причина, в первую очередь, в том, что вам не нужно думать о распределении и освобождении памяти, вы можете просто приступить к написанию своего приложения. , При написании приложений для iOS в Objective-C вы должны как выделить память для ваших объектов, так и затем очистить себя, возвращая память вашего объекта обратно в свободный пул. Это кажется очень старой школой для второго десятилетия 21-го века. Кроме того, выделив память для объекта, вы должны отслеживать количество ссылок на него — практика, известная как подсчет ссылок , с чем я впервые столкнулся в своей предыдущей жизни как программист C ++. Основная идея здесь заключается в том, что каждый раз, когда вы создаете новую ссылку на объект, вы увеличиваете счетчик ссылок, а когда вы заканчиваете со ссылкой на объект, вы уменьшаете его счетчик ссылок.
Когда счетчик достигает нуля, система освобождает память обратно в свободный пул. В Objective-C функция уменьшения счетчика ссылок называется release ; следовательно, если бы в Java был подсчет ссылок, и если бы я хотел, например, попросить AddressService найти мне адрес, мне нужно было бы сделать что-то вроде этого:
1
2
3
4
5
6
7
8
|
// create an object and set the reference count to 1 AddressService addressService = new AddressService(); // Use the object Address address = addressService.findAddress( id ); // pass it to a method model.addAttribute( "address" , address); // free the memory addressService.release(); |
Это простой сценарий, но что произойдет, если тот или иной метод передаст вам ссылку на объект в качестве аргумента метода? В этом случае вам нужно решить, как вы собираетесь его удерживать, и, кажется, есть два способа сделать это. Первый — сделать копию объекта, а второй — увеличить счетчик ссылок. Создание копии, вероятно, является самой безопасной идеей, но она потребляет больше памяти и будет медленнее, в то время как увеличение счетчика ссылок происходит быстро, но не так безопасно, так как какая-то другая часть программы может ошибиться в подсчете ссылок и уменьшить счетчик слишком много раз. , это означает, что у вас есть ссылка на некоторую память, которая могла быть освобождена, и когда вы пытаетесь получить доступ к вашему освобожденному объекту, ваша программа падает … Опять же, если бы в Java был подсчет ссылок, тогда метод обработчика запросов Spring Controller мог бы выглядеть примерно так:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@RequestMapping (value = "/find" , method = RequestMethod.GET) public String findAddress( @RequestParam ( "id" ) int id, Model model) { // increment the reference count - 'retain' is the Objective-C method for doing this. model.retain(); // create a new string object - with reference count of one String msg = new String().withFormat( "Processing an address page request for address with id: " + id); // pass the string to the logger logger.info(msg); // release the string's memory msg.release(); AddressService addressService = new AddressService(); Address address = addressService.findAddress(id); model.addAttribute( "address" , address); addressService.release(); // finished with the model model.release(); return "address-display" ; } |
Здесь следует отметить пару моментов: во-первых, метод-обработчик передается объекту модели, поэтому я увеличиваю счетчик ссылок, вызывая retain, а затем вызываю release для модели, когда заканчиваю с ним в конце метода. , Во-вторых, даже при создании тривиальных объектов, таких как строка сообщения, которая передается в регистратор, вы должны применять правила подсчета ссылок и освободить память, как только закончите с ней.
В приведенном ниже примере демонстрируется альтернатива увеличению счетчика ссылок: создание собственной копии объекта…
01
02
03
04
05
06
07
08
09
10
11
12
|
@RequestMapping (value = "/find" , method = RequestMethod.GET) public String findAddress( @RequestParam ( "id" ) int id, Model model) { // increment the reference count - 'retain' is the Objective-C method for doing this. Model myModel = model.copy(); // As previous example // finished with the model myModel.release(); return "address-display" ; } |
Эти примеры являются лишь тривиальными, есть целый ряд правил подсчета ссылок, которые вам нужно применить, и если вы ошиблись, то Ka-Bam вылетит и произойдет ошибка, если вы попытаетесь получить доступ к уже освобожденной памяти, или медленно умереть из-за утечки памяти, потому что вы забыли освободить память. Хотя я предполагаю, что ключевым моментом здесь является владение : если у вас есть объект, увеличьте его счетчик ссылок, когда вы закончите с объектом, уменьшите его счетчик ссылок.
Приведенный выше код является всего лишь наброском, написанным для иллюстрации сути — он не скомпилируется. Код был взят из моего примера Address на GitHub и в реальной жизни выглядит так:
01
02
03
04
05
06
07
08
09
10
|
@RequestMapping (value = "/find" , method = RequestMethod.GET) public String findAddress( @RequestParam ( "id" ) int id, Model model) { logger.info( "Processing an address page request for address with id: " + id); Address address = addressService.findAddress(id); model.addAttribute( "address" , address); return "address-display" ; } |
… Намного меньше аккуратнее и понятнее. И последнее: некоторые из вас заметят, что в примере с подсчетом ссылок я выделяю (слово Objective-C) новый AddressService — это потому, что в программировании на iOS нет ничего похожего на внедрение зависимостей или среду Spring, поэтому вы вернулись к создание объектов для себя. (Примечание для парней в Spring: «Spring iOS» — звучит как идея для меня…)
Те из вас, кто в курсе, подчеркнут тот факт, что Apple недавно представила так называемый «Автоматический подсчет ссылок». Хотя это не сборка мусора, это упрощает процесс, поскольку iOS теперь автоматически отслеживает ваши ссылки на указатели и освобождает память для вас, когда счетчик достигает нуля, что означает, что вам не нужно беспокоиться о вызове методов сохранения и освобождения ,
Кроме того, этот блог не пытается очернить Objective-C — мне очень нравится Objective-C. Его синтаксис кажется довольно загадочным и кажется многословным по сравнению с Java, но он заставляет вас быть более дисциплинированным в вашей технике программирования, поэтому если вы, как и я, считаете, что хорошее программирование сводится к «ясности мышления», то при написании Objective- С программой нужно думать чуть яснее, и это мне очень нравится.
Я также предполагаю, что многие читатели могут придумать множество причин, почему они считают Java ужасным языком и почему их предпочтительный язык «делает это лучше», каким бы он ни был, поэтому я с нетерпением жду к вашим комментариям …
Наконец, я просто новичок, когда дело доходит до программирования на iOS, поэтому, если кто-нибудь из мастеров iOS / Objective-C встретит этот блог — пожалуйста, дайте мне знать, где я ошибаюсь.
Справка: разве Java не цивилизованный язык? от нашего партнера JCG