Шокирующий Objective-C для Java программистов

    О чем эта статья?


    Два факта. В мире много Java программистов. Популярность Objective-C растет. Вывод: Java программист, изучающий Objective-C не такая уж редкость. Если знать ключевые различия между языками, то можно эффективно использовать существующие знания Java и быстрее начать писать на Objective-C.

    Я начинал с С, пишу на Java последние 15 лет, иногда переключаясь на С++, Python, Perl, с интересом наблюдаю за Scala. И вот теперь Objective-C.

    От каждого путешествия обычно остается несколько историй о наиболее забавных отличиях «нас» от «них». Не претендуя на полноту изложения расскажу об особенностях Objective-C, которые особенно удивили меня, как пришельца из Java. Позднее я заметил, что непонимание или неприятие этих особенностей порождает код на Java, написанный синтаксисом Objective-C, тогда как гораздо естественнее писать просто код на Objective-C. Язык это не только синтаксис, это в первую очередь идиомы. Еще раз подчеркну — это не путеводитель, а заметки туриста. Если они покажутся интересными — продолжу рассказывать о своих наблюдениях в последующих статьях.

    Посылаем, а не вызываем, сообщения, а не методы


    Java:
    object.method(param);

    Objective-C:
    [object method:param];


    В Java мы вызываем методы объекта, в Objective-C — посылаем сообщения объекту. Разница не только в терминологии. Любое сообщение проходит через функцию-диспетчер, которая использует параметры, помещенные в стек и идентификатор метода (использую слово метод, чтобы обозначить код, обрабатывающий сообщение и продолжу его использовать, чтобы было привычнее для Java программистов), называемый селектор (selector), чтобы найти и вызвать метод объекта-получателя. Звучит как ненужное усложнение, но эта дополнительная абстракция фундаментальна и обеспечивает динамизм, частные проявления которого описаны ниже.

    Замечу, что в отличие от Java компилятор не всегда может проверить наличие метода, в таких случаях он выдает предупреждение (warning). Если уверены в себе — игнорируйте. Если взяли на себя слишком много — программа свалится на посылке сообщения.

    Как меня зовут?


    Java:
    public Feature addFeature (String name, String value, boolean isOptional);

    Objective-C:
    -(Feature*) addFeature :(NSString*)name withValue:(NSString*)value asOptional:(BOOL) optional:


    Имя метода в Objective-C “размазано” по списку аргументов. Полное имя, а именно оно используется при конструировании селектора, звучит как addFeature:withValue:asOptional:

    SEL selector = @selector(addFeature:withValue:asOptional:);

    Если сдержать первые позывы, начинаешь привыкать и оказывается, что такие имена хорошо читаются и даже ясно, зачем нужен каждый из 16 параметров. Хотя это не причина делать метод с 16 параметрами.

    Серьезный шок: любой может испортить мой класс, а не только я



    В Java аналогов нет

    Objective-C:
    @interface NSString (LetsAugment)
    -(BOOL) isGoodActor;
    @end


    Но и мы в ответ можем испортить что угодно, хоть NSObject. Спасибо категориям (category). В примере выше определена категория LetsAugment, которая добавила метод isGoodActor базовому классу NSString. Пусть реализация возвращает NO (false в Java), если это не актер или актер, но плохой и YES (true) если актер, да еще и хороший. Домашнее задание — угадайте результат работы этого кода:

    if ([@”Steven Seagal” isGoodActor]) NSLog (@”Yeah!”) else NSLog (@”What's wrong with you?”);

    Все дело в динамической диспетчеризации сообщений, вот она динамика, вот она гибкость.

    Категории, во-первых, позволяют разбить определение класса по нескольким файлам. В идеале класс должен выполнять одну конкретную роль, но иногда это не так, например в случае реализации фасада и некоторых других шаблонов. В этом случае удобно описать его в нескольких файлах. Во-вторых, можно действительно элегантно добавить отсутствующую функциональность к существующему классу.

    Совсем шокирующее: неинициализированные ссылки не портят почти ничего


    Java:
    MyTao tao = null;
    int howManyHands = tao.clap();

    Objective-C:
    MyTao* tao = nil;
    int howManyHands = [tao clap];


    В первом случае мы, конечно, получим NullPointerException и, возможно, увольнение. Во втором — в howManyHands будет возвращено 0. Это не 1, как мы ожидали, но хоть не уволили.

    Опять все дело в динамической диспетчеризации сообщений. Диспетчер сообщения сразу же проверяет получателя объекта и если он nil (null в Java), то возвращает типизированную пустоту (nil, 0, NO и т.п.). Звучит как жалкая защита от дурака, но на самом деле разумное использование этой особенности позволяет писать очень компактный и читаемый код.
    Java: (псевдокод)

    class Profile {
    int getVersion() {
    ...
    }

    class Feature {
    Profile getProfile(String name) {
    ...
    }

    class Phone {
    Feature getFeature(String name) {
    ...
    }

    class PhoneFactory {
    static Phone designAndProduce(String model) {
    ...
    }
    }

    ...
    int version = 0;
    Phone phone = PhoneFactory.designAndProduce(“iphone5”);
    Feature btFeature = phone.getFeature(“bt”);
    if (btFeature != null) {
    Profile profile = btFeature.getProfile(“a2dp”);
    if (profile != null) {
    version = profile.getVersion();
    }
    }



    Objective-C:

    @interface Profile : NSObject
    @property (readonly) int version;
    @end

    @interface Feature : NSObject
    - (Profile*) getProfile:(NSString*)name;
    @end

    @interface Phone : NSObject
    + (Phone*) designAndProduce:(NSString*)name;
    -(Feature*) getFeature:(NSString*)name;
    @end
    ...

    Phone* phone = [Phone designAndProduce:@"iphone5"];
    Feature* btFeature = [phone getFeature:@"bt"];
    Profile* profile = [btFeature getProfile:@"a2dp"];
    int version = profile.version;



    Код на Objective-C гораздо более чистый и при этом безопасен как и Java эквивалент. Если [phone getFeature:@«bt»] вернет nil, исполнение продолжится и version будет иметь значение 0.

    Почему же «не портят почти ничего»? Все же nil не является полностью безопасным, диспетчер защищает нас при отправлении сообщений, но он бессилен, если мы обращаемся к полям объекта. Кстати именно поэтому важно обращаться к полям через методы (getter/setter). Более того, Objective-C предлагает для этого специальную конструкцию языка (кто-то обратил внимание на profile.version?) — свойства (property), но об этом в следующей статье.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 161

      +9
      На самом деле, смысла в описании различий синтаксиса нет никакого — понимание приходит через две недели работы, а начинать писать можно сразу же после прочтения статьи о языке в википедии.

      А вот различия в семантике — особенно работа со счетчиком ссылок (assign/retain-init-copy, autorelease pool), категории и подстановки первое время серьезно бьют по мозгам.

      Хотя уже через месяц вырабатываются практики использования всех этих возможностей для эффективного программирования. Правда, программисты на C# по инерции продолжают использовать категории в качестве партиальных классов.
        +1
        Используйте ARC и забудьте про счетчик ссылок =)
          +1
          а также забудьте о поддержке версий < 5.0 :)
            0
            вас бы за это заминусовать до -100 чтобы никто не видел. Проекты с ARC прекрасно работают даже на 3х
            ARC это функция компилятора а не ОС — учите матчасть
              0
              4.3x имелось в виду
                0
                Ой, я конечно же имел ввиду ios 4.0, ведь поддержка идет с xcode 4.2 для ios >= 4.0. А вот на счет 3х — не правда.
            0
            Странно. Я вот C# разработчик и не использую так категории.
            И уж пошла речь о них:
            Partial class в C# — это совсем другое. А вот методы расширения — один в один категории.
              +1
              Вы особенный.
                0
                По сути это нечто среднее между partial и extension. Partial — всего лишь одно из применений категорий. И C# тут не при чем: много классов в самом Foundation Kit используют категории в качестве Partial.
              +8
              *shoked*
                +6
                когда-то начинал писать подобную серию статей для C# разработчиков, но после первого поста забросил — Objective-C для C# разработчиков
                ваш подход «через шок» мне кажется интереснее.
                <мысливслух>может тоже стоит возобновить и таки дописать этот предполагаемый цикл.</мысливслух>
                  +5
                  Было бы очень интересно почитать дальше.
                    +1
                    спасибо. попробую продолжить.
                      +1
                      Да, пожалуйста продолжайте.
                  • UFO just landed and posted this here
                      +1
                      приятно, что статья оказалась полезной:) в ближайшее время напишу продолжение.
                    +4
                    Казалось бы, что может быть интересного в сравнении синтаксисов двух языков… Но автору удалось удержать мое внимание до конца статьи и просить продолжить в том же духе. Наверное, если бы пришлось изучать Objective-C, статья не вызвала бы интереса, но для общего развития посмотреть в «чужой огород» было интересно. Спасибо. (сам пишу на java)
                      +4
                      Когда я осваивал Objective-C, я был до смерти запуган подобными статьями. Теперь же могу сказать, что такие статьи — зло, а Obj-C я очень люблю.
                        0
                        Мобильная версия чуть промахивается, повторю — мне он тоже нравится, см последний пример
                          +2
                          Просто новички (по себе сужу), больше внимания обращают не на объективные плюсы, а на часто саркастические пугающие комментарии к примерам и постам.
                            –1
                            Лично я на комменты не обращаю внимание, тут фишка в другом. Не могу сказать, что я полиглот, но языков программирования знаю достаточно. Objective-C начал учить недели 3 назад по Kochan S. Programming in Objective-C 2.0 и сразу испугало объявление интерфейса:
                            @interface Fraction: NSObject
                            {
                            int numerator;
                            int denominator;
                            }
                            -(void) print;
                            -(void) setNumerator: (int) n;
                            -(void) setDenominator: (int) d;
                            @end

                            Ну все-таки привык, когда "}" закрывает описание интерфейса/класса, а тут она закрывает только описание полей.
                            Сообщения, типа [fraction print] тоже убили… Сразу вспомнил статью про приставку «http://», когда разработчики стандарта говорили, что не подумали о возможной популярности протокола и может пользователи не набирали бы так много лишних символов (как-то так, не могу эту статью найти). Так и тут, выразительности ноль, зато есть много лишних элементов синтаксиса.
                              0
                              все эти «лишние» элементы синтаксиса отлично сам вставляет XCode
                                0
                                Но читает же программист? Или тоже XCode?
                                  0
                                  про какие лишние элементы синтаксиса вы говорите? @end? @interface? }?
                                    0
                                    Видимо про квадратные скобки.
                                    Справедливости ради стоит заметить, что буквально через неделю-две кодинга глаз привыкает и автоматически их игнорирует, за то, благодаря синтаксису написания сообщений и их именованию, код читается намного лучше чем те же плюсы.
                                      0
                                      Привыкнуть можно, но Стив Джобс явно не приложил руку к Objective-C ) Все могло быть проще и красивее.
                          +8
                          Все-таки по современным меркам objective C — довольно уродливый язык. А без блоков он был бы еще и убогий.

                          Отсутствие обобщений довольно сильно угнетает, например. Зато встроенные примеси — это прекрасно, хотя по качеству они недалеко ушли от extension methods в C#.
                            –2
                            Ну не знаю. С точки зрения синтаксиса — мне лично более симпатичен, чем знакомые С++ или JavaScript (хоть это и скриптовый язык, но мы же про синтаксис).
                              +2
                              С-подобные языки лично мне более симпатичны, нежели smalltalk-образные. Хотя мне, определенно, нравится их идея построения объектной модели.
                              0
                              Некоторые считают, что extension methods — зло http://habrahabr.ru/blogs/net/122320/
                                +1
                                Некоторые до сих пор считают, что писать ресурсоемкие модули нужно на ассемблере. Не надо ориентироваться на девиации.
                            0
                            Мне он тоже нравится, см последний пример
                              +1
                              В плане схожего синтаксиса последнее время меня очень манит Objective-J – Cappuccino
                                +2
                                Практика «под каждую задачу свой язык» — хороша. Но «под каждую платформу свой язык» — имхо, перегиб.
                                  0
                                  А причем тут Cappuccino?
                                +18
                                Re: «В первом случае мы, конечно, получим NullPointerException и, возможно, увольнение. Во втором — в howManyHands будет возвращено 0. Это не 1, как мы ожидали, но хоть не уволили»
                                Это очень большой минус. Представим себе аналогичное поведение в Java: NullPointerException никогда не бросается. И бегай потом с дебаггером по всему коду и ищи почему он не работает.
                                  –15
                                  Это огромный плюс. Как Objective-C разработчик говорю — никаких проблем с отладкой.
                                  Плюсы очевидны:
                                  1 Мне не надо совать кучу проверок на nil и тд -> код меньше и проще
                                  2 Если указатель был nil я знаю что я всегда получу (0, nil, NO и тд) и на этом строитятся много кода
                                  3 Снижается шанс, что программа упадет если все таки проверка где-то забыта или nil появился там где его не ожидали
                                    +16
                                    Как Objective-C разработчик говорю — отсутствие NullPointerException — рассадник ошибок. Да, к этому привыкаеш, но тому кто это придумал я б гвоздь в голову забил.
                                      –5
                                      А вы не путаете nil и NULL? nil — это полноценный объект, которому (сюрприз!) можно послать любое сообщение.
                                        –2
                                        Да ты что? Найди определение nil и NULL, а потом смотри разницу.
                                        –3
                                        ой да какой рассадник ошибок? мне вот только помогает — например при отправке сообщения делегату не надо смотреть существует он или нет
                                          –5
                                          Чушь. Пеняйте на свои руки и привычки, а не на язык. Возможность посылать сообщения nil'у — великое благо, т. к. избавляет код от туевой хучи ненужных проверок и делает гораздо более читабельным. И в случае необходимости никто не запрещает проверку добавить.
                                          (пишу на obj-c уже четвертый год)
                                            +2
                                            Любопытно было бы узнать опыт разработки на obj-c анонимных самоутверждающихся минусователей. Сферические рассуждения о том, что посылка сообщения nil'у сообщения может быть причиной ошибки имеет мало общего с действительностью — нормальный код пишется с осознанными допущениями, где указатель может быть nil'ом, а где нет. Как уже выше написали, яркий пример этому — делегат.
                                              +3
                                              3 года. Конечно в сообшениях в nil есть удобство при написании кода, но было бы лучше если бы была возможность отследить посылку сообшения в nil. Или если бы результатов сообшения от nil было какое то специфическое значение, а на 0.
                                                +1
                                                )))
                                                Победитель Game of The Year for iPad в этом году — моя игра Contre Jour. написана на objc конечно.
                                                Не пропало желание опытом мериться?
                                                  0
                                                  Я тут не опытом меряюсь, а хочу узнать есть ли тут программеры с опытом, которые реально считают возможность посылки сообщений nil'у проблемой. И про свой опыт Вы не написали. Награды меня не особо впечатляют — один из проектов, над которым я работал, был 9 в top100 us appstore и использовался в рекламе iphone.
                                                    0
                                                    да. я прогер с опытом.
                                                    я это не считаю проблемой. Я считаю это полнейшым профтыком разработчиков языка.
                                                    посмотрите в инете видео contre jour. оцените сложность. и вам все станет понятно.
                                                      0
                                                      Вы продолжаете кидать понты, но так и не указали сколько времени программируйте на obj-c. Вы не считаете поведение nil'а проблемой, но кидаетесь обвинениями в адрес языка. Вы можете быть сколь угодно крутым игроделом, но вопрос сейчас не об этом. Я не говорю о том, что такое поведение нулевого указателя будет хорошо для любого языка, но в obj-c оно оправдано, и те, кто это отрицают, по моему мнениюпросто тянут свои привычки. Мне после C++ тоже было довольно непривычно.
                                                        +4
                                                        А какая разница, сколько я программирую? (3 года на objc если уж так интересно)
                                                        Мастерство не в месяцах измеряется. Я делаю крутые и сложные вещи.
                                                        Я знаю сколько времени у меня уходит на отлавливание багов, связаных с nil. У вас нет? Так может вы просто делаете примитивные проекты?
                                                          –3
                                                          Вы такая скромняжка =) Нет, у меня проблем с nil'ом нет. Что в Вашем понимании примитивные проекты? 50k строчек кода — все еще примитивный? А 100k? И неужели не нашлось ни одного универсального способа отловить отсылку сообщения nil'у, какой-нибудь магией типа method_exchangeImplementation?
                                                            –2
                                                            Сложность проекта и количество строк кода — величины весьма слабо связанные.
                                                              0
                                                              лол что? отловить сообщение нилу можно только переопределением obj_msgSend или навешиваним на нее проба в DTrace.
                                                                +1
                                                                У вас какоето непреодолимое желание мерить все сантиметрами. Опыт в годах, сложность в строчках. Сложность в строчках не измеряется.
                                                                Дайте линк на какой-то свой проект и по описанию функционала будет видно сложный ли он.
                                                                method_exchangeImplementation — и к чему вы это??
                                                                Можно попробовать оверрайднуть obj_msgSend, но что тогда делать со всеми подключаемыми библиотеками, которые на такое поведение расчитывают?
                                                                  0
                                                                  Опыт в годах — потому что интересен именно objc-опыт, а не общий опыт программирования. Насчет сложности — предложите другие критерии. По описанию — это еще более хреновый критерий. Например, в одном из проектов, над которым я работал, используется оптимизированный под arm mp3-кодек — как Вы про это узнаете из описания?
                                                                  method_exchangeImplementation — к тому, что obj-c довольно гибкий язык в плане подмены реализации. У меня не было нужды использовать этот набор функций, поэтому я не могу дать готового решения, но мне кажется в той стороне можно что-то накопать. Не уверен, что можно перегружать obj_msgsend — это статическая функция вроде, а не классовый метод.
                                                                  Ссылки на проекты кину в PM.
                                                                    0
                                                                    Погуглил — вроде есть какие-то волшебные флажки для linker'а, чтобы подменить вызов функции своей оберткой. Но работает не везде. Если получится перегрузить, то можно хотя бы в лог выводить сообщения nil'у.
                                                                      0
                                                                      цитирую свой предыдущий комент (вы его читали?)
                                                                      >но что тогда делать со всеми подключаемыми библиотеками,
                                                                      >которые на такое поведение расчитывают?
                                                                        0
                                                                        Для начала надо смотреть что там linker позволяет — возможно он будет использовать обертку только в скомпилированных объектниках. Если не получится, можно фильтр написать. Например, заполнить массив из стандартных объектов как blacklist, и массив из кастомных объектов как whitelist. Потом сначала пробегать по blacklist'у и вызывать у каждого объекта respondsToSelector — если не отвечает, то по whitelist'у бежать и писать в лог если отвечает. Вы же опытный программер, неужели ничего сами придумать не сможете? =)
                                                                          0
                                                                          из того что я накопал я сделал вывод, что реплейснутый метод будет вызываться для всех библиотек.

                                                                          а добавлять все классы каждой подключеной либы в блеклист… вы это действительно считаете приемлемым решением?

                                                                          вообще для себя я нашел решение намного проще. следующие иОС проекты буду писать на моно. быстрее, удобнее и общяя код база для иОС, андроида и винфона.
                                                                            0
                                                                            Это только то, что сходу пришло в голову. Наверняка есть более интересные решения.
                                                                            Если уж отказываться от obj-c, то чего тогда уж не написать движок сразу на C++? На iOS и Android уже давно можно, на WP7 наверняка добавят в одном из следующих релизов (да и, честно говоря, эта платформа до сих пор не выглядит актуальной). И нет зависимости от неофициальных фреймворков, которые Apple может запретить, если у нее зачешется левая пятка.
                                                                              0
                                                                              mono уже врядли запретят — довольно популярные приложения на нем есть в сторе.
                                                                              в WP7 не факт что плюсы добавят, да и пишу я под него уже прямо сейчас.
                                                                              да и в плане скорости и удобства разработки C# всетаки намного привлекательнее чем C++. + следующий проект у меня возможно будет на Unity, а там опять C#.
                                                                              Это не правило, конечно, но конкретно в моем случае mono выглядит очень хорошим решением.
                                                                            0
                                                                            Лучшее решение этой проблемы это использование DTrace probe. Проб можно повесить на вызов obj_msgSend и настроить так чтобы он сообшал при вызове с нилом.
                                                                +3
                                                                А до того я еще года 4 программировал на AS2, где аналогичное поведение null. И вздохнул с облегчением, когда из AS3 эту «фичу» убрали. И это несмотря на то, что AS2 вообще для меня был первым языком, на котором я работал.
                                                                Так что это явно не дело привычки.
                                                    +15
                                                    Задача разработче состоит не втом, чтобы написать программу которая не падает, а в том, чтобы написать программу которая работает. Иногда такая особенность как посылка сообшения в nil может быть причиной ошибок.
                                                      0
                                                      Большинству пользователей не будет дела до того как она работает, если периодически она будет вываливаться.
                                                        +3
                                                        Тоесть будет хуже если она будет неправильно реализовывать логику необходимую пользователю?) А если ваша программа падает/не падает, это не недостаток/преимущество языка, это мера вашей кривокукости)
                                                          0
                                                          Кто сказал, что она будет работать не правильно? Мой опыт говорит, что поведение nil больше плюс, чем минус, и статистикой (говорю только за себя) это подтверждается
                                                            0
                                                            Я сказал :) Возмем пример

                                                            — (long long)someCalculations;

                                                            ваш код расчитывает, что метод вернет или 0 или кактой значение, так же?
                                                            А что по вашему вернет метод при посылке сообшения в nil? Подумайте над этим)

                                                            Я не говорю, что сообшения в nil это вселенское зло, но это потенциальный источник проблем, а удобств он дает самую малось)
                                                              0
                                                              извиняюсь на счет long long метода был не прав, уже пофиксили ) Раньше метод бы вернул не 0, а числовое представление селектора, но это было во времен 32 битного кокоа.
                                                                0
                                                                В 64 битном окружении проблем стало меньше) но опять же никто не отменял некоретного поведения основанного на nil, примет:

                                                                FireDetector *detector = [Detectors getDetector:kFireDetector];

                                                                //Предположим что по какой то ошибке в коде фабрика возврашает нам nil, какого поведение нашего кода в случае пожара?)

                                                                if ([detector isFire]) {
                                                                [self alarm];
                                                                }
                                                                • UFO just landed and posted this here
                                                                    0
                                                                    тада, я что то не очень удачный пример привел, но в целом это показывает возможные последствия от нила
                                                                    • UFO just landed and posted this here
                                                      0
                                                      Вы просто со своей колокольни смотрите на это.
                                                        +2
                                                        Я со своей колокольни iOS-разработчика смотрю точно так же.

                                                        Конечно, замечательно, что в язык встроен патерн null object, нередко это бывает очень полезно. Но я бы все-таки хотел, чтобы реализация его была явной, например в виде [SomeObject nilInstance]

                                                        Единственное, что действительно приносит определенную пользу — это не падающий [nil release]
                                                          0
                                                          Я не гуру, конечно, но почему рекомендуют делать так, аргументируя, что типа так безопаснее?
                                                          [name release];
                                                          name = nil;
                                                            +2
                                                            Дело в том, что после [name release] в переменной name остается адрес уже мертвого объекта. Любое обращение к этому объекту выдает SIG_BAD_ACCESS, который потом долго придется отлавливать с помощью NSZombie и прочих эзотерических практик.
                                                              0
                                                              Две поправки — потенциально мертвого (если ваш release уменьшил счетчик ссылок до 0 и вызвал dealloc) и EXC_BAD_ACCESS.
                                                                0
                                                                Да, я это и имел ввиду.
                                                                0
                                                                Ну вот. Получается, что без этого `name = nil;`в Obj-C получим результат как в Java с ним, как написал general?
                                                                  0
                                                                  Не совсем. EXC_BAD_ACCESS это все-таки не совсем обращение к нулевому указателю.

                                                                  Кроме того, возможно, что в переменной name будет живой объект, если ссылка на него существует еще где-то. В этом случае мы получим просто неверное поведение.
                                                                0
                                                                Да, что бы обезопасить себя.
                                                                Яркий пример касается uiviewcontrollera
                                                                Не гарантируется, что метод viewDidUnload будет вызван, а в нем рекомендуется освобождають ui шные переменные. В то же время, dealloc точно будет вызван. Что бы не возникла ситуация с утечкой памяти релизят и в методе viewdidunload и в dealloc. При этом если зарелизиться в viewdidload и переменной будет присвоенно nil, то в dealloc еще один realese к нилу пройдет незаметно.
                                                                  +1
                                                                  Вы о чем? viewDidUnload не вызывается при удалении. Для освобождения ресурсов при удалении объекта только dealloc.

                                                                  viewDidUnload метод для реакции на некоторые особые ситуации. Например, сообщение low memory warning. В этом методе рекомендуется освободить
                                                                  все IB объекты и все, что потом легко восстановить в методе viewDidLoad (если вызван viewDidUnload то точно будет вызван повторно viewDidLoad, если объект раньше не удалят).

                                                                  Пример с low memory warning.
                                                                  Есть 2 viewController: А и В, мы используем navigationController для навигации между ними. У нас сначало был открыт А, в нем мы нажали что-либо и открылся В. Тоесть стек навигации: А->B.
                                                                  Приходит сообщение low memory warning, при этом у A вызывается viewDidUnload, но только у А, потому что он не на экране и его объекты интерфейса можно освободить (у того контроллера, который находится на экране
                                                                  viewDidUnload не вызывается, иначе юзер получит пустую форму). Дальше юзер поработал в В и нажал кнопку назад чтобы вернуться в A, при этом в A будет повторно вызван viewDidLoad чтобы восстановить объекты интерфейса и тд освобожденные в viewDidUnload.
                                                                  У B, при возвращении к А, вызовется только dealloc (не в коеv случае не viewDidUnload)
                                                                0
                                                                Такое есть:
                                                                [NSNull null];

                                                                Пример использования:
                                                                NSArray *arr1=[NSArray arrayWithObject:nil]; //исключение 
                                                                NSArray *arr2=[NSArray arrayWithObject:[NSNull null]]; //без ошибок
                                                                  0
                                                                  Но проблема [(NSObject *)nil retain] остается.
                                                                    0
                                                                    А какая проблема? Мб просто я не понял о чем вы. nil можно ретайнить и релизить сколько угодно, никаких ошибок и утечек не будет.
                                                                      0
                                                                      Допустим, у меня есть массив, который я получаю в функцию и дальше считаю количество элементов. В случае, если мне в функцию передадут nil и я забуду сделать проверку — у меня будет каждый раз отрабатывать так, как будто мне передали массив из 0 элементов.
                                                                        0
                                                                        В Objective-C это нормально. Как я говорил выше на этом строится много логики. В принципе, достаточно логично: массив = nil -> в нем просто 0 элементов
                                                                          +1
                                                                          Это у вас на этом строится много логики. Вы же не думаете, что ваш подход — самый правильный и стройный?

                                                                          Кроме того, nil и масссив из 0 элементов это разные вещи. Например, массив из 0 элементов вернет respondToSelector:@selector(objectAtIndex:) YES, а nil вернет NO.
                                                                            0
                                                                            Не только у меня. В том числе и примеры apple. Это стиль Objective-C.
                                                                              +1
                                                                              Радости от этого никакой, честно говоря.
                                                                              +1
                                                                              Может я не правильно выразился. Я имел в виду следующее, в многих случаях это очень удобно, например, зачем писать так (как сделали бы по привычке, люди писавшие, на том же C):
                                                                              -(void)dealloc
                                                                              {
                                                                              	if(obj1!=nil)
                                                                              		[obj1 release];
                                                                              	if(obj2!=nil)
                                                                              		[obj2 release];
                                                                              	[super dealloc];
                                                                              }
                                                                              


                                                                              Если проще использовать следующее (это вы увидите везде, и в примерах apple, и в принципе в примерах по Objective-C)
                                                                              -(void)dealloc
                                                                              {
                                                                              	[obj1 release]; //если obj1==nil, то ничего не произойдет
                                                                              	[obj2 release]; //если obj1==nil, то ничего не произойдет
                                                                              	[super dealloc];
                                                                              }
                                                                              
                                                                                0
                                                                                Плохо то, что такое поведение навязывается.
                                                              +3
                                                              Эх, живой явный последователь smalltalk
                                                                0
                                                                Именованные параметры в методах мне даже нравятся (хотя я плевался, когда впервые столкнулся с ними в ABAP :).
                                                                Категории напоминают JavaScript.
                                                                Но вот счётчики ссылок для меня пока за гранью добра и зла :(
                                                                  0
                                                                  Мне наоборот нравятся счетчики ссылок)) В последних версия Xcode есть компилятор со сборщиком мусора, так что если вас пугают счетчики ссылок, то просто используйте его (apple сам его рекомендует, по крайней мере для начала)
                                                                    0
                                                                    сборщик мусора существует уже очень давно, а точнее с версии Мака 10.5, а если вы имеете ввиду ARC, то это не сборщик мусора, а статический умный «подставлятель» release/retain ов. Что просто декорирует а не убирает это поведение. Для iOS сборщика мусора не будет скорее всего, и я склонен к мысли что это хорошо, а не плохо. Да и компилятор к икскоду имеет не совсем прямое отношение и поддержка ARC появилась в LLVM3 достаточно давно, помоему более чем пол года назад.
                                                                      0
                                                                      Для iOS сборщика мусора, вроде бы, нет.
                                                                      И Эплл, похоже, опять передумал, и рекомендует всем переходить с GC на ARC.
                                                                        +1
                                                                        Да, я ошибся. Я имел в виду, конечно же, ARC. Просто сам использую ручное управление
                                                                      0
                                                                      Счетчик ссылок — это как в поговорке «Сила есть – ума не надо», только наоборот.
                                                                      0
                                                                      С удовольствием прочитал бы продолжение. Про подсчет ссылок, сборку мусора, свойства, рефлексию и т.д. И еще — про внутреннее устройство системы диспетчеризации сообщений.
                                                                        –2
                                                                        Маленькое замечания по селекторам
                                                                        Селектор это не совсем так

                                                                        addFeature:withValue:asOptional:

                                                                        Это скорей так

                                                                        addFeature:::

                                                                        Т.е. withValue и asOptional это Необязательные подсказки и их можно не указывать, вызвав метод так

                                                                        [self addFeature :@"Foo" :@"bar" :YES]

                                                                        или

                                                                        SEL selector = @selector(addFeature:::)
                                                                          0
                                                                          Правильно ли я понимаю, что

                                                                          -(void) someMethod:(int)param with:(int)param2;

                                                                          и

                                                                          -(void) someMethod:(int)param inCaseOf:(int)param2;

                                                                          неразличимы?
                                                                            0
                                                                            А вот это вопрос!
                                                                              0
                                                                              Различимы до предупреждения компилятором и падения исполнением
                                                                              +1
                                                                              Вы полностью ошибаетесь, значимы все элементы селектора.
                                                                                +3
                                                                                Извините, я действительно был некомпетентен в этом вопросе.
                                                                                  –1
                                                                                  Чушь. Неправильно.
                                                                                  +1
                                                                                  Не стоит начинать название метода с «get»:
                                                                                  -(Feature*) getFeature:(NSString*)name;

                                                                                  Хотя это и не обязательно, но Apple рекомендует это тут

                                                                                  Use “get” only for methods that return objects and values indirectly. You should use this form for methods only when multiple items need to be returned.

                                                                                  - (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)phase;
                                                                                    0
                                                                                    У меня это не совсем accessor, но спасибо, учту
                                                                                    +1
                                                                                    Напишите еще.
                                                                                      0
                                                                                      А современный компилятор Objective C для иос поддерживает C++? Если да, то на каком уровне? Можно ли писать только на с++, вообще не используя синтаксис Objective C? А то этот язык уж очень опасен своей работой с памятью, кучей с сложностей с подсчетом ссылок, в то время как на с++ с его деструктуроми и перегрузкой операторов подсчет ссылок делается практически прозрачным и автоматическим.
                                                                                        +2
                                                                                        Objective-C гораздо проше чем C++. Писать использую C++ можно, но для работы с какими то системными либами (GUI, FS, etc) придется юзать Objective-C
                                                                                          0
                                                                                          В Xcode ≥ 4.2 в коробке идёт Clang 3.0, соответственно его фичи смотрите здесь: clang.llvm.org/cxx_status.html. Только замечу, что C++11 доступен только в iOS ≥ 5.0.

                                                                                          Можно ли писать только на с++, вообще не используя синтаксис Objective C
                                                                                          Можно. Хотя, конечно бОльшая часть API в iOS — на Objective-C (оставшаяся часть — на чиcтом C), и использовать его всё равно придется.

                                                                                          А то этот язык уж очень опасен своей работой с памятью, кучей с сложностей с подсчетом ссылок, в то время как на с++ с его деструктуроми и перегрузкой операторов подсчет ссылок делается практически прозрачным и автоматическим.
                                                                                          Это вы зря. Мне после C++ было наоборот намного приятней работать с Objective-C. А после недавнего введения ARC (Automatic Reference Counting) вообще просто сказка.
                                                                                            0
                                                                                            Правильная ссылка: clang.llvm.org/cxx_status.html
                                                                                              0
                                                                                              Ну, у меня нет опыта с Objective C. Я просто как то на синтаксис взглянул и ужаснулся, что там будет твориться, если случился Exception. Это ж в каждой функции надо блок finally писать. Код по сравнению с с++ получается просто нечитаемым. Впрочем, может это впечатление у меня с непривычки. Но пока я бы предпочел первым делом сделать с++ обертки для всех системных библиотек и забыть про эту нахлобучку на с.
                                                                                                0
                                                                                                Exception в Objective-C(без GC) практически не применяються, только для каких то критических событий после который программа уже не может продолжать свое выполнение.
                                                                                                А код на Objective-C на порядок читабельнее кода на большинстве других языков, особеннос по сравнению с С++ :)
                                                                                                  +1
                                                                                                  Наверное, потому и не используются, что они там прилеплены для галочки. Он вообще весь какой то внутренне противоречивый, на мой взгляд. Я не верю, что код, который делает одно и то же на с++ будет выглядеть сложнее, просто потому, что у с++ возможностей больше, хотя бы деструкторы. На Objective C читабельнее могут быть только очень простые программки. Чуть только что посложнее, и всё, жопа, память потеряна, обработка ошибок из миллиона строк.

                                                                                                  Повторяю, это всё имхо, впечатление возникло от первого знакомства с синтаксисом.
                                                                                                    0
                                                                                                    Ну так в этом и проблема, познакомтись с ним поближе и все пройдет) А код на С++ будет выглядеть сложнее как раз таки потому что в С++ больше возможностей. Весь Objective-C описыватеся очень небольшим набором концепций, в то время как в С++ разных тонкостей гораздо больше. А если говорить про имхо, то лично для меня С++ выглядит как уродливый набор разного рода фич который делали с мотивацией вида: «А не добавить ли на фичу <названиефичи>», а не затем что она действительно нужна. Помоему один из отцов основателей нашей индустрии говорил, что формальная граматика хорошого языка должна занимать не больше пары страниц, Objective-C думаю сможет уложиться в пару страница, а С++ точно нет :)
                                                                                                      0
                                                                                                      Может быть. :) Я просто хорошо знаю с++ и он мне кажется очень логичным и целостным, а Objective C нет, и первое знакомство повергло меня в ужас. А у вас обратная ситуация. Может, я не успел ухватить общую картину. Будем надеяться.
                                                                                                        0
                                                                                                        Да он вам понравиться, я знаю двух С++ разработчиков которые по началу тоже плевались на Objective-C, а сейчас уже во всю на не нём под iOS пишут, причем вполне успешно.
                                                                                                          0
                                                                                                          Надеюсь. Слава Джобсу, переход на Objective C облегчен поддержкой с++. То есть использовать именно Objective C можно именно там, где это действительно удобно. Такие случаи, конечно, есть.
                                                                                                            0
                                                                                                            Если вы планируете, что в будушем ваш проект будут поддерживать другие люди, то я крайне не рекомендую использовать С++ в нем, если это конечно не игра с каким то кросплатформенным движком. Это позволит вам избежать проклятий в свою сторону от будуших разрабов, так как поддержка кода на смеси Objective-C и C++ то еше удовольствие :)
                                                                                                              +1
                                                                                                              Это уж точно, Objective-C++ та еще жесть.
                                                                                                              Главное прочесть внимательно гайды и примеры от Apple, проникнуться идеологией Objective-C и apple coding convention. Тогда и код будет получатся красивый и кочественный, и отвращение к синтаксису очень быстро перерастет в симпатию.
                                                                                            –1
                                                                                            Все языки одинаковы. API и project environment разные. И не пугайтесь Вы alloc release. В С никто не забывает malloc free, а если и забудет — никто не умрет.
                                                                                              –4
                                                                                              Для говнокодеров, если руки из жопы — то уже ничего не поможет, кроме gc.
                                                                                                0
                                                                                                Вы забываете, что это не компьютер и общее количество памяти, а так же память на одну программу в iOS сильно ограничена. Поэтому «а если и забудет — никто не умрет» тут не подходит. Да, мелкие утечки я согласен, в принципе не страшно. А если вы забыли удалить какой-либо крупный объект? С учетом того, что приложения обычно юзеры не закрывают, а просто сворачивают и они так и висят месяцами. Рано или позно юзер развернет приложение и получит креш, если мы забыли удалить что-то крупное.
                                                                                                  0
                                                                                                  Вы всё-таки перегнули палку на счет «месяцев». Обычно висит в памяти 3-4 приложения. Запускаете что-то крупное, какой-нибудь Infinity Blade — и всё, все отправляются в «terminate».
                                                                                                    0
                                                                                                    У меня и их знакомых висят штук 20. Никто terminate не получает, а предупреждения по логам сыплются
                                                                                                    0
                                                                                                    Почему это он креш получит? если програма висит месяцами, то она там неисполняется, а просто висит.
                                                                                                      0
                                                                                                      Прочитайте внимательнее «юзер развернет приложение » (и в этот момент в очередной раз будет выделяться память на что-то здоровое).
                                                                                                  –1
                                                                                                  Да уж, у Objective C растёт не только популярность, но и возраст — скоро 30 лет ему исполнится. Неужели платформы Apple нативно не поддерживают более современные языки?
                                                                                                    +1
                                                                                                    Может, потому, что Apple всегда особенная, и по особенному смотрит на вещи? :)
                                                                                                      0
                                                                                                      Эм, а подскажите мне язык, сочитаюший в себе высокую скорость выполнения, динамизм и простоту уровня Objective-C?)
                                                                                                        0
                                                                                                        С++?
                                                                                                          +1
                                                                                                          простоту? серьезно? по вашему С++ простой язык? И в любом коде на С++ легко разобраться? Тем более С++ не очень хорошо подходит для GUI фреймворков.
                                                                                                            0
                                                                                                            та и с динамизмом у С++ не очень.
                                                                                                              0
                                                                                                              Я не буду об этом спорить, соглашусь только, что Objective C выглядит (и, похоже, является) компромиссом. В результате при напмсании программ на нем, даже в случае хорошего фреймворка, надо быть чрезвычайно аккуратным, потому что компилятор ни хрена не проверяет и многие конструкции языка плохо взаимодействуют друг с другом.

                                                                                                              В с++ все гораздо лучше. Там можно написать фреймворк, которым легко и безопасно пользоваться. В том числе и гуевый.
                                                                                                                0
                                                                                                                Другое дело, что такого фреймворка, может и не написано, но это как раз вина Apple.
                                                                                                                  +1
                                                                                                                  да все там хорошо с компилятором, все что нужно в рамках языка и идеологии он проверяет.
                                                                                                                  вы просто не разобравшись в новом, начинаете защищать знакомое.

                                                                                                                  я не фанат объектно-ориентированной идеологии разработки (мне ближе категории которыми оперирует процессор а не «очеловеченные» абстракции), но что касается реализации ООП в С++ — то это, тот еще костыль. Почитайте про смалталк хотя бы.
                                                                                                                    –1
                                                                                                                    Не будем разводить холивар, я действительно очень поверхностно знаком с objective c.

                                                                                                                    Понятно, что и с++ и objective c оба являются надстройкой над с. Только при этом, на мой взгляд, с++ в этом отношении более качественный. Потому что мне ближе именно Ооп подход, и возможность сосредоточения на реальной задаче, а не на борьбе со счетчиками ссылок. В с++ есть деструкторы, в Java хоть сборщик мусора, а в objective c всё вручную. Не знаю, как вам, а мне эта рутина претит. Особенно учитывая, что в других языках с этим всё в порядке.

                                                                                                                    То есть, проблема даже не в синтаксисе аля смолтолк, а в том, что привнесенные объекты в обжектив с не образуют полную инфраструктуру, как объекты в с++
                                                                                                                      0
                                                                                                                      Вы не разобрались и делаете поспешные выводы, на основе слухов и домыслов.
                                                                                                                      В objectivec используется GC (например, в маке).

                                                                                                                      Что касатеся ифона, там собрщик мусора — гусенечный привод для телеги, поэтому в первых версиях ввели ручное управления счетчиками.
                                                                                                                      Но сейчас с появлением ARC (полгода как уже), об этом можно забыть и писать как для больших платформ, все будет учтено автоматом.
                                                                                                                      В результате стало проще писать и производительность кода осталось на высоком уровне… да и утечек теперь будет меньше ибо все учитывае автомат.
                                                                                                                        0
                                                                                                                        ну если так, то уже легче жить. Спасибо за надежду. Может, и подружимся с Objective C.
                                                                                                                        –2
                                                                                                                        Чем dealloc не деструктор? Какие проблемы с памятью, вы о чем? Я перешел на Obj-C с .Net, да, первое время было тяжко и не превычно без GC. Но если придерживаться пары простых правил, то никаких утечек борьбы со счетчиками ссылок и в помине нет. К тому же в XCode встроен отличный статический анализатор, который большинство тривиальных утечек памяти легко детектит.
                                                                                                            +1
                                                                                                            Можно уточнить — какие, например? Для большинства и Lisp все еще язык из будущего.
                                                                                                              +2
                                                                                                              Любые популярные на данный момент у разработчиков и активно развиваемые. При этом популярность Objective C несколько искусственна, ибо программисты вынужденно начинают писать на нём, так как видят в платформах Apple золотую жилу.

                                                                                                              Может после смерти Джобса, Apple повернётся лицом к разработчикам.
                                                                                                                0
                                                                                                                Не лезете в чужой моностырь, со своими уставами.
                                                                                                                ObjectiveC — это основной столб мак платформы. На его базе построенно все семейство OS X и все программы под мак написаны на нем с использованием апловских фреймворков.

                                                                                                                Не удивительно, что его (язык и фреймворки) перенесли на ифон, как перенесли и наработки из OS X в iOS.
                                                                                                                Тоесть разработчику под мак, что бы начать писать под ифон, необходим самый минимум телодвижений.

                                                                                                                В двух словах, все сделали в рамках устоявшихся традиций и экосистемы.
                                                                                                                А теперь на хорошую возможность заработать, привалила куча нищебродов и начинает рассказывать что кошерно, а что нет.
                                                                                                                  0
                                                                                                                  моностырь — это такой фреймворк, по типу монотач :D

                                                                                                                  P.S. очень плохо, что нельзя редактировать свои коменты…
                                                                                                            +4
                                                                                                            Я шокируюсь при одном только виде синтаксиса Objective-C. Чтобы настолько изуродовать старый добрый Си надо было постараться.
                                                                                                              +3
                                                                                                              Хорошо, что я не один такой. А то я был в таком шоке, что вообще засомневался, как можно на таком кошмаре написать неплохую иос. Objective C выглядит как сиюминутная заплатка, которую в своё время неосторожно ввели, а потом просто не оставалось сил от неё избавиться. Вот все до сих пор и мучаются. Хорошо хоть с++ все таки поддерживается.
                                                                                                                +1
                                                                                                                Я тоже шокировался синтаксису С после паскаля, в лихих 90-ых.
                                                                                                                Но ничего, мне это не помешало статить системным программистом.
                                                                                                                  0
                                                                                                                  Постараюсь в следующей статье переубедить.
                                                                                                                    0
                                                                                                                    Синтаксис не такой уж ужасный, просто непривычный. Зато сами возможности языка просто потрясающие. Чего только стоит отправка сообщений вместо вызова методов!
                                                                                                                      0
                                                                                                                      Синтаксис только кажется страшным, на самом деле, если не городить монтруозных вложенных конструкций, он очень легко читается. XCode отличная IDE, она прекрассно дописывает код, и сама расставляет скобочки там где это нужно. Просто не превычно по началу, но потом привыкаешь, и все становится намного лучше.
                                                                                                                      +2
                                                                                                                      Вижу надо продолжать. Почитал комментарии, пока план такой: философия языка (С, минимализм и вера в человека), id и его отличия от void* и Object, подсчет ссылок (почему это просто и что не так alloc/new )
                                                                                                                        0
                                                                                                                        Рекомендую практикующим Obj-C программистам к ознакомлению: BlocksKit. И стиль написания и возможности из коробки помогают писать интересные вещи, для которых раньше требовались обходные пути. Например заменить делегаты блоками и не писать в UIAlertViewDelegate определение, какая же это мессага закрылась сейчас.
                                                                                                                          0
                                                                                                                          возможно, вы сможете написать об этом статью? Чтобы таким новичкам, как я, легче было проникнуться ;)
                                                                                                                            0
                                                                                                                            Откройте документацию на сайте, там достаточно примеров к большинству методов.
                                                                                                                              0
                                                                                                                              если вы об этом, то всё-же хорошая статья с примером «документации на сайте» не помешает :)
                                                                                                                          0
                                                                                                                          Хорошая статья. Сам джавист и тоже в свободное время начал почитывать про objC. Многое непривычно, но этого и стоило ожидать. У меня например есть коллега, который с java на хаскель перешел. И ниче — доволен))
                                                                                                                            0
                                                                                                                            Вы будете удивлены, но большинство полезных концепций реализовано в Java в том или ином виде.

                                                                                                                            > Посылаем, а не вызываем, сообщения, а не методы

                                                                                                                            В Java есть класс Proxy, позволяющий генерить обертки для объектов. Кроме того, концепция давно знакома любителям AOP и Spring. Посылка же сообщений чаще всего предполагает именно асинхронный обмен данными, что в Java достигается помощи популярной ныне модели Actors. В данном же случае эта операция имеет свойства именно вызова функции (один тред, стек, блокирующий вызов). Так что можно сильно спорить по поводу корректности терминологии.

                                                                                                                            > Серьезный шок: любой может испортить мой класс, а не только я

                                                                                                                            Производные от Java языки типа Groovy, Xtend, Kotlin имеют похожую концепцию расширений (class-extensions). Причем сам класс никак не «портится», это только алиас функции, которая работает над классом в текущем namespace.

                                                                                                                            > Совсем шокирующее: неинициализированные ссылки не портят почти ничего

                                                                                                                            Оч. и оч. спорное «улучшение». Это нормально для «скриптовых» языков с нестрогим контролем типов, типа Groovy. В производных языках (Scala, Kotlin, Fantom) взяли концепцию nullable types от C#. Автоматический контроль null програмистам Java должен быть знаком от J2EE/EL и JavaFX Script.

                                                                                                                            Вот что действительно шокирует, так это синтаксис Objective-C, непохожий ни на один из привычных языков. Но это дело привычки.
                                                                                                                              0
                                                                                                                              > Автоматический контроль null

                                                                                                                              А можно подробнее?

                                                                                                                            Only users with full accounts can post comments. Log in, please.