Objective c язык программирования для чего

Objective-C с нуля

Банальная теория возникновения ООП

Проблема повторного использования написанного кода и его переносимость постоянно заставляет программистов искать все новые пути его упорядочивания, структуризации и абстрагирования. Для решения этих проблем создаются новые парадигмы программирования, шаблоны проектирования, новые языки, компиляторы и стандартные библиотеки к ним, программные платформы и фреймворки. Так образовались парадигма подпрограмм (процедур), реализуемая при помощи процессорных команд CALL\RET и стека (по сути, перенос потока выполнения по адресу произвольной, а не следующей за текущей команды, с последующим возвратом). Затем, парадигма модулей (каждый файл – отдельная единица трансляции), породившая двухэтапную трансляцию: компиляция модулей, а затем их компоновка (статическая или динамическая) в исполняемый модуль.

В следствии увеличения объема кода в проектах и сложностей его поддержки, с 1960х начинает образовываться новая, объектно-ориентированная парадигма программирования, разбившая программы на еще более мелкие составляющие – типы данных. Ее суть заключается во взаимодействии сущностей (объектов) посредством посылки друг другу сообщений. Каждый объект является переменной определенного программистом типа данных (так называемого класса). Определение такого специального пользовательского типа данных (класса) заключается в двух вещах: определении набора данных (инвариантов, членов) и набора подпрограмм (методов), которые будут их обслуживать.

Objective c язык программирования для чего. Смотреть фото Objective c язык программирования для чего. Смотреть картинку Objective c язык программирования для чего. Картинка про Objective c язык программирования для чего. Фото Objective c язык программирования для чего

Класс обычно оформляется как определенный программистом тип, основанный на встроенных (языковых) типах данных и\или других классах. Для языка С, не поддерживающего объектно-ориентированную парадигму, это может быть структура (struct). А набор подпрограмм реализуется как обычные функции, обязательно принимающие как минимум один параметр — указатель на набор данных, подлежащих обработке.

Основным преимуществом объектно-ориентированного подхода стала возможность создавать новые классы на основе уже написанных (добавлять инварианты и методы, переопределять методы, использовать определенные в базовом классе методы как свои), названное наследованием.

Objective c язык программирования для чего. Смотреть фото Objective c язык программирования для чего. Смотреть картинку Objective c язык программирования для чего. Картинка про Objective c язык программирования для чего. Фото Objective c язык программирования для чего

Набор методов представляет собой интерфейс для взаимодействия с инвариантами. Невозможность непосредственной модификации данных класса (без задействования его интерфейса) отражает принцип инкапсуляции. На рисунке показан класс и его объекты. Имеется инвариант x типа float и к нему интерфейс (метод) doubleX, возвращающий значение инварианта.

Бывает, что необходимо послать сообщение объекту, который на него определенно отвечает (т.е. вызвать для объекта класса такой метод, который он реализовал), но, по ситуации, конкретный класс этого объекта неизвестен. Например, каждому элементу списка указателей на объекты класса Auto нужно послать сообщение Move, а известно что в списке находятся указатели на объекты не только класса Auto, но также и указатели на производные (наследованные) классы Ford и Subaru. Это возможно сделать только благодаря принципу полиморфизма, заключающегося в том, что при посылке определенного сообщения объекту из некой иерархии классов, в которой все объекты способны принять такое сообщение, этот объект реагирует на него соответственно своему, а не базовому для данной иерархии классу.

Первым языком с поддержкой объектно-ориентированного подхода стал Simula67. Затем появился Smalltalk. А в 80х начал оформляться С++ — основной язык современного системного программирования. Его расширение и усовершенствование в 90х породило ряд парадигм и шаблонов проектирования, и оказало необратимое влияние на современное видение объектно-ориентированного подхода, в том числе, и на язык Objective-C.

Чуть-чуть истории

Objective-C возник в 80-x как модификация С в сторону Smalltalk. Причем модификация эта состояла в добавлении новых синтаксических конструкций и специальном препроцессоре для них (который, проходя по коду преобразовывал их в обычные вызовы функций С), а также библиотеке времени выполнения (эти вызовы обрабатывающей). Таким образом, изначально Objective-C воспринимался как надстройка над C. В каком-то смысле это так и до сих пор: можно написать программу на чистом С, а после добавить к ней немного конструкций из Objective-C (при необходимости), или же наоборот, свободно пользоваться С в программах на Objective-C. Кроме того, все это касается и программ на С++. В 1988 NeXT (а в последствии Apple) лицензировала Objective-C и написала для него компилятор и стандартную библиотеку (по сути SDK). В 1992 к усовершенствованию языка и компилятора подключились разработчики проекта GNU в рамках проекта OpenStep. С тех пор GCC поддерживает Objective-C. После покупки NeXT, Apple взяля их SDK (компилятор, библиотеки, IDE) за основу для своих дальнейших разработок. IDE для кода назвали Xcode, а для GUI – Interface Builder. Фреймворк Cocoa для GUI разработок (и не только) на сегодня является наиболее значимой средой разработки программ на Objective-C.

Особенности Objective-C

Обмен сообщениями

Чтобы заставить объект выполнить какой-нибудь метод нужно послать ему сообщение, именуемое так же, как и требуемый метод. Такое сообщение называется селектор метода. Синтаксис посылки таков:

Objective c язык программирования для чего. Смотреть фото Objective c язык программирования для чего. Смотреть картинку Objective c язык программирования для чего. Картинка про Objective c язык программирования для чего. Фото Objective c язык программирования для чего

В сообщении можно передавать параметры для вызываемого метода:

Перед каждым параметром необходимо ставить двоеточие. Сколько двоеточий – столько и параметров. Имя метода может продолжаться после каждого такого двоеточия-параметра:

Методы с неограниченным количством аргументов вызываюся следующим синтаксисом:

Посылка сообщения, как и любая функция C, возвращает определенное (может void) значение:

При посылке сообщения nil оно просто пропадает. При посылке сообщения объекту, который принадлежит классу, не реализовавшему заказанный метод, возникает исключение, которое, будучи не перехваченным, приводит всю программу к незапланированному завершению. Для проверки, отвечает ли данный объект на кокое-либо сообщение можно использовать следующий шаблон кода:

Как работает передача сообщений

Посылка сообщения транслируется в С-функцию с прототипом:

Тип SEL, по сути, определен как char const *, но лучше воспринимать его как int, поскольку во время выполнения все селекторы индексируются целыми значениями согласно глобальной таблице селекторов.

Objective c язык программирования для чего. Смотреть фото Objective c язык программирования для чего. Смотреть картинку Objective c язык программирования для чего. Картинка про Objective c язык программирования для чего. Фото Objective c язык программирования для чего

Пользуясь инвариантом isa объекта receiver (при использовании фреймворка Foundation, базового для Cocoa, все классы должны наследовать класс NSObject, поэтому наличие isa неизбежно), эта функция просматривает локальный список селекторов класса с целью определить, отвечает ли объект данного класса на сообщение method. Если такой селектор находится, то управление передается соответствующему методу класса, которому передается id объекта (указатель на его инварианты) и указанные после селектора параметры функции objc_msgSend(). Значение, возвращенное методом, отдается как результат посылки сообщения. Если у объекта-приемника данный селектор отсутствует, функции objc_msgSend() просматривает список селекторов его базового класса.

Objective c язык программирования для чего. Смотреть фото Objective c язык программирования для чего. Смотреть картинку Objective c язык программирования для чего. Картинка про Objective c язык программирования для чего. Фото Objective c язык программирования для чего

При такой схеме вызов, например:

Так как в глобальной таблице селекторов 12 соответствует строке “addObject:”. Далее функция objc_msgSend() выполняет поиск по списку селекторов объекта receiver и, найдя его (пусть это объект класса NSArray, который реализовал метод с селектором 12), производит вызов типа:

Объявление метода

Интересно отметить, что прототип метода addObject из предыдущего раздела в объявлении класса выглядел так:

То есть принимал всего один параметр. Но, исходя из принципа объектно-ориентированной парадигмы, что методы – это подпрограммы, обрабатывающие определенные наборы данных, методу необходимо передавать адресс данных, подлежащих обработке. Поэтому такой параметр передается во всякий метод класса неявно. Компилятору об этом дополнительном параметре дает понять минус («-«), стоящий первым в прототипе метода. Такой метод (с минусом впереди) называется методом объекта (или экземпляра), т.к. может быть вызван только для объекта какого-нибудь класса. В теле метода этот указатель на экземпляр данных (или адрес объекта, которому послали сообщение) доступен посредством зарезервированного слова self (аналог this в С++), а указатель на экземпляр базового класса – через зарезервированное слово super. Кроме того, в метод объекта также передается неявный параметр _cmd – селектор этого метода из глобальной таблицы селекторов. С точки зрения программиста С++ все методы объектов в Objective-C как-будто объявлены с ключевым словом virtual, и всегда следуют динамическому полиморфизму.

Если в начале прототипа метода поставить знак плюс (“+”), то такой метод будет считаться методом класса, и, естественно, не будет принимать неявный параметр self (это аналогично объявлению static-метода в С++). А без инварианта isa объекта, на который указывает self, указатель super работать, конечно, тоже не будет.
Таким образом, прототип любого метода объявляется так:

Если метод возвращает некий объект (тип id) или класс (тип Class), можно воспользоваться вложенным синтаксисом вызова:

Здесь объекту класса UILabel из фреймворка UIKit устанавливается значение инварианта text равное строке @”Hello world”. Эта строка, в свою очередь, образована конкатенацией строк @”Hello” и @” world”. Первая является результатом посылке сообщения stringWithString классу NSString с параметром-константой @”Hello”. Такой вызов возвращает объект класса NSString, инициализированный строкой-параметром. Затем этому объекту посылается сообщение stringByAppendingString с параметром @” world”. Результат посылки этого сообщения и есть объект класса NSString, содержащий конкатенацию значения объекта-приемника и строкового аргумента. Этот объект и попадает как параметр в сообщение setText: объекта myLabel.

Объявление класса

Объявим простой класс комплексного числа в файле Complex.h:

Как видим, все объявление заключено в ключевые слова interface и end. Первым делом объявляются инварианты (в фигурных скобках). Вне фигурных скобок объявляются методы. Метод description отсутствует в объявлении класса не случайно. Дело в том, что он, как и метод dealloc и init, присутствует в определении класса. При посылке объекту класса Complex сообщения description будет рассмотрен его локальный список селекторов, куда, после компиляции, попадут селекторы всех методов, реализованных классом этого объекта, даже не объявленные в интерфейсной части. То есть init, description и dealloc будут вызывать абсолютно корректно.

Создание объектов

В связи с тем, что все объекты распределяютя в динамической памяти, cоздание объекта приходится проводить в два этапа: 1) выделении памяти (сообщение alloc) и 2) инициализация инвариантов (конструкторы класса).

После создания объекта им можно смело пользоваться:

Некоторые классы обладают методом для быстрого (в один этап) создания собственных экземпляров. Такие методы являются методами класса, возвращают указатель на объект своего класса и их имя обычно начинается с названия самого класса. Например метод:

Возвращает уже готовую строку, инициализированную соответствующей сторокой с завершающим нулем, без вызовов alloc и init:

Время жизни объекта

Реализация init очень важна. Это конструктор класса. Конструкторы отличаются тем, что возвращаеют id и их названия всегда начинается со слова init, а конструктор по умолчанию – это и есть просто init. Схема любого конструктора примерно следующая:

Вот типичный специализированный (не по умолчанию) конструктор для класса с двумя членами типа некоторого класса и одним целочисленным инвариантом:

Реализация release и retain для NSObject идеологически примерно следующая, и ее не нужно переопределять в производных классах, в силу отсутствия доступа к инварианту счетчика ссылок:

То есть самому объекту посылается сообщение dealloc, в реализации метода которого он может, по необходимости, уменьшить счетчики своих инвариантов и передать аналогичное сообщение объекту базового класса, чтобы он сделал то же самое. Очевидно, реализация метода dealloc для NSObject освободит память, выделенную объекту. Обычно dealloc для какого-нибудь класса выглядит так:

Методы доступа

Правильная работа с подсчетом ссылок очень важна при возврате адреса объекта из метода или инициализации инварианта формальным параметром. Обычно такими вещами занимаются так называемые методы доступа, возвращающие и устанавливающие инварианты объектов. Принято именовать метод, возвращающий значение инварианта, так же как и инвариант, а имя метода, устанавливающего его значение, начинать со слова set:

Так как инвариант _re относится ко встроенному типу, никаких сложностей с изменением его значения не возникает. Но если инвариант – объект некоторого класса – то простым присваиванием не обойтись, ведь надо учитывать счетчики ссылок. Для решения этой проблемы применяются следующие три метода:

Вариант №3 не очень удачный потому, что засоряет текущий самовыгружаемый пул, а обычно это не очень желательно (см. следующий раздел).
Метод доступа для чтения значения инварианта всегда очень прост:

Самовыгружаемый пул в нитях программы

Теперь попробуем вернуть из метода созданный внутри него объект:

Строка формата соответствует стандарту языка С. Но если в ней необходимо указать тип id, то используется спецификатор формата %@. Каким образом метод, разбирающий формат, понимает какие символы подставить вместь id? Он просто подставит то, что вернет метод описания description данного объекта. Этот метод изначально объявлен для класса NSObject. NSString переопределил его на вывод своего строкового содержания. Переопределив его, любой объект может представлять свое строковое содержание. Например, так это может сделать класс комплексного числа с двумя инвариантами типа double:

После выполнения метода sayHelloToName:withSurname: определенно произойдет утечка памяти, так как вызывающий код скорей всего не догадывается, что возвращенному объекту нужно после обработки послать сообщение release. Даже если он догадается это сделать, возможно, что возвращался указатель на инвариант объекта, а значит его уничтожение чревато серьезными последствиями. Хотелось бы иметь механизм самоосвобождения объектов когда либо в будующем, чтобы пользовательский код вообще не думал об их освобождении. Решается эта проблема с помощью объекта класса NSAutoreleasePool – самовыгружаемого пула объектов.

После создания объекта такого класса всем объектам, созданным после него, можно послать сообщения autorelease. При этом данный объект помещается в текущий (последний созданный) самовыгружаемый пул. Когда некий пул получит сообщение release, то он отошлет такое же сообщение и всем своим объектам, уменьшая их счетчик ссылок (по сути, уничтожая). Таким образом. Объект, помещенный в самовыгружаемый пул, продолжает жить и занимать память во все время жизни пула. Это удобно для небольших временных объектов, но может с течением времени занять значительную часть памяти. Потому рекомендуется циклы, способные порождать большое количество временных объектов, которые отправляются в самовыгружаемый пул, обрамлять локальными (вложенными) пулами.

Любая нить в программе, использующей Cocoa, должна создавать объект класса NSAutoreleasePool в самом начале (прежде создания других объектов), и в самом конце его уничтожать (после уничтожения всех других объектов). Функция main(), являющаяся главной нитью любой программы на Objective-C, при использовании фреймворка Cocoa должна всегда выглядеть вот так:

А корректный метод sayHelloToName:withSurname: теперь будет выглядеть вот так:

К слову, метод drain самовыгружаемого пула аналогичен release с той лишь разницей, что, кроме освобождения себя самомго и всех содержащихся объектов, еще дает подсказку сборщику мусора вступить в игру. Однако, это актуально только для Mac OS 10.4 и выше, так как на iOS сборки мусора нет.

Определение класса

Теперь рассмотрим файл Complex.m с определением методов класса Complex:

Конструктор по умолчанию вызывает специализированный конструктор с определенными начальными параметрами. Метод complexWithRe:andIm: возвращает инициализированный объект класса Complex, размещенный в текущем самовыгружаемом пуле. То же самое делает и метод description, возвращая объект класса NSString. Вот пример программы, где используется класс Complex:

Категории и расширения

Если к уже написанному (а, возможно, и откомпилированному) классу нужно добавить\переопределить некоторые методы без наследования – категории позволяют это сделать без особых усилий:

А пользоваться этим можно вот так:

Расширения несут добрую службу как безымянные категории:

Протоколы

Протокол Objective-C – это формализованное объявление группы методов, которые, по желанию, может реализовать любой класс (аналог класса в С++, где все методы объявлены со спецификатором virtual … = 0). В версии языка 2.0 методы протокола могут быть требуемыми (спецификатор @required, он считается умалчиваемым) и выборочными (спецификатор @optional). Если какой либо класс реализовал требуемые методы протокола, то он называется классом, поддерживающим данный протокол. Протокол, и класс, его поддерживающий, объявляются вот так:

Oбъекту класса MyPrinter можно гарантированно посылать сообщения print и switchedOn, и, после проверки на respondsToSelector:, можно посылать сообщение loadPaper:, та как в его реализации должны присутствовать определения одноименных методов. Объявление объекта класса, поддерживающего какой-либо протокол осуществляется так:

Кроме того, один класс может удовлетворять нескольким протоколам. Для этого их можно перечислить через запятую в угловых скобках в объявлении класса.

А чтобы объявить объект неизвестного класса (id), соответствующий некоторому протоколу, пишут так:

Исключения

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

Исключение – это объект некоторого класса. Он (даже своим типом) несет в себе некоторую информацию о произошедшей ситуации. Для удобства в Cocoa имеется класс NSException, который можно инициализировать двумя объектами NSString и одним объектом произвольного класса (тип id):

Сгенерировать исключение и, тем самым, запустить механизм раскрутки стека вызовов, можно с помощью оператора @throw. Чтобы перхватить сгенерированное исключение, участок кода, где возможна его генерация, необходимо заключить в специальный блок с заглавием try (такие блоки могут быть вложенными). А затем, после этого блока, поставить блок с заглавием catch(), где в круглых скобках указать тип предполагаемого исключения. Блоков catch() после блока try может быть несколько. После генерации исключения управление, раскручивая стек, выходит из блока try и, проверяя по очереди все блоки catch(), попадает именно в тот блок catch(), в фигурных скобках которого стоит такой тип, к которому тип исключения приводится неявно (точное совпадение, указатель на базовый класс или id). Если исключение по типу не совпало ни с одним блоком catch(), управление продолжает раскрутку стека. Если после блока с заглавием try стоит блок с заглавием finally, то управление передастся ему независимо от того, произошло ли в блоке try исключение (и обработан какой-нибудь блок catch()), или выполнилась его последняя инструкция. Ниже приведен пример работы с объектом класса Cup в методе fill которого происходит исключение:

В блоке finally удобно освобождать ресурсы, выделенные в блоке try, но не освобожденные по причине сгенерированного исключения.

Свойства

Для версии Objective-C 2.0 нашa реализация класса Complex явно избыточна: в ней слишком много методов доступа и их определение – сплошная рутина. Перепишем его с использованием свойств:

Источник

Objective-C как первый язык программирования

Данный пост был задуман после того, как на некоторые важные вопросы не было найдено внятных ответов. Я отнюдь не претендую на то, что стал крутым программистом. Нет, всё ещё впереди, но период высиживания уже пройден. Это статья из цикла «Не умеешь сам — научи другого». В смысле, чтобы что-то лучше понять нужно это что-то, кому-то объяснить. Мопед не мой, эта фраза встречалась мной раньше в публикациях на Хабре. Некоторые вещи очень сложно понять. И люди, которые понимают, обычно не могут объяснить начинающему. Может быть меня тоже это ждёт. Это как разговор взрослого и ребёнка. Практически конфликт поколений. Пока мой уровень не перерос в профессионала, нужно изложить моё текущее видение.

В статье, термины которые используются при объяснении различных понятий взяты в кавычки. Статья написана для людей, которые уже научились отличать циклы от массивов и понимают что такое функция и метод.
Если Вы, никогда не программировали, то книга Кернигана и Ритчи (в любом издании), Вам явно будет не по силам. В природе не существует такой силы воли, которая смогла бы заставить Вас дочитать книгу до конца, при этом решить все приведённые задачи.
Очень рекоммендую BecomeAnXcoder. Там всё написано достаточно понятно для людей, которые о программировании знают крайне мало. Информация немного устарела, но для старта сойдёт. Может она Вам уже попадалась на глаза или вы даже скачали её, но отложили в каталог с литературой (ну такой каталог есть у каждого, он занимает десятки гигабайт и всё это мы собираемся прочитать как только появится свободное время, а каталог всё растёт. ).
Понятно, что оптимальный вариант — MAC. На худой конец — Хакинтош или виртуальная машина. И даже если процессор не позволяет запустить ничего из вышеизложенного — начать можно прямо в блокноте с последующей компиляцией в коммандной строке.
На многих форумах можно найти популярный вопрос, задаваемый людьми, которые, по-видимому находятся в тяжело-бронированном танке: «Нужно ли программисту Objective-C учить собственно С?». Везде пишут одно и то же. Те кто побородатее и начинали со структурного программирования — говорят, что просто необходимо стать, как минимум MiddleDeveloper’ом в C, и лишь потом искать путь в лютых дебрях ООП, коим является Objective-C. Те кто не знал С, но уже каким-то образом достиг статуса MiddleDeveloper’а, возражают: мол, выучи как кнопки на iPhone рисуются и как им назначить функцию, а матчасть — потом подтянется, по мере необходимости. Категорически заявляю, что выучить как кнопкам назначаются функции, не есть программирование! Я не призываю потратить полгода на понимание чистого С. Но пару недель — месяц уделить стоит. Это даст некоторый бэкграунд Вашим амбициям. По мере обучения уже Objective-C обязательно будут возникать такие структуры кода, что не будет ничего понятно. Поэтому, предлагаю безо всякого фанатизма, но детально ознакомиться с книгой Крупника А.Б. «Изучаем Си». Она раза в 3 больше предыдущей по объему, но читается легко и непринуждённо. В книге опять же, на достаточно доступном уровне, объясняются основные азы программирования. В ней можно узнать как отличить массив от цикла и что такое указатели.
Недавно на Хабре промелькнула статья, где автор приводил кучу литературы, которую советовал прочитать и пойти работать джуниором за хлеб. Если Вы просто прочитаете всю приведенную в той статье литературу, то ничему не научитесь, а если вы сможете перерешать и запомнить опять же всю литературу, то Вам можно будет идти не джуниором, а солидным разработчиком.

Начало: метод класса и метод экземпляра

Что такое метод? Это набор команд/инструкций или одна команда/инструкция, которая может быть применена к объекту и вызывает в нём необходимые процессы. Если так не совсем понятно, то читайте дальше и поймёте. На самом деле тяжело понять что такое метод класса и метод экземпляра. Все говорят: «со знаком „+“ — это метод класса, а вот со знаком „-“ — это метод экземпляра. Понятно?» И в ответ слышат: «Да-а, метод класса и метод экземпляра». Я лично сначала понимал только то что они разные, а вот что и когда применять — осталось не понятным. Википедия упорно повторяет то же самое, что мы слышали и читали.
В подавляющем большинстве случаев, Вы будете работать с методами экземпляра.
Итак, метод экземпляра. Представим, что у нас есть программа, в которой мы будем использовать 2 класса: Primus и Kitchen.
Любой класс (кроме абстрактного) имеет методы и/или функции. Класс может иметь несколько методов со знаком «+» перед названием метода (метод класса) и несколько методов со знаком «-» перед названием метода (метод экземпляра). Вот те методы, которые со знаком «-» мы активно применяем в отношении объектов — экземпляров класса и собственно класса. А методы со знаком «+» можно применять только в отношении самого класса, где этот метод был объявлен.

Что такое экземпляр класса?

Звучит гордо, но непонятно. Кто помнит из школьного курса: в геометрии точка — родитель для круга, прямой и прочих фигур, потому что каждая фигура состоит из множества точек.
Класс для Objective-C, на некоторых ресурсах интерпретируют как объект и наоборот. На самом деле это немного на так. Можно сказать что объект это экземпляр класса. Как конкретный экземпляр стоящего у Вас на кухне примуса — это экземпляр типа «Примус»: с крутилками, горелкой и пр. Это не просто примус — это Ваш примус. Класс — это пример для подражания. Образец-эталон чего-то, что тоже может исполнять некоторые функции благодаря методам класса (со знаком «+»). Вот здесь можно прочитать немного более развёрнуто.
Также есть «протоколы» и «абстрактные классы». Здесь всё более интересно, но порог понимания выше чем у класса и объекта. Различие состоит в том, что «протокол» не может иметь подкласс или дочерний объектно его на наследуют, ему нужно соответствовать. Как требованию при приёме на работу. Применение протоколов в реальной жизни я затрону в этой статье. Абстрактный класс — это такая сущность, которая как бы класс, но не совсем конкретный класс, потому и абстрактный. Например опять же, Ваш домашний примус — он экземпляр класса «Примус», а не какого-то абстрактного класса «Нагревательный прибор». Вы же не можете иметь дома нагревательный прибор без рода и племени (это может быть также камин и батарея). Вот таким образом, класс «Примус» — может быть наследником абстрактного класса «Нагревательный прибор». А уже Ваш примус — экземпляр конкретного определения примуса. И за своими атрибутами — свойствами, методами, протоколами он при использовании обращается к своему классу и сверяет что он может делать что не может и что он вообще может иметь в наличии.
Представим что есть некий класс «Горелка газовая» — наследник абстрактного класса «Нагревательный прибор». Класс «Горелка газовая» будет родительским для «Примуса» и «Газовой плиты». Для того, чтобы приблизиться к программированию, нужно немного абстрагироваться.
В Objective-C есть родительский класс NSObject. В языке программирования он как точка в геометрии. Это идеальный класс: в нём нет ничего лишнего, он ничего конкретного делает, но из него можно создать всё что угодно. Такой вот кирпичик мироздания. Если в Xcode зажать кнопку «Command» и кликнуть на NSObject, то перед Вами откроется содержимое файла NSObject.h. В нём около 200 строк описания различных методов. Есть как методы со знаком «+» перед названием, а также методы со знаком «-«. Суть методов со знаком «+» такова что их можно применить только непосредственно к самому NSObject. Таким методом является, например,

и применять его можно только так:

Любой другой объект в Objective-C по определению — потомок NSObject. В нём реализовываются дополнительные методы, которые придают ему черты индивидуальности. Допустим это NSResponder. У этого потомка — NSResponder’а тоже могут быть дочерние объекты. К примеру UIView. Далее по древу наследования можно в качестве примера взять UIScrollView. Потом — UITableView. В каждом случае потомки обрастают дополнительным функционалом. Кроме того, что они умеют делать что-то своё, индивидуальное, они могут делать всё то что может делать их предок. Это и есть — наследование.
Если же вы не хотите, чтобы Ваш класс-потомок абсолютно точно копировал поведение класса-родителя, то можно переделать любой метод класса — родителя по Вашему вкусу. Это есть — полиморфизм.
В Ваших программах вы будете брать нужный Вам класс и добавляя в него нужные методы — расширять его функционал. Также можно брать созданный Вами класс и делать его потомка, опять же расширяя функционал и одновременно создавая уникальный инструмент, для решения нужной задачи. Описанный механизм называется — создание подклассов «subclass».
Не буду вдаваться в широкие описания методов со знаком «+». Нагляднее будет показать, что применение метода

к любому классу или подклассу выделяет под него нужный объём памяти в ОЗУ компьютера.

инициализирует объект, выделяет для него место в ОЗУ и собственно после этого объект начинает существовать и с ним можно работать.

Эти 2 метода («alloc» и «init») только что создали объект «object». И данный объект является экземпляром объекта или экземпляром класса NSObject. Если применить эти методы по раздельности

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

выделил для него такой адрес в памяти

Так происходит потому что при инициализации, исполняемая среда, всем объектам задаёт значение «nil», чтобы избежать ссылки на место в памяти, заполненное «мусором». Или ссылки на другой конкретный объект, который по факту тоже уже является «мусором», потому что он закончил свой жизненный цикл и уже не «хранится» в памяти, а просто «находится». Для того чтобы понять что такое «мусор», создайте простейшую программку, в которой объявите

не присваивая ей значение, а потом выведите её значение в консоль

Вы будете удивлены тем, чему равняется Ваше «i».
Также будет создан экземпляр объекта «isa», который будет рассмотрен позже. Это единственный ненулевой указатель при создании Вашего объекта. Допустим, это ниточка к родительскому объекту, который породит свой экземпляр и даст жизнь нашему объекту.
То есть теоретически объект уже есть после применения метода «alloc». Но он не сможет пройти проверку

Такой кусок кода можно видеть в любом шаблонном объекте в методе «init» или его производных.
В данном случае, объект вроде как есть, но в принципе он равен «nil». Не инициализированный объект — это как машина, которую Вы только собираетесь купить в кредит. Вроде как есть, но она не Ваша. И если не отходя от кассы применить метод «init»

то «Бинго!», и объект принадлежит Вам, с ним можно делать всё что хотите. А вот если к нему применить метод

то инициализироваться может другой объект. Вроде как вы выплатили кредит за машину, но оказалось что не за ту машину и Вам вместо одного автомобиля дают другой. Они на первый взгляд не отличимы друг от друга. Но у них разные «VIN» номера, а значит при проверке на посту «ГАИ» Вам сообщат что авто не Ваш. Ниже будет приведено дополненное объяснение этого явления.
Как Вы уже поняли метод «+alloc» — метод класса, а метод «-init» — метод экземпляра.
Приведу пример с реальными вещами.
Полная реализация метода включает в себя обычно 2 файла с расширениями *.h и *.m. Бывает и другое количество, в зависимости от того, что это за класс и какие цели он преследует.
В Вашей программе есть класс «Primus». В файле «Primus.h» объявлены методы:

Также в программе есть класс «Kitchen», где в файле «Kitchen.h», объявлены методы:

В файлах «Primus.m» и «Kitchen.m» все объявленные методы должны быть реализованы, то есть описаны: как и что в каждом методе происходит.
Если вы собираетесь в каком-либо классе создавать экземпляр объекта другого класса, то в шапке нужно будет импортировать файл *.h создаваемого объекта, например в шапке файла Kitchen.h мы впишем

Для начала создадим экземпляр класса «Primus» внутри класса «Kitchen»

Как видите, мы посылаем метод c «+» не экземпляру класса «myPrimus», а непосредственно классу «Primus». Экземпляр класса «Primus» под названием «myPrimus» создан. В дальнейшем, методы из «Primus.h» со знаком «-» будут применяться к экземпляру класса — «myPrimus». И если захотим создать новый экземпляр класса «Primus», то можно будет опять воспользоваться методом «+hotAsHell». Также в классе «Primus» есть метод

Обычно все методы, название которых начинается с «init», делают то же самое что и метод «init» класса NSObject, только с расширенными возможностями. И в данном случае применение метода «init» в таком ракурсе

создаст новый объект класса «Primus» с уникальными характеристиками.
В описанном только что примере был применён метод с аргументами. В данном, конкретном случае, он применяется для создания экземпляра класса «Primus» с чётко заданными характеристиками. По названию характеристик видно, что данный экземпляр класса «Primus» будет работать на газе типа «Propan» и при температуре 750 градусов.
Обратите внимание, что названия методов в Objective-C весьма осмысленны. Временами Вы будете поражены их названиями состоящими из 10 слов, но это способствует лучшему понимаю написанного. Грубо говоря код получается самодокументируемым. Что конечно же не исключает необходимости написания комментариев. Но если взять за правило создавать свои методы, название которых будет нести смысловую нагрузку и таким же образом относиться к созданию переменных, то количество комментариев в коде можно заметно снизить.
В отличие от некоторых других языков программирования в Objective-C методы не вызываются, а посылаются объектам. Таким образом, этот ЯП относится к «message oriented language», на русском языке звучит не так строго, поэтому перевод не привожу.
Также обратите внимание на то, что все методы которые после посылки объекту создают (возвращают) новый объект имеют в скобочках после «+» или «-» либо конкретное название объекта, экземпляр которого они будут возвращать, либо «id». То есть, по том, какой объект указан в скобочках сразу после знака «+» или «-«, можно судить что мы получим после посылки этого метода. Что такое «id»? Это такой тип объекта, который может принимать форму (тип) любого другого объекта. Скажем это «слабый» тип объекта. Не в смысле того, что ему что-то «слабо». Если говорить общепринятыми понятиями, то это слабо типизированный объект. Наличие таких объектов в ЯП делает его слабо типизированным.
Также можно в этих самых скобочках обнаружить тип «void».

Что такое «void»?

Все говорят: «это когда метод ничего не возвращает». А зачем же он нужен? Применение метода этого типа всё же производит манипуляции с объектами, структурами и цифрами. Также объекты и скалярные величины, попавшие в него в качестве аргументов могут измениться либо вообще исчезнуть. Всё зависит от того, что реализовано внутри каждого конкретного метода. Дело в том, что «void» таки ничего не возвращает… нового. Как и было сказано, то что попавшие в него аргументы могут изменяться сами, либо влиять на другие объекты, манипуляция с которыми производится в методе с «void». Он может даже создавать новые объекты внутри себя, но наружу ничего не возвращается в явном виде. Обычно метод, который возвращает что-то, имеет ключевое слово «return» в самом конце. А метод типа «void», «return» в конце не имеет. Он может его иметь внутри своих собственных циклов или условий, чтобы иметь возможность прервать их в нужном месте. Но не в конце. Метод не создаёт ничего принципиально нового, он просто, работая с указателем на какой-то объект (число, массив, ячейка и т.д.), меняет данные по этому адресу или применяет их для расчёта других данных, которые присваивает другим объектам.

Что такое «self»?

Это слово очень часто применяется где попало. Сам факт его применения во всевозможных местах, вносит путаницу в стройные кладовые Ваших знаний.
Вернёмся к классам «Primus» и «Kitchen». Возьмём конкретный метод класса «Primus» и рассмотрим как будет выглядеть его реализация в файле «Primus.m». Например это метод.

может быть реализован таким образом:

В фигурных скобках происходит реализация или «имплиментация» метода. В данном случае, реализация метода читается так: если не myPrimus, то выполнить команду

которая в свою очередь читается как: себе инициализировать с газом:gas температурой:750. То есть, метод посылается себе, а не какому-нибудь другому объекту. В данном случае «себе» — это классу «Primus», так как метод находится внутри класса «Primus». Его объявление — в файле Primus.h и реализация в файле Primus.m.
Также можно заметить, что метод ничего не возвращает «void». То есть получается каламбур: если примуса нет, то мы его создаём, но наружу он из метода не выходит. Зачем его тогда создавать? Допустим его функционал реализован так:

И тут уже понятно что где-то внутри метода появляется мастер по ремонту примуса.
Почему был использован знак восклицания «!» в скобках после «if»? В программировании это — знак отрицания. То есть «!=» звучит как «не равно». Этот способ условия удобен своей лаконичностью. В данном примере можно было использовать другое по структуре условие, которое несло бы ту же самую функцию.

Это условие имеет в 2 раза большую длину и нужно полностью читать всю строку, чтобы понять его. Это условие небольшое, но если Вам нужно записать что-то вроде этого

будет в более выигрышной позиции, как по лаконичности так и по физическому размеру. Предыдущая конструкция — банально может просто не влезть в одну строку.
Рассмотрим как выглядела бы реализация этого метода в рамках класса «Kitchen». В файле «Kitchen.m» тот же метод будет реализован так:

Видно, что здесь нужно указать, какой объект будет создаваться, как будет называться его экземпляр и потом непосредственно родительскому классу посылать метод.
То есть, хитрое слово «self», применяется внутри класса, как будто вы уже создали его экземпляр.

и обращаетесь к экземпляру класса. Только фишка в том, что вы ничего не создавали, и обращаетесь не к экземпляру, а напрямую к классу. Для наглядности я создал объект

к которому можно обратиться с методом. Но можно было его не создавать, а реализовать более сложную структуру, которая выполняла бы те же самые функции

Для того, чтобы понять можно ли написать «self» или нельзя — просто представьте себе какой метод какому объекту Вы хотите послать и начните вводить слово «self», но не до конца, например «sel». Xcode предложит несколько вариантов, среди которых будет собственно «self». Слева от него будет описание — какой это класс. Если это именно тот класс, которому вы хотели послать нужный метод (класс внутри которого вы сейчас производите действие), значит используйте «self». Если Xcode указывает, что «self» это не тот объект, который Вам нужен — то используйте имя класса или экземпляра нужного Вам.
Также видно что здесь были задействованы аргументы. У каждого аргумента есть тип, который тоже описан в скобках, но после двоеточия. После скобок с типом аргумента идёт имя аргумента. Если в скобках присутствует знак «*» после типа аргумента, то это объект. Если знака «*» нет, то это скалярный тип, например «NSInteger», который по сути является простым «int». Также «NSInteger» может быть со знаком «*» для передаваемого аргумента. В таком случае мы будем передевавать не саму переменную, а указатель на неё. Тема Указателей выходит за рамки данной статьи. Имя аргумента, в данном методе

будет звучать как «gas». Вы обратили внимание, что в реализации не было использовано нормального названия газа? Например «Propan». Дело в том, что в аргументе «gas» как раз и передаётся нужное название газа. Откуда? Мы рассмотрели как реализовуется метод

В нём был задействован метод

В этом методе было 2 аргумента «gas» и «t». В посылке метода объекту, температуру мы указали, а тип газа просто продублировали от метода

То есть этот метод тоже где-то посылается. Рассмотрим поближе метод

Его реализация может выглядеть так

Обратите внимание на значение посылаемого аргумента «propanButan». Именно оно передаётся по всему классу, от метода к методу.
Также здесь видно что метод посылается объекту при определённых условиях.
Нужно знать что ни один Ваш метод сам по себе не может сработать. Ему нужен «пинок» снаружи. Нажатие кнопки, возникновения какого-либо события или его должен запустить метод протокола, который среда исполнения запускает в нужный ей момент. Данный метод «hotAsHell» посылается лишь после явного вызова, это не системный метод, он тоже где-то должен быть прописан либо чему-то назначен.
Теперь рассмотрим метод

Он состоит из типа возвращаемого объекта, типов аргументов, аргументов и селектора. Селектор это то что остаётся от метода когда от него отнять тип возвращаемого объекта, тип аргументов, и аргументы.

именно с двоеточиями. Если аргументов нет, то двоеточий тоже нет, как в случае с «hotAsHell». Часто прийдётся сталкиваться с необходимостью употребить селектор. Теперь вы знаете что употреблять.
Немного выше было использовано понятие «super».

Что такое «super»?

Рассмотрим реализованный выше метод «hotAsHell». В нём есть такая конструкция

Так принято инициализировать дочерний класс — через инициализацию родительского.
Предположим, что класс «Primus» — непосредственный потомок класса «NSObject». Именно тот класс, который стоит по иерархии сразу над тем классом, с которым мы работаем имеет право называться «super». Команда

вызывает метод init экземпляра NSObject. То есть, автоматически создаётся экземпляр прародителя всех объектов — NSObject, с дефолтными (сугубо NSObject’овскими) параметрами. Посылка метода «init» NSObject’y возвращает «self» от NSObject’a. То есть непосредственно экземпляр самого NSObject’a. И этот экземпляр присваивается нашему объекту «Primus». Ведь «self» в данном случае — является именно «Primus’ом». И мы на данном этапе получаем экземпляр объекта «Primus», который ничем не отличается от NSObject’а. Индивидуальные черты ему придаёт наша посылка метода

а также остальные методы, реализованные в рамках данного класса.
Конструкция

это просто перестраховка на случай, если что-то пойдёт не так и дефолтный «Primus» не создастся. т.е. метод init класса родителя не выполнится. В таком случае обычно делают

где пытаются исправить положение дел, но, к сожалению, это не тот случай и «else» нам уже ничем не поможет.
И здесь я хочу Вам напомнить о неинициализированном объекте из начала статьи. Именно при инициализации экземпляра объекта его суперклассом, происходит назначение места в памяти ему и передача указателя на это место в памяти. И когда проводим проверку

то именно в этот самый момент «self» может получить неожиданный адрес в памяти. То есть, полученный указатель уже будет не «self». Суперкласс не возвратит нам что-то из ряда вон выходящее. Экземпляр объекта будет идентичен тому с которым мы собираемся работать. Но экземпляр именно этого объекта не будет тем экземпляром, который нам нужен. Это настолько редкая ошибка, что Вы можете её не наблюдать очень продолжительное время в своих приложениях. Просто в один прекрасный момент Ваше приложение может начать выдавать экзотические ошибки. Вследствие чего придётся потратить время на то, чтобы найти их причину. Выделенная память под Ваш объект не была задействована. Инициализироваться мог случайный указатель, не имеющий никакой связи в объектом, которому была выделена память методом «alloc». Вот тогда «self» не проходит проверку

В рассматриваемом методе инициализации. И всё потому что в каком-то месте программы при вызове этого объекта инициализация не была произведена должным образом.
Последнее, что мы должны сделать для завершения инициализации

Поскольку данный метод не «void», то он ожидает от нас, что в конце мы скажем ему что нужно возвратить. В данном случае будет возвращён объект типа «Primus», потому что «self» в рамках данного класса — именно «Primus». Также тип возвращаемого объекта нам говорит о том что ожидается именно «Primus».
В этих методах

тип возвращаемых объектов — «Kitchen», «UkrainianBorsch» и «MasterPoRemontu».
Таким образом, в методе «hotAsHell» мы говорим, что в конце выполнения данного метода желаем получить объект типа «Primus» с заданными параметрами.

Какими именно заданными параметрами?

Опишем такую реализацию метода

Это значит, что при вызове этого метода

задаются буквально такие параметры

Параметры задаются переменным, которые объявлены в файле *.h
Обратите внимание на конструкцию слова «setGas» или «setTemperature». Если есть переменная, например «variable», то задать ей нужное значение можно через префикс «set»:

при этом первая буква переменной становится заглавной. Таким образом, мы выяснили что в файле Primus.h были объявлены переменные «gas» и «temperature». Но само наличие переменных не даёт нам возможности назначать их с помощью префикса «set»
Для получения такой возможности нужно объявить свойства для этих переменных. Допустим такие:

а в файле имплементации нужно будет прописать

и только после этого станет возможным присвоение им значения через «setGas» и «setTemperature». Эти префиксы называются сэттерами.
В любой удобный момент можно попросить объект «Primus» показать Вам эти значения, обращаясь к его экземпляру

например для команды

Эти методы называются гэттерами. В случае обращения за значениями к названию переменной, ничего дописывать не нужно.
Обратите внимание, что к свойству объекта можно обращаться как через конструкцию

Они выполняют аналогичные действия.
Есть одна хитрость при доступе к переменным объекта. Это можно производить не только через свойства, но и через доступ к ним по принципу ключ-значение «key-value coding». То есть можно обратиться к переменной

Мы обратились за значением, которое находится в объекте «Primus» в ключевом слове «gas».
А такая конструкция

в контексте «key-value coding» будет выглядеть так

Вместо свойств использовать «key-value coding» — вполне нудное занятие. Но иметь понятие о нём необходимо, чтобы в случае, когда без этого не обойтись — воспользоваться.
Также не лишним будет указать тот факт, что с недавнего времени пременными в программировании на Objective-C уже не пользуются. Вместо них используют свойства. Свойства могут быть как доступными извне, так и инкапсулированными. Естественно, что для использования внутри методов можно и нужно использовать переменые. Но объявляние переменных в блоке «ivar», который находится в интерфейсе класса — это уже анахронизм.

runtime

Даже если этого ещё не произошло, есть вероятность того что вскоре Вы встретите в документации слово «runtime» и в пределах той же статьи слово «isa».
Понятие «runtime» можно охарактеризовать как «среда в которой происходит перевод Вашего кода на более низкоуровневый код». «runtime» написан непосредственно с использованием C и Ассемблера. Это ещё не перевод в машинный код, а приведение Вашего кода к языкам C и Ассемблеру. Ваш метод

в «runtime» на С выглядит примерно как

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

Пока же нас интересует что такое «isa».

Это переменная, которая объявлена непосредственно в NSObject’е. Единственная его переменная. Когда мы вызывали метод

то создавался не только экземпляр класса NSobject, но и экземпляр этой переменной «isa», которая ссылается на NSObject. То есть, она конкретно говорит «runtime’у», что она принадлежит объекту NSObject. А значит, и работать с экземпляром Вашего, только что созданного объекта нужно как и с NSObject’ом. В «isa» записывается указатель на тот родительский объект, который нам нужно унаследовать. Допустим, Ваш объект — потомок NSArray или UITableView или CFDictionaryRef или любого другого объекта. В таком случае «isa» указывает на NSArray или UITableView или CFDictionaryRef или любой другой объект соответственно. Так что создание экземпляра любого объекта, создаёт и переменную класса — «isa», которая ссылается непосредственно на родительский класс, вследствие чего «runtime» знает как будет поступать с каждым экземпляром.
Эта информация на этапе обучения нужна не для чего-то конкретного, а в принципе, для более объёмного понимания философии программирования Objective-C.
В процессе чтения книг и различной документации, на глаза Вам не раз попадётся понятие «singleton». Как говорит один популярный интернет-мем: «Нельзя вот так сразу взять и понять, что такое „singleton“.

Что такое синглтон?

Вообразим себе, что Вам нужно создать объект, который при каждом его вызове в любой точке приложения, возвращает один и тот же экземпляр. На самом деле, в процессе создания приложений, Вам действительно нужно будет такое создавать. Так почему же нельзя создать объект, несколько раз и присвоить ему те же данные через метод „initWithSomething:“ или с помощью сеттеров? Всё дело в работе с памятью и быстродействием, да и с собственно, меньшими затратами времени на написание кода. Памяти всегда мало, и даже когда на iPhone6 поставят 2Гб ОЗУ — её опять-таки будет мало. Создание одного экземпляра объекта, и последующее обращение к нему — экономит ресурсы устройства и ускоряет работу приложения. А ведь каждый хочет, чтобы его приложение было быстрым как „Bugatti Veyron“ и юзабельным как слово „хрен“.
Допустим что наш „Primus“ вполне может быть синглтоном. Тогда его метод

при реализации будет выглядеть так

Рассмотрим что это значит позже. Пока что выясним, зачем „Primus“ делать синглтоном.
Допустим, это не вполне обычный „Primus“, а раритетный. На нём есть гравировка неизвестного мастера, он имеет крайне низкое потребление газа, а также у него есть специальная коробочка, в которой он идеально укладывается. А теперь задайте себе вопрос: „нужен ли Вам другой примус?“. Конечно же нет! Но при посылке метода

будет создан один „Primus“, а при посылке метода

будет создан абсолютно другой „Primus“. Без гравировки и коробочки.
Теперь вернёмся к тому, что написано в реализации метода „hotAsHell“.
Для начала нужно создать экземпляр объекта со свойством „static“, для того, чтобы перекрыть доступ к объекту извне. Затем присвоить ему „nil“, для того чтобы он не взял случайный адрес в памяти. Конструкция

создаёт предикат (условие) — »predicate» который тоже не будет виден извне. Условие заключается в том, что запрещается автоматический или динамический вызов блока, стоящего за предикатом. А вот строка

уже производит все необходимые действия для создания уникального экземпляра объекта. Конкретно «dispatch_once» означает что выражение в скобках после него гарантированно будет запущенно только один раз на протяжении всего жизненного цикла приложения. Также «dispatch_once» гарантирует потокобезопасность. То есть, при запуске приложения в многопоточном режиме эта функция не будет вызвана одновременно в нескольких потоках, и у ж точно не создаст нам ещё один «уникальный „Primus“». Также есть блок

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

означает: один раз за весь жизненный цикл приложения будет инициализирован экземпляр объекта «Primus» под названием «myPrimus» со свойствами объекта-родителя и не будет возможности обратиться к этому блоку другим путём. Но о том что был создан «myPrimus» никто не узнает, потому что этот экземпляр объекта снаружи не виден. Все происходит в фоне и только единожды. И происходит благодаря GCD (Grand Central Dispatch). Рассказ о котором — отдельная тема.
И конечно же в конце мы возвращаем созданный синглтон

Синглтон — «Primus» у нас есть, теперь можно добавить ему свойства: коробочка — «Box», гравировка — «Etching», КПД — «Performance». И если объявить для них свойства, то можно будет извне менять эти переменные. Обшить коробочку, почистить гравировку, прочиповать наш «Primus» для повышения КПД. Но это останется наш старый добрый «Primus». Доступ извне к объекту «Primus» будет у тех классов, в шапке которых он объявлен. Но теперь, если делать так

а потом работать с «myPrimus» как с синглтоном, то ничего работать не будет. Все обращения к переменным синглтона должны происходить в следующей манере

так можно создать экземпляр «someBox» совсем другого класса коробок и ему присвоить значение, которое имеет коробка нашего синглтона или наоборот

поменять коробку нашего «Primus».
Синглтон можно применять когда нужно вызвать NSLog с описанием свойств синглтона, а самого синглтона в данном классе нет в принципе. В таком случае его нужно просто объявить в шапке файла и вызвать один раз там где нужно. Синглтон можно и даже рекомендуют использовать в качестве глобальной переменной. Точнее его свойства будут глобальными переменными.
После усвоения основных принципов, можно будет начинать решать предлагаемые в учебниках задачи. И если с написанием своих методов в своих классах и посылкой метода объекту разобраться можно, то в дальнейшем, нужно будет использовать делегаты, протоколы и прочие MVC. Необходимо будет использовать документацию Apple и применять тысячи различных методов, заботливо созданных и описанных купертиновскими программистами.
И тут становится непонятно в принципе как и что работает. Если созданный Вами метод создаёт внутри себя массив, потом вносит в него объекты, потом запускает цикл и что-то в нём делает, а потом этот метод запускает другой Ваш метод, то вроде всё понятно. Но вот Вы открываете документацию по интересующему Вас объекту, а в нём 20 методов, которые могут делать весьма занятные вещи. Кроме того, есть объекты предки, методы которых этот объект тоже может принимать. Кроме того, в начале статьи я писал о протоколах, которым может соответствовать объект. Итого, методов может быть сотни. Какой из них нужно применять? Встречный вопрос: «для чего именно Вам нужен метод?». Правильно заданный вопрос — уже половина ответа. Когда Вы поймёте что хотите сделать, то в описании класса сможете найти интересующий Вас метод и применитьего поназначению. Если Вы хотите чтобы этот экземпляр объекта сделал что-то, присущее только классу от которого он произошёл, то в документации по этому классу нужно внимательно поискать метод, который производит необходимые Вам операции. Послать это метод объекту нужно так

То есть, в документации Вы узнали, что этот метод берёт указанный аргумент «Potato» и делает с ним что-то, что в конечном итоге приводит Вас к цели если применить метод к объекту «myPrimus». Не нужно реализовывать этот метод, он реализован за Вас для прямого применения. Исключения составляют случаи, когда Вам нужно взять готовый класс из фрэймворка и субклассировать его так, чтобы при посылке стандартных методов его экземпляру, происходили нестандартные действия.

Протоколы

Есть также методы протоколов. Как я уже указывал в начале статьи, у них не может быть потомков. Они являются просто набором методов. Для того, чтобы применить метод протокола внутри себя, объект должен соответствовать этому протоколу. Это указывается в файле *.h

В данном случае, объект соответствует сразу двум протоколам «UITableViewDataSource» и «UITableViewDelegate».

И чем отличаются методы классов и протоколов?

Если зайти в описание этих протоколов, то там можно найти методы, которые объект может реализовать. Обратите внимание: методы протоколов Вы не посылаете своему объекту, а должны внутри них указать как должен отреагировать ваш объект, при обращении программы к этим методам. Некоторые методы в протоколах могут быть обязательными. И если вы решили что Ваш объект должен соответствовать протоколу, то обязательные методы нужно реализовать в первую очередь. Внутри любого метода протокола может быть любой метод класса. То есть, метод протокола — это контейнер, в котором находятся любые другие методы, собственно как и любой реализуемый Вами метод. Реализовать необходимый функционал внутри каждого метода протокола нужно исходя из потребностей. К примеру, нужно сделать так, чтобы Ваша формочка делала что-то, при определённых условиях. К примеру, меняла цвет, после того, как стала активной/неактивной. Идём в документацию Apple, смотрим какие протоколы реализуют нужные Вам методы. Затем ищем каким протоколам соответствует родительский класс формочки. Если протоколов, которые поддерживают нужный Вам функционал нет в стандартном наборе функций, то добавляем их в скобках. В описании этих протоколов ищем методы, которые реализуются после какого-либо события. Допустим

который автоматически выполняется когда аргумент «active» принимает значение «YES». И меняет цвет в части экрана описанной в «rect»:

Методы протоколов задают параметры работы экземпляра класса, меняют функционал, передают значения. Например:

возвращает количество строк в секции «section» для заданной таблицы «tableView».

На этом позволю себе закончить. Если статья поможет целевой аудитории, в которой несколько месяцев назад числился и я, то значит, что я думаю правильно и такие статьи нужны. Статьи не профессионалов, а людей, которые понимают что-то на таком уровне, который тяжело перешагнуть, не имея опоры или трамплина. Надеюсь эта статья кому-то будет трамплином или хотя бы табуреткой. Отсутствие хороших учителей, которые могут нормально что-то объяснить — фундаментальная проблема современности. У меня нет педагогического образования, но в статье изложено понятие в программировании в таком ключе, в каком лично мне было бы понятно.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *