Учебники

Objective-C Краткое руководство

Objective-C Обзор

Objective-C — это язык общего назначения, который разработан поверх языка программирования C путем добавления функций языка программирования Small Talk, что делает его объектно-ориентированным языком. Он в основном используется при разработке операционных систем iOS и Mac OS X, а также его приложений.

Первоначально Objective-C был разработан NeXT для ее ОС NeXTSTEP, от которой Apple перешла к его iOS и Mac OS X.

Объектно-ориентированное программирование

Полностью поддерживает объектно-ориентированное программирование, включая четыре столпа объектно-ориентированной разработки —

  • Инкапсуляция
  • Скрытие данных
  • наследование
  • Полиморфизм

Пример кода

Live Demo

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

   NSLog (@"hello world");
   [pool drain];
   return 0;
}

Основа основы

Foundation Framework предоставляет большой набор функций, и они перечислены ниже.

  • Он включает в себя список расширенных типов данных, таких как NSArray, NSDictionary, NSSet и так далее.

  • Он состоит из богатого набора функций, управляющих файлами, строками и т. Д.

  • Он предоставляет функции для обработки URL, такие утилиты, как форматирование даты, обработка данных, обработка ошибок и т. Д.

Он включает в себя список расширенных типов данных, таких как NSArray, NSDictionary, NSSet и так далее.

Он состоит из богатого набора функций, управляющих файлами, строками и т. Д.

Он предоставляет функции для обработки URL, такие утилиты, как форматирование даты, обработка данных, обработка ошибок и т. Д.

Цель обучения-C

Самое важное, что нужно сделать при изучении Objective-C, — это сосредоточиться на концепциях, а не потеряться в технических деталях языка.

Цель изучения языка программирования — стать лучшим программистом; то есть, чтобы стать более эффективным в разработке и внедрении новых систем и в поддержании старых.

Использование Objective-C

Objective-C, как упоминалось ранее, используется в iOS и Mac OS X. Он имеет большую базу пользователей iOS и значительно увеличивает пользователей Mac OS X. А поскольку Apple в первую очередь ориентируется на качество, и это замечательно для тех, кто начал изучать Objective-C.

Настройка среды Objective-C

Настройка локальной среды

Если вы все еще хотите настроить свою среду для языка программирования Objective-C, вам потребуются следующие две программы, доступные на вашем компьютере: (а) текстовый редактор и (б) компилятор GCC.

Текстовый редактор

Это будет использоваться для ввода вашей программы. Примерами немногих редакторов являются Блокнот Windows, команда редактирования ОС, Brief, Epsilon, EMACS и vim или vi.

Имя и версия текстового редактора могут различаться в разных операционных системах. Например, Блокнот будет использоваться в Windows, а vim или vi могут использоваться в Windows, а также в Linux или UNIX.

Файлы, которые вы создаете в редакторе, называются исходными файлами и содержат исходный код программы. Исходные файлы для программ Objective-C обычно называются с расширением « .m ».

Перед началом программирования убедитесь, что у вас есть один текстовый редактор, и у вас достаточно опыта, чтобы написать компьютерную программу, сохранить ее в файле, скомпилировать и, наконец, выполнить.

Компилятор GCC

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

Этот компилятор GCC будет использоваться для компиляции вашего исходного кода в конечную исполняемую программу. Я предполагаю, что у вас есть базовые знания о компиляторе языка программирования.

Компилятор GCC доступен бесплатно на различных платформах, а процедура установки на различных платформах описана ниже.

Установка в UNIX / Linux

Первым шагом является установка gcc вместе с пакетом gcc Objective-C. Это сделано с помощью —

$ su - 
$ yum install gcc
$ yum install gcc-objc

Следующим шагом является настройка зависимостей пакетов с помощью следующей команды —

$ yum install make libpng libpng-devel libtiff libtiff-devel libobjc 
   libxml2 libxml2-devel libX11-devel libXt-devel libjpeg libjpeg-devel

Чтобы получить все возможности Objective-C, загрузите и установите GNUStep. Это можно сделать, загрузив пакет с http://main.gnustep.org/resources/downloads.php .

Теперь нам нужно перейти в загруженную папку и распаковать файл с помощью —

$ tar xvfz gnustep-startup-.tar.gz

Теперь нам нужно переключиться на папку gnustep-startup, которая создается с помощью —

$ cd gnustep-startup-<version>

Далее нам нужно настроить процесс сборки —

$ ./configure

Тогда мы можем построить —

$ make

Мы должны, наконец, настроить окружающую среду путем —

$ . /usr/GNUstep/System/Library/Makefiles/GNUstep.sh

У нас есть helloWorld.m Objective-C следующим образом —

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   
   NSLog (@"hello world");
   [pool drain];
   return 0;
}

Теперь мы можем скомпилировать и запустить файл Objective-C, скажем helloWorld.m, переключившись на папку, содержащую файл, используя cd, а затем выполнив следующие шаги:

$ gcc `gnustep-config --objc-flags` 
-L/usr/GNUstep/Local/Library/Libraries 
-lgnustep-base helloWorld.m -o helloWorld
$ ./helloWorld

Мы можем увидеть следующий вывод —

2013-09-07 10:48:39.772 tutorialsPoint[12906] hello world

Установка в Mac OS

Если вы используете Mac OS X, самый простой способ получить GCC — это загрузить среду разработки Xcode с веб-сайта Apple и следовать простым инструкциям по установке. После настройки XCode вы сможете использовать компилятор GNU для C / C ++.

Xcode в настоящее время доступен по адресу developer.apple.com/technologies/tools/ .

Установка на Windows

Чтобы запустить программу Objective-C в Windows, нам нужно установить MinGW и GNUStep Core. Оба доступны по адресу https://www.gnu.org/software/gnustep/windows/installer.html .

Сначала нам нужно установить системный пакет MSYS / MinGW. Затем нам нужно установить пакет GNUstep Core. Оба из которых предоставляют установщик Windows, который не требует пояснений.

Затем использовать Objective-C и GNUstep, выбрав Пуск -> Все программы -> GNUstep -> Оболочка

Перейдите в папку, содержащую helloWorld.m

Мы можем скомпилировать программу, используя —

$ gcc `gnustep-config --objc-flags` 
-L /GNUstep/System/Library/Libraries hello.m -o hello -lgnustep-base -lobjc

Мы можем запустить программу с помощью —

./hello.exe

Мы получаем следующий вывод —

2013-09-07 10:48:39.772 tutorialsPoint[1200] hello world

Структура программы Objective-C

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

Пример Objective-C Hello World

Программа Objective-C в основном состоит из следующих частей —

  • Команды препроцессора
  • Интерфейс
  • Реализация
  • метод
  • переменные
  • Заявления и выражения
  • Комментарии

Давайте посмотрим на простой код, который будет печатать слова «Hello World» —

Live Demo

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
- (void)sampleMethod;
@end

@implementation SampleClass

- (void)sampleMethod {
   NSLog(@"Hello, World! \n");
}

@end

int main() {
   /* my first program in Objective-C */
   SampleClass *sampleClass = [[SampleClass alloc]init];
   [sampleClass sampleMethod];
   return 0;
}

Давайте посмотрим различные части вышеуказанной программы —

  • Первая строка программы #import <Foundation / Foundation.h> — это команда препроцессора, которая указывает компилятору Objective-C включить файл Foundation.h перед тем, как перейти к фактической компиляции.

  • Следующая строка @interface SampleClass: NSObject показывает, как создать интерфейс. Он наследует NSObject, который является базовым классом всех объектов.

  • Следующая строка — (void) sampleMethod; показывает, как объявить метод.

  • Следующая строка @end отмечает конец интерфейса.

  • Следующая строка @implementation SampleClass показывает, как реализовать интерфейс SampleClass.

  • Следующая строка — (void) sampleMethod {} показывает реализацию sampleMethod.

  • Следующая строка @end отмечает конец реализации.

  • Следующая строка int main () — это основная функция, с которой начинается выполнение программы.

  • Следующая строка /*…*/ будет игнорироваться компилятором, и она была добавлена ​​для добавления дополнительных комментариев в программу. Поэтому такие строки называются комментариями в программе.

  • Следующая строка NSLog (…) — это еще одна функция, доступная в Objective-C, которая вызывает сообщение «Hello, World!» быть отображенным на экране.

  • Следующая строка возвращает 0; завершает функцию main () и возвращает значение 0.

Первая строка программы #import <Foundation / Foundation.h> — это команда препроцессора, которая указывает компилятору Objective-C включить файл Foundation.h перед тем, как перейти к фактической компиляции.

Следующая строка @interface SampleClass: NSObject показывает, как создать интерфейс. Он наследует NSObject, который является базовым классом всех объектов.

Следующая строка — (void) sampleMethod; показывает, как объявить метод.

Следующая строка @end отмечает конец интерфейса.

Следующая строка @implementation SampleClass показывает, как реализовать интерфейс SampleClass.

Следующая строка — (void) sampleMethod {} показывает реализацию sampleMethod.

Следующая строка @end отмечает конец реализации.

Следующая строка int main () — это основная функция, с которой начинается выполнение программы.

Следующая строка /*…*/ будет игнорироваться компилятором, и она была добавлена ​​для добавления дополнительных комментариев в программу. Поэтому такие строки называются комментариями в программе.

Следующая строка NSLog (…) — это еще одна функция, доступная в Objective-C, которая вызывает сообщение «Hello, World!» быть отображенным на экране.

Следующая строка возвращает 0; завершает функцию main () и возвращает значение 0.

Компилировать и выполнять программу Objective-C

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2017-10-06 07:48:32.020 demo[65832] Hello, World!

Objective-C Основной синтаксис

Вы видели базовую структуру программы Objective-C, поэтому вам будет легко понять другие основные строительные блоки языка программирования Objective-C.

Жетоны в Objective-C

Программа Objective-C состоит из различных токенов, и токен является ключевым словом, идентификатором, константой, строковым литералом или символом. Например, следующий оператор Objective C состоит из шести токенов —

NSLog(@"Hello, World! \n");

Отдельные токены —

NSLog
@
(
   "Hello, World! \n"
)
;

Точки с запятой;

В программе Objective-C точка с запятой является разделителем операторов. То есть каждое отдельное утверждение должно заканчиваться точкой с запятой. Это указывает на конец одного логического объекта.

Например, следующие два разных утверждения —

NSLog(@"Hello, World! \n");
return 0;

Комментарии

Комментарии подобны тексту помощи в вашей программе Objective-C, и они игнорируются компилятором. Они начинаются с / * и заканчиваются символами * /, как показано ниже —

/* my first program in Objective-C */

Вы не можете иметь комментарии в комментариях, и они не встречаются внутри строковых или символьных литералов.

Идентификаторы

Идентификатор Objective-C — это имя, используемое для идентификации переменной, функции или любого другого пользовательского элемента. Идентификатор начинается с буквы от A до Z или от a до z или подчеркивания _, за которым следуют ноль или более букв, подчеркиваний и цифр (от 0 до 9).

Objective-C не позволяет использовать знаки препинания, такие как @, $ и% в идентификаторах. Objective-C является регистрозависимым языком программирования. Таким образом, рабочая сила и рабочая сила — это два разных идентификатора в Objective-C. Вот несколько примеров допустимых идентификаторов:

mohd       zara    abc   move_name  a_123
myname50   _temp   j     a23b9      retVal

Ключевые слова

В следующем списке показано несколько зарезервированных слов в Objective-C. Эти зарезервированные слова не могут использоваться как константы или переменные или любые другие имена идентификаторов.

авто еще долго переключатель
перерыв перечисление регистр ЬурейеЕ
дело внешний вернуть союз
голец поплавок короткая неподписанный
Const за подписанный недействительным
Продолжить идти к размер летучий
дефолт если статический в то время как
делать ИНТ структура _Packed
двойной протокол интерфейс реализация
NSObject NSInteger NSNumber CGFloat
имущество неатомический; сохранить сильный
слабый unsafe_unretained; читай пиши только для чтения

Пробелы в Objective-C

Строка, содержащая только пробел, возможно, с комментарием, называется пустой строкой, и компилятор Objective-C полностью игнорирует ее.

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

int age;

Должен быть хотя бы один символ пробела (обычно пробел) между int и age, чтобы компилятор мог их различать. С другой стороны, в следующем утверждении,

fruit = apples + oranges;   // get the total fruit

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

Типы данных Objective-C

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

Типы в Objective-C можно классифицировать следующим образом:

Sr.No. Типы и описание
1

Основные типы —

Они являются арифметическими типами и состоят из двух типов: (а) целочисленные типы и (б) типы с плавающей точкой.

2

Перечисляемые типы —

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

3

Тип пустоты —

Спецификатор типа void указывает, что значение недоступно.

4

Производные типы —

Они включают (a) типы указателей, (b) типы массивов, (c) типы структур, (d) типы объединений и (e) типы функций.

Основные типы —

Они являются арифметическими типами и состоят из двух типов: (а) целочисленные типы и (б) типы с плавающей точкой.

Перечисляемые типы —

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

Тип пустоты —

Спецификатор типа void указывает, что значение недоступно.

Производные типы —

Они включают (a) типы указателей, (b) типы массивов, (c) типы структур, (d) типы объединений и (e) типы функций.

Типы массивов и типы структур совместно называются агрегатными типами. Тип функции указывает тип возвращаемого значения функции. Мы увидим основные типы в следующем разделе, тогда как другие типы будут рассмотрены в следующих главах.

Целочисленные типы

В следующей таблице приведены подробные сведения о стандартных целочисленных типах с их размерами хранения и диапазонами значений.

Тип Размер хранилища Диапазон значений
голец 1 байт От -128 до 127 или от 0 до 255
без знака 1 байт От 0 до 255
подписанный символ 1 байт От -128 до 127
ИНТ 2 или 4 байта От -32 768 до 32 767 или от -2 147 483 648 до 2 147 483 647
без знака int 2 или 4 байта От 0 до 65 535 или от 0 до 4 294 967 295
короткая 2 байта От -32 768 до 32 767
неподписанный короткий 2 байта От 0 до 65 535
долго 4 байта От -2 147 483 648 до 2 147 483 647
без знака долго 4 байта От 0 до 4 294 967 295

Чтобы получить точный размер типа или переменной на конкретной платформе, вы можете использовать оператор sizeof . Выражение sizeof (тип) возвращает размер хранилища объекта или типа в байтах. Ниже приведен пример получения размера типа int на любой машине:

Live Demo

#import <Foundation/Foundation.h>

int main() {
   NSLog(@"Storage size for int : %d \n", sizeof(int));
   return 0;
}

Когда вы компилируете и запускаете вышеупомянутую программу, она дает следующий результат в Linux:

2013-09-07 22:21:39.155 demo[1340] Storage size for int : 4 

Типы с плавающей точкой

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

Тип Размер хранилища Диапазон значений точность
поплавок 4 байта 1,2E-38 до 3,4E + 38 6 десятичных знаков
двойной 8 байт 2,3E-308 до 1,7E + 308 15 десятичных знаков
длинный двойной 10 байт От 3.4E-4932 до 1.1E + 4932 19 десятичных знаков

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

Live Demo

#import <Foundation/Foundation.h>

int main() {
   NSLog(@"Storage size for float : %d \n", sizeof(float));
   return 0;
}

Когда вы компилируете и запускаете вышеупомянутую программу, она дает следующий результат в Linux:

2013-09-07 22:22:21.729 demo[3927] Storage size for float : 4 

Тип пустоты

Тип void указывает, что значение недоступно. Он используется в трех видах ситуаций —

Sr.No. Типы и описание
1 Функция возвращается как void

В Objective-C существуют различные функции, которые не возвращают значение, или вы можете сказать, что они возвращают void. Функция без возвращаемого значения имеет тип возврата как void. Например, void exit (int status);

2 Аргументы функции как void

В Objective-C существуют различные функции, которые не принимают никаких параметров. Функция без параметра может быть принята как пустая. Например, int rand (void);

В Objective-C существуют различные функции, которые не возвращают значение, или вы можете сказать, что они возвращают void. Функция без возвращаемого значения имеет тип возврата как void. Например, void exit (int status);

В Objective-C существуют различные функции, которые не принимают никаких параметров. Функция без параметра может быть принята как пустая. Например, int rand (void);

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

Переменные Objective-C

Переменная — это не что иное, как имя, данное области памяти, которой могут манипулировать наши программы. Каждая переменная в Objective-C имеет определенный тип, который определяет размер и расположение памяти переменной; диапазон значений, которые могут быть сохранены в этой памяти; и набор операций, которые могут быть применены к переменной.

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

Sr.No. Тип и описание
1

голец

Обычно один октет (один байт). Это целочисленный тип.

2

ИНТ

Наиболее натуральный размер целого числа для машины.

3

поплавок

Значение с плавающей запятой одинарной точности.

4

двойной

Значение с плавающей запятой двойной точности.

5

недействительным

Представляет отсутствие типа.

голец

Обычно один октет (один байт). Это целочисленный тип.

ИНТ

Наиболее натуральный размер целого числа для машины.

поплавок

Значение с плавающей запятой одинарной точности.

двойной

Значение с плавающей запятой двойной точности.

недействительным

Представляет отсутствие типа.

Язык программирования Objective-C также позволяет определять различные другие типы переменных, которые мы рассмотрим в следующих главах, таких как Перечисление, Указатель, Массив, Структура, Объединение и т. Д. В этой главе мы изучим только основные типы переменных.

Определение переменной в Objective-C

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

type variable_list;

Здесь тип должен быть допустимым типом данных Objective C, включая char, w_char, int, float, double, bool или любой определенный пользователем объект и т. Д., А variable_list может состоять из одного или нескольких имен идентификаторов, разделенных запятыми. Некоторые действительные объявления показаны здесь —

int    i, j, k;
char   c, ch;
float  f, salary;
double d;

Линия int i, j, k; оба объявляют и определяют переменные i, j и k; который инструктирует компилятор создавать переменные с именами i, j и k типа int.

Переменные могут быть инициализированы (им присвоено начальное значение) в их объявлении. Инициализатор состоит из знака равенства, за которым следует постоянное выражение:

type variable_name = value;

Вот некоторые примеры:

extern int d = 3, f = 5;    // declaration of d and f. 
int d = 3, f = 5;           // definition and initializing d and f. 
byte z = 22;                // definition and initializes z. 
char x = 'x';               // the variable x has the value 'x'.

Для определения без инициализатора: переменные со статической продолжительностью хранения неявно инициализируются с помощью NULL (все байты имеют значение 0); начальное значение всех других переменных не определено.

Объявление переменных в Objective-C

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

Объявление переменной полезно, когда вы используете несколько файлов и определяете свою переменную в одном из файлов, которые будут доступны во время компоновки программы. Вы будете использовать ключевое слово extern для объявления переменной в любом месте. Хотя вы можете объявить переменную несколько раз в вашей программе Objective-C, но она может быть определена только один раз в файле, функции или блоке кода.

пример

Попробуйте следующий пример, где переменные были объявлены сверху, но они были определены и инициализированы внутри основной функции —

Live Demo

#import <Foundation/Foundation.h>

// Variable declaration:
extern int a, b;
extern int c;
extern float f;

int main () {
  /* variable definition: */
  int a, b;
  int c;
  float f;
 
  /* actual initialization */
  a = 10;
  b = 20;
  
  c = a + b;
  NSLog(@"value of c : %d \n", c);

  f = 70.0/3.0;
  NSLog(@"value of f : %f \n", f);
 
  return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-07 22:43:31.695 demo[14019] value of c : 30 
2013-09-07 22:43:31.695 demo[14019] value of f : 23.333334 

Та же концепция применяется к объявлению функции, когда вы предоставляете имя функции во время ее объявления, и ее фактическое определение может быть дано где-либо еще. В следующем примере это объясняется с использованием функции C, и, как вы знаете, Objective-C также поддерживает функции стиля C —

// function declaration
int func();

int main() {
   // function call
   int i = func();
}

// function definition
int func() {
   return 0;
}

L-значения и R-значения в Objective-C

В Objective-C есть два вида выражений:

  • lvalue — Выражения, которые ссылаются на ячейку памяти, называются выражением «lvalue». Lvalue может отображаться как левая или правая сторона задания.

  • rvalue — термин rvalue относится к значению данных, которое хранится по некоторому адресу в памяти. Значение r — это выражение, которому не может быть присвоено значение, что означает, что значение r может появляться с правой, но не с левой стороны присвоения.

lvalue — Выражения, которые ссылаются на ячейку памяти, называются выражением «lvalue». Lvalue может отображаться как левая или правая сторона задания.

rvalue — термин rvalue относится к значению данных, которое хранится по некоторому адресу в памяти. Значение r — это выражение, которому не может быть присвоено значение, что означает, что значение r может появляться с правой, но не с левой стороны присвоения.

Переменные являются lvalues ​​и могут отображаться в левой части назначения. Числовые литералы являются r-значениями, поэтому не могут быть назначены и не могут отображаться слева. Следующее является действительным утверждением —

int g = 20;

Но следующее не является допустимым утверждением и может привести к ошибке во время компиляции —

10 = 20;

Константы Objective-C

Константы относятся к фиксированным значениям, которые программа не может изменить во время своего выполнения. Эти фиксированные значения также называются литералами .

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

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

Целочисленные литералы

Целочисленный литерал может быть десятичной, восьмеричной или шестнадцатеричной константой. Префикс указывает основание или основание: 0x или 0X для шестнадцатеричного, 0 для восьмеричного и ничего для десятичного.

Целочисленный литерал также может иметь суффикс, который представляет собой комбинацию U и L для беззнакового и длинного соответственно. Суффикс может быть в верхнем или нижнем регистре и может быть в любом порядке.

Вот несколько примеров целочисленных литералов —

212         /* Legal */
215u        /* Legal */
0xFeeL      /* Legal */
078         /* Illegal: 8 is not an octal digit */
032UU       /* Illegal: cannot repeat a suffix */

Ниже приведены другие примеры различных типов литералов Integer:

85         /* decimal */
0213       /* octal */
0x4b       /* hexadecimal */
30         /* int */
30u        /* unsigned int */
30l        /* long */
30ul       /* unsigned long */

Литералы с плавающей точкой

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

При представлении с использованием десятичной формы вы должны включать десятичную точку, экспоненту или оба, а при представлении с использованием экспоненциальной формы вы должны включать целую часть, дробную часть или оба. Подписанный показатель вводится через e или E.

Вот несколько примеров литералов с плавающей точкой —

3.14159       /* Legal */
314159E-5L    /* Legal */
510E          /* Illegal: incomplete exponent */
210f          /* Illegal: no decimal or exponent */
.e55          /* Illegal: missing integer or fraction */

Символьные константы

Символьные литералы заключаются в одинарные кавычки, например, ‘x’, и могут храниться в простой переменной типа char .

Символьный литерал может быть простым символом (например, «x»), escape-последовательностью (например, «\ t») или универсальным символом (например, «\ u02C0»).

Есть определенные символы в C, когда они обрабатываются обратной косой чертой, они будут иметь особое значение, и они будут использоваться для представления, например, новой строки (\ n) или табуляции (\ t). Здесь у вас есть список некоторых из таких кодов escape-последовательностей —

Последовательность побега Имея в виду
\\ \ персонаж
‘ персонаж
» персонаж
\? ? персонаж
\ а Оповещение или звонок
\ б возврат на одну позицию
\ е Форма подачи
\ п Новая линия
Возврат каретки
\ т Горизонтальная вкладка
\ v Вертикальная вкладка
\ ооо Восьмеричное число от одной до трех цифр
ххх , , Шестнадцатеричное число из одной или нескольких цифр

Ниже приведен пример, показывающий несколько символов escape-последовательности:

Live Demo

#import <Foundation/Foundation.h>

int main() {
   NSLog(@"Hello\tWorld\n\n");
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-07 22:17:17.923 demo[17871] Hello	World

Строковые литералы

Строковые литералы или константы заключаются в двойные кавычки «». Строка содержит символы, похожие на символьные литералы: простые символы, escape-последовательности и универсальные символы.

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

Вот несколько примеров строковых литералов. Все три формы являются одинаковыми строками.

"hello, dear"

"hello, \

dear"

"hello, " "d" "ear"

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

Есть два простых способа определения констант в C:

  • Использование #define препроцессора.

  • Используя ключевое слово const .

Использование #define препроцессора.

Используя ключевое слово const .

Препроцессор #define

Ниже приведена форма для использования препроцессора #define для определения константы:

#define identifier value

Следующий пример объясняет это подробно —

Live Demo

#import <Foundation/Foundation.h>

#define LENGTH 10   
#define WIDTH  5
#define NEWLINE '\n'

int main() {
   int area;
   area = LENGTH * WIDTH;
   NSLog(@"value of area : %d", area);
   NSLog(@"%c", NEWLINE);

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-07 22:18:16.637 demo[21460] value of area : 50
2013-09-07 22:18:16.638 demo[21460] 

Ключевое слово const

Вы можете использовать префикс const для объявления констант определенного типа следующим образом:

const type variable = value;

Следующий пример объясняет это подробно —

Live Demo

#import <Foundation/Foundation.h>

int main() {
   const int  LENGTH = 10;
   const int  WIDTH  = 5;
   const char NEWLINE = '\n';
   int area;  
   
   area = LENGTH * WIDTH;
   NSLog(@"value of area : %d", area);
   NSLog(@"%c", NEWLINE);

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-07 22:19:24.780 demo[25621] value of area : 50
2013-09-07 22:19:24.781 demo[25621] 

Обратите внимание, что это хорошая практика программирования для определения констант в заглавных буквах.

Операторы Objective-C

Оператор — это символ, который указывает компилятору выполнять определенные математические или логические манипуляции. Язык Objective-C богат встроенными операторами и предоставляет следующие типы операторов:

  • Арифметические Операторы
  • Операторы отношений
  • Логические Операторы
  • Битовые операторы
  • Операторы присваивания
  • Разные Операторы

Этот урок объяснит один за другим арифметические, реляционные, логические, побитовые, присваивания и другие операторы.

Арифметические Операторы

В следующей таблице показаны все арифметические операторы, поддерживаемые языком Objective-C. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать примеры

оператор Описание пример
+ Добавляет два операнда А + Б даст 30
Вычитает второй операнд из первого A — B даст -10
* Умножает оба операнда А * Б даст 200
/ Делит числитель на знаменатель Б / у даст 2
% Оператор модуля и остаток от целочисленного деления B% A даст 0
++ Оператор приращения увеличивает целое значение на единицу А ++ даст 11
Оператор декремента уменьшает целочисленное значение на единицу A— даст 9

Операторы отношений

В следующей таблице показаны все реляционные операторы, поддерживаемые языком Objective-C. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать примеры

оператор Описание пример
== Проверяет, равны ли значения двух операндов или нет; если да, то условие становится истинным. (A == B) не соответствует действительности.
знак равно Проверяет, равны ли значения двух операндов или нет; если значения не равны, то условие становится истинным. (A! = B) верно.
> Проверяет, больше ли значение левого операнда, чем значение правого операнда; если да, то условие становится истинным. (A> B) не соответствует действительности.
< Проверяет, меньше ли значение левого операнда, чем значение правого операнда; если да, то условие становится истинным. (A <B) верно.
> = Проверяет, больше ли значение левого операнда или равно значению правого операнда; если да, то условие становится истинным. (A> = B) не соответствует действительности.
<= Проверяет, меньше ли значение левого операнда или равно значению правого операнда; если да, то условие становится истинным. (A <= B) верно.

Логические Операторы

В следующей таблице приведены все логические операторы, поддерживаемые языком Objective-C. Предположим, что переменная A содержит 1, а переменная B содержит 0, тогда —

Показать примеры

оператор Описание пример
&& Называется логический оператор И. Если оба операнда отличны от нуля, условие становится истинным. (A && B) неверно.
|| Вызывается логическим оператором ИЛИ. Если любой из двух операндов отличен от нуля, условие становится истинным. (A || B) верно.
! Вызывается логическим оператором НЕ. Используйте для изменения логического состояния своего операнда. Если условие истинно, то оператор Логический НЕ будет делать ложь. ! (A && B) верно.

Битовые операторы

Побитовый оператор работает с битами и выполняет побитовую операцию. Таблицы истинности для &, | и ^ следующие:

п Q P & Q р | Q р ^ д
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Предположим, если А = 60; и B = 13; теперь в двоичном формате они будут выглядеть следующим образом —

A = 0011 1100

B = 0000 1101

——————

A & B = 0000 1100

A | B = 0011 1101

A ^ B = 0011 0001

~ A = 1100 0011

Побитовые операторы, поддерживаемые языком Objective-C, перечислены в следующей таблице. Предположим, что переменная A содержит 60, а переменная B содержит 13, тогда —

Показать примеры

оператор Описание пример
& Двоичный оператор AND немного копирует результат, если он существует в обоих операндах. (A & B) даст 12, что составляет 0000 1100
| Оператор двоичного ИЛИ копирует немного, если он существует в любом из операндов. (A | B) даст 61, что составляет 0011 1101
^ Двоичный оператор XOR копирует бит, если он установлен в одном операнде, но не в обоих. (A ^ B) даст 49, что составляет 0011 0001
~ Оператор дополнения двоичных единиц является унарным и имеет эффект «переворачивания» битов. (~ A) даст -61, что составляет 1100 0011 в форме дополнения 2.
<< Двоичный оператор левого сдвига. Значение левого операнда перемещается влево на количество битов, указанное правым операндом. А << 2 даст 240, что составляет 1111 0000
>> Оператор двоичного правого сдвига. Значение левого операнда перемещается вправо на количество битов, указанное правым операндом. A >> 2 даст 15, что составляет 0000 1111

Операторы присваивания

Существуют следующие операторы присваивания, поддерживаемые языком Objective-C —

Показать примеры

оператор Описание пример
знак равно Простой оператор присваивания, присваивает значения от правых операндов к левому операнду C = A + B назначит значение A + B в C
+ = Добавить оператор присваивания И добавляет правый операнд к левому операнду и присваивает результат левому операнду C + = A эквивалентно C = C + A
знак равно Вычитание И оператор присваивания, вычитает правый операнд из левого операнда и присваивает результат левому операнду C — = A эквивалентно C = C — A
знак равно Оператор присваивания умножения И, умножает правый операнд на левый операнд и присваивает результат левому операнду C * = A эквивалентно C = C * A
знак равно Оператор деления И присваивания, делит левый операнд на правый операнд и присваивает результат левому операнду C / = A эквивалентно C = C / A
знак равно Модуль и оператор присваивания, принимает модуль с использованием двух операндов и присваивает результат левому операнду C% = A эквивалентно C = C% A
<< = Левый сдвиг И оператор присваивания C << = 2 совпадает с C = C << 2
>> = Оператор правого сдвига И присваивания C >> = 2 — это то же самое, что C = C >> 2
знак равно Побитовое И оператор присваивания C & = 2 совпадает с C = C & 2
^ = побитовое исключающее ИЛИ и оператор присваивания C ^ = 2 совпадает с C = C ^ 2
| = побитовое ИЛИ и оператор присваивания C | = 2 — это то же самое, что C = C | 2

Разные операторы ↦ sizeof & ternary

Есть несколько других важных операторов, включая sizeof и ? : поддерживается языком Objective-C.

Показать примеры

оператор Описание пример
размер() Возвращает размер переменной. sizeof (a), где a является целым числом, вернет 4.
& Возвращает адрес переменной. & А; даст фактический адрес переменной.
* Указатель на переменную. * А; будет указатель на переменную.
? : Условное выражение Если условие верно? Тогда значение X: в противном случае значение Y

Приоритет операторов в Objective-C

Приоритет оператора определяет группировку терминов в выражении. Это влияет на то, как оценивается выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например, оператор умножения имеет более высокий приоритет, чем оператор сложения —

Например, х = 7 + 3 * 2; здесь x назначено 13, а не 20, потому что оператор * имеет более высокий приоритет, чем +, поэтому он сначала умножается на 3 * 2, а затем прибавляется к 7.

Здесь операторы с самым высоким приоритетом отображаются вверху таблицы, а операторы с самым низким — внизу. Внутри выражения операторы с более высоким приоритетом будут оцениваться первыми.

категория оператор Ассоциативность
постфикс () [] ->. ++ — — Слева направо
Одинарный + -! ~ ++ — — (тип) * & sizeof Справа налево
Multiplicative * /% Слева направо
присадка + — Слева направо
сдвиг << >> Слева направо
реляционный <<=>> = Слева направо
равенство ==! = Слева направо
Побитовый XOR ^ Слева направо
Побитовое ИЛИ | Слева направо
Логическое И && Слева направо
Логическое ИЛИ || Слева направо
условный ?: Справа налево
присваивание = + = — = * = / =% = >> = << = & = ^ = | = Справа налево
запятая , Слева направо

Циклы Objective-C

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

Языки программирования предоставляют различные управляющие структуры, которые допускают более сложные пути выполнения.

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

Петлевая архитектура

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

Sr.No. Тип и описание петли
1 в то время как цикл

Повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.

2 для цикла

Выполнить последовательность операторов несколько раз и сократить код, который управляет переменной цикла.

3 делать … пока цикл

Как оператор while, за исключением того, что он проверяет условие в конце тела цикла.

4 вложенные циклы

Вы можете использовать один или несколько циклов внутри любого другого цикла while, for или do.. while.

Повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.

Выполнить последовательность операторов несколько раз и сократить код, который управляет переменной цикла.

Как оператор while, за исключением того, что он проверяет условие в конце тела цикла.

Вы можете использовать один или несколько циклов внутри любого другого цикла while, for или do.. while.

Заявления о контроле цикла

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

Objective-C поддерживает следующие управляющие операторы. Нажмите на следующие ссылки, чтобы проверить их детали.

Sr.No. Контрольное заявление и описание
1 заявление о нарушении

Завершает оператор цикла или переключателя и передает выполнение в оператор, следующий сразу за циклом или переключателем.

2 продолжить заявление

Заставляет петлю пропускать оставшуюся часть своего тела и немедленно проверять свое состояние перед повторением.

Завершает оператор цикла или переключателя и передает выполнение в оператор, следующий сразу за циклом или переключателем.

Заставляет петлю пропускать оставшуюся часть своего тела и немедленно проверять свое состояние перед повторением.

Бесконечный цикл

Цикл становится бесконечным, если условие никогда не становится ложным. Цикл for традиционно используется для этой цели. Поскольку ни одно из трех выражений, образующих цикл for, не требуется, вы можете создать бесконечный цикл, оставив условное выражение пустым.

#import <Foundation/Foundation.h>
 
int main () {

   for( ; ; ) {
      NSLog(@"This loop will run forever.\n");
   }

   return 0;
}

Когда условное выражение отсутствует, оно считается истинным. У вас может быть выражение инициализации и приращения, но программисты Objective-C чаще используют конструкцию for (;;) для обозначения бесконечного цикла.

Objective-C принятия решений

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

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

Заявления о принятии решений в Objective-C

Язык программирования Objective C принимает любые ненулевые и ненулевые значения как истинные , и если это или ноль или нуль , то это предполагается как ложное значение.

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

Sr.No. Заявление и описание
1 если заявление

Оператор if состоит из логического выражения, за которым следует одно или несколько операторов.

2 если … еще заявление

За оператором if может следовать необязательный оператор else , который выполняется, когда логическое выражение имеет значение false.

3 вложенные операторы if

Вы можете использовать один оператор if или else if внутри другого оператора if или else if .

4 заявление о переключении

Оператор switch позволяет проверять переменную на соответствие списку значений.

5 вложенные операторы switch

Вы можете использовать один оператор switch внутри другого оператора (ов) switch .

Оператор if состоит из логического выражения, за которым следует одно или несколько операторов.

За оператором if может следовать необязательный оператор else , который выполняется, когда логическое выражение имеет значение false.

Вы можете использовать один оператор if или else if внутри другого оператора if или else if .

Оператор switch позволяет проверять переменную на соответствие списку значений.

Вы можете использовать один оператор switch внутри другого оператора (ов) switch .

? : Оператор

Мы накрыли условного оператора? : в предыдущей главе, которая может быть использована для замены операторов if … else . Он имеет следующую общую форму —

Exp1 ? Exp2 : Exp3;

Где Exp1, Exp2 и Exp3 являются выражениями. Обратите внимание на использование и размещение толстой кишки.

Значение? Выражение определяется следующим образом: Exp1 оценивается. Если это правда, то Exp2 оценивается и становится значением целого? выражение. Если Exp1 имеет значение false, то Exp3 оценивается, и его значение становится значением выражения.

Функции Objective-C

Функция — это группа операторов, которые вместе выполняют задачу. Каждая программа Objective-C имеет одну функцию C, которая является main () , и все самые тривиальные программы могут определять дополнительные функции.

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

Объявление функции сообщает компилятору об имени функции, типе возврата и параметрах. Определение функции обеспечивает фактическое тело функции.

В основном в Objective-C мы называем функцию как метод.

Основа Objective-C предоставляет множество встроенных методов, которые может вызывать ваша программа. Например, метод appendString () для добавления строки в другую строку.

Метод известен с различными именами, такими как функция или подпрограмма или процедура и т. Д.

Определение метода

Общая форма определения метода в языке программирования Objective C следующая:

- (return_type) method_name🙁 argumentType1 )argumentName1 
joiningArgument2🙁 argumentType2 )argumentName2 ... 
joiningArgumentn🙁 argumentTypen )argumentNamen {
   body of the function
}

Определение метода в языке программирования Objective C состоит из заголовка метода и тела метода . Вот все части метода —

  • Тип возврата — метод может возвращать значение. Return_type — это тип данных значения, которое возвращает функция. Некоторые методы выполняют желаемые операции без возврата значения. В этом случае return_type является ключевым словом void .

  • Имя метода — это фактическое имя метода. Имя метода и список параметров вместе составляют сигнатуру метода.

  • Аргументы — Аргумент похож на заполнитель. Когда вызывается функция, вы передаете значение аргументу. Это значение называется фактическим параметром или аргументом. Список параметров относится к типу, порядку и количеству аргументов метода. Аргументы необязательны; то есть метод может не содержать аргументов.

  • Аргумент присоединения — объединяющий аргумент состоит в том, чтобы облегчить чтение и сделать его понятным во время вызова.

  • Тело методаТело метода содержит коллекцию операторов, которые определяют, что делает метод.

Тип возврата — метод может возвращать значение. Return_type — это тип данных значения, которое возвращает функция. Некоторые методы выполняют желаемые операции без возврата значения. В этом случае return_type является ключевым словом void .

Имя метода — это фактическое имя метода. Имя метода и список параметров вместе составляют сигнатуру метода.

Аргументы — Аргумент похож на заполнитель. Когда вызывается функция, вы передаете значение аргументу. Это значение называется фактическим параметром или аргументом. Список параметров относится к типу, порядку и количеству аргументов метода. Аргументы необязательны; то есть метод может не содержать аргументов.

Аргумент присоединения — объединяющий аргумент состоит в том, чтобы облегчить чтение и сделать его понятным во время вызова.

Тело методаТело метода содержит коллекцию операторов, которые определяют, что делает метод.

пример

Ниже приведен исходный код метода max () . Этот метод принимает два параметра num1 и num2 и возвращает максимум между двумя —

/* function returning the max between two numbers */
- (int) max🙁int) num1 secondNumber🙁int) num2 {
   
   /* local variable declaration */
   int result;
 
   if (num1 > num2) {
      result = num1;
   } else {
      result = num2;
   }
 
   return result; 
}

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

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

Объявление метода состоит из следующих частей:

- (return_type) function_name🙁 argumentType1 )argumentName1 
joiningArgument2🙁 argumentType2 )argumentName2 ... 
joiningArgumentn🙁 argumentTypen )argumentNamen;

Для определенной выше функции max () ниже приводится объявление метода —

-(int) max🙁int)num1 andNum2🙁int)num2;

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

Вызов метода

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

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

Чтобы вызвать метод, вам просто нужно передать необходимые параметры вместе с именем метода, и если метод возвращает значение, вы можете сохранить возвращаемое значение. Например —

Live Demo

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
/* method declaration */
- (int)max🙁int)num1 andNum2🙁int)num2;
@end

@implementation SampleClass

/* method returning the max between two numbers */
- (int)max🙁int)num1 andNum2🙁int)num2 {

   /* local variable declaration */
   int result;
 
   if (num1 > num2) {
      result = num1;
   } else {
      result = num2;
   }
 
   return result; 
}

@end

int main () {
   
   /* local variable definition */
   int a = 100;
   int b = 200;
   int ret;
   
   SampleClass *sampleClass = [[SampleClass alloc]init];

   /* calling a method to get max value */
   ret = [sampleClass max:a andNum2:b];
 
   NSLog(@"Max value is : %d\n", ret );
   return 0;
}

Я сохранил функцию max () вместе с функцией main () и выполнил исходный код. Запустив финальный исполняемый файл, он даст следующий результат:

2013-09-07 22:28:45.912 demo[26080] Max value is : 200

Аргументы функции

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

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

При вызове функции существует два способа передачи аргументов в функцию:

Sr.No. Тип звонка и описание
1 Звонок по значению

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

2 Звоните по ссылке

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

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

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

По умолчанию Objective-C использует вызов по значению для передачи аргументов. В целом это означает, что код внутри функции не может изменять аргументы, используемые для вызова функции, и в приведенном выше примере при вызове функции max () использовался тот же метод.

Блоки Objective-C

Класс Objective-C определяет объект, который объединяет данные со связанным поведением. Иногда имеет смысл представлять одну задачу или единицу поведения, а не набор методов.

Блоки — это функция уровня языка, добавленная в C, Objective-C и C ++, которая позволяет создавать отдельные сегменты кода, которые можно передавать в методы или функции, как если бы они были значениями. Блоки — это объекты Objective-C, что означает, что они могут быть добавлены в коллекции, такие как NSArray или NSDictionary. Они также могут захватывать значения из окружающей области, делая их похожими на замыкания или лямбды в других языках программирования.

Синтаксис объявления простого блока

returntype (^blockName)(argumentType);

Простая реализация блока

returntype (^blockName)(argumentType)= ^{
};

Вот простой пример

void (^simpleBlock)(void) = ^{
   NSLog(@"This is a block");
};

Мы можем вызвать блок, используя

simpleBlock();

Блоки принимают аргументы и возвращают значения

Блоки также могут принимать аргументы и возвращать значения так же, как методы и функции.

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

double (^multiplyTwoValues)(double, double) = 
   ^(double firstValue, double secondValue) {
      return firstValue * secondValue;
   };

double result = multiplyTwoValues(2,4); 
NSLog(@"The result is %f", result);

Блоки с использованием определений типов

Вот простой пример использования typedef в блоке. Обратите внимание, что этот пример пока не работает на онлайн-компиляторе . Используйте XCode, чтобы запустить то же самое.

#import <Foundation/Foundation.h>

typedef void (^CompletionBlock)();
@interface SampleClass:NSObject
- (void)performActionWithCompletion🙁CompletionBlock)completionBlock;
@end

@implementation SampleClass

- (void)performActionWithCompletion🙁CompletionBlock)completionBlock {

   NSLog(@"Action Performed");
   completionBlock();
}

@end

int main() {
   
   /* my first program in Objective-C */
   SampleClass *sampleClass = [[SampleClass alloc]init];
   [sampleClass performActionWithCompletion:^{
      NSLog(@"Completion is called to intimate action is performed.");
   }];

   return 0;
}

Давайте скомпилируем и выполним его, он даст следующий результат —

2013-09-10 08:13:57.155 demo[284:303] Action Performed
2013-09-10 08:13:57.157 demo[284:303] Completion is called to intimate action is performed.

Блоки чаще используются в приложениях iOS и Mac OS X. Поэтому важнее понимать использование блоков.

Числа Objective-C

В языке программирования Objective-C, чтобы сохранить основные типы данных, такие как int, float, bool в виде объекта,

Objective-C предоставляет ряд методов для работы с NSNumber, и важные из них перечислены в следующей таблице.

Sr.No. Метод и описание
1

+ (NSNumber *) numberWithBool: (BOOL) значение

Создает и возвращает объект NSNumber, содержащий заданное значение, обрабатывая его как BOOL.

2

+ (NSNumber *) numberWithChar: (char) значение

Создает и возвращает объект NSNumber, содержащий заданное значение, рассматривая его как подписанный символ.

3

+ (NSNumber *) numberWithDouble: (double) значение

Создает и возвращает объект NSNumber, содержащий заданное значение, рассматривая его как double.

4

+ (NSNumber *) numberWithFloat: (float) значение

Создает и возвращает объект NSNumber, содержащий заданное значение, обрабатывая его как число с плавающей точкой.

5

+ (NSNumber *) numberWithInt: (int) значение

Создает и возвращает объект NSNumber, содержащий данное значение, рассматривая его как подписанное int.

6

+ (NSNumber *) numberWithInteger: (NSInteger) значение

Создает и возвращает объект NSNumber, содержащий данное значение, рассматривая его как NSInteger.

7

— (BOOL) boolValue

Возвращает значение получателя в виде BOOL.

8

— (char) charValue

Возвращает значение получателя в виде символа.

9

— (double) doubleValue

Возвращает значение получателя как double.

10

— (float) floatValue

Возвращает значение получателя в виде числа с плавающей запятой.

11

— (NSInteger) integerValue

Возвращает значение получателя как NSInteger.

12

— (int) intValue

Возвращает значение получателя как int.

13

— (NSString *) stringValue

Возвращает значение получателя в виде удобочитаемой строки.

+ (NSNumber *) numberWithBool: (BOOL) значение

Создает и возвращает объект NSNumber, содержащий заданное значение, обрабатывая его как BOOL.

+ (NSNumber *) numberWithChar: (char) значение

Создает и возвращает объект NSNumber, содержащий заданное значение, рассматривая его как подписанный символ.

+ (NSNumber *) numberWithDouble: (double) значение

Создает и возвращает объект NSNumber, содержащий заданное значение, рассматривая его как double.

+ (NSNumber *) numberWithFloat: (float) значение

Создает и возвращает объект NSNumber, содержащий заданное значение, обрабатывая его как число с плавающей точкой.

+ (NSNumber *) numberWithInt: (int) значение

Создает и возвращает объект NSNumber, содержащий данное значение, рассматривая его как подписанное int.

+ (NSNumber *) numberWithInteger: (NSInteger) значение

Создает и возвращает объект NSNumber, содержащий данное значение, рассматривая его как NSInteger.

— (BOOL) boolValue

Возвращает значение получателя в виде BOOL.

— (char) charValue

Возвращает значение получателя в виде символа.

— (double) doubleValue

Возвращает значение получателя как double.

— (float) floatValue

Возвращает значение получателя в виде числа с плавающей запятой.

— (NSInteger) integerValue

Возвращает значение получателя как NSInteger.

— (int) intValue

Возвращает значение получателя как int.

— (NSString *) stringValue

Возвращает значение получателя в виде удобочитаемой строки.

Вот простой пример использования NSNumber, который умножает два числа и возвращает продукт.

Live Demo

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
- (NSNumber *)multiplyA🙁NSNumber *)a withB🙁NSNumber *)b;
@end

@implementation SampleClass

- (NSNumber *)multiplyA🙁NSNumber *)a withB🙁NSNumber *)b {
   float number1 = [a floatValue];
   float number2 = [b floatValue];
   float product = number1 * number2;
   NSNumber *result = [NSNumber numberWithFloat:product];
   return result;
}

@end

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

   SampleClass *sampleClass = [[SampleClass alloc]init];
   NSNumber *a = [NSNumber numberWithFloat:10.5];
   NSNumber *b = [NSNumber numberWithFloat:10.0];   
   NSNumber *result = [sampleClass multiplyA:a withB:b];
   NSString *resultString = [result stringValue];
   NSLog(@"The product is %@",resultString);

   [pool drain];
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-14 18:53:40.575 demo[16787] The product is 105

Массивы Objective-C

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

Вместо того, чтобы объявлять отдельные переменные, такие как number0, number1, … и number99, вы объявляете одну переменную массива, такую ​​как числа, и используете числа [0], числа [1] и …, числа [99] для представления отдельные переменные. Определенный элемент в массиве доступен по индексу.

Все массивы состоят из смежных областей памяти. Самый низкий адрес соответствует первому элементу, а самый высокий адрес — последнему.

Массивы в Objective-C

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

Чтобы объявить массив в Objective-C, программист определяет тип элементов и количество элементов, требуемых массивом, следующим образом:

type arrayName [ arraySize ];

Это называется одномерным массивом. ArraySize должен быть целочисленной константой, большей нуля, и тип может быть любым допустимым типом данных Objective C. Например, чтобы объявить массив из 10 элементов с именем balance типа double, используйте этот оператор —

double balance[10];

Теперь баланс — это переменный массив, которого достаточно для хранения до 10 двойных чисел.

Инициализация массивов

Вы можете инициализировать массив в Objective-C либо один за другим, либо используя один оператор следующим образом:

double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};

Число значений в фигурных скобках {} не может быть больше, чем количество элементов, которые мы объявляем для массива в квадратных скобках []. Ниже приведен пример назначения одного элемента массива:

Если вы опустите размер массива, будет создан массив, достаточно большой, чтобы вместить инициализацию. Поэтому, если вы напишите —

double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0};

Вы создадите точно такой же массив, как и в предыдущем примере.

balance[4] = 50.0;

Приведенный выше оператор присваивает элементу номер 5 в массиве значение 50,0. Массив с 4-м индексом будет 5-м, т. Е. Последним элементом, поскольку все массивы имеют 0 в качестве индекса их первого элемента, который также называется базовым индексом. Ниже приведено графическое представление того же массива, который мы обсуждали выше.

Презентация массива

Доступ к элементам массива

Доступ к элементу осуществляется путем индексации имени массива. Это делается путем помещения индекса элемента в квадратные скобки после имени массива. Например —

double salary = balance[9];

Приведенный выше оператор возьмет 10-й элемент из массива и присвоит значение переменной salary. Ниже приведен пример, который будет использовать все три вышеупомянутых понятия, а именно. декларация, назначение и доступ к массивам —

Live Demo

#import <Foundation/Foundation.h>
 
int main () {
   int n[ 10 ];   /* n is an array of 10 integers */
   int i,j;
 
   /* initialize elements of array n to 0 */         
   for ( i = 0; i < 10; i++ ) {
      n[ i ] = i + 100;    /* set element at location i to i + 100 */
   }
   
   /* output each array element's value */
   for (j = 0; j < 10; j++ ) {
      NSLog(@"Element[%d] = %d\n", j, n[j] );
   }
 
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 01:24:06.669 demo[16508] Element[0] = 100
2013-09-14 01:24:06.669 demo[16508] Element[1] = 101
2013-09-14 01:24:06.669 demo[16508] Element[2] = 102
2013-09-14 01:24:06.669 demo[16508] Element[3] = 103
2013-09-14 01:24:06.669 demo[16508] Element[4] = 104
2013-09-14 01:24:06.669 demo[16508] Element[5] = 105
2013-09-14 01:24:06.669 demo[16508] Element[6] = 106
2013-09-14 01:24:06.669 demo[16508] Element[7] = 107
2013-09-14 01:24:06.669 demo[16508] Element[8] = 108
2013-09-14 01:24:06.669 demo[16508] Element[9] = 109

Массивы Objective-C в деталях

Массивы важны для Objective-C и требуют много дополнительных деталей. Существует несколько важных понятий, связанных с массивом, которые должны быть понятны программисту Objective-C —

Sr.No. Концепция и описание
1 Многомерные массивы

Objective-C поддерживает многомерные массивы. Простейшей формой многомерного массива является двумерный массив.

2 Передача массивов в функции

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

3 Возврат массива из функции

Objective-C позволяет функции возвращать массив.

4 Указатель на массив

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

Objective-C поддерживает многомерные массивы. Простейшей формой многомерного массива является двумерный массив.

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

Objective-C позволяет функции возвращать массив.

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

Objective-C Указатели

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

Как вы знаете, каждая переменная является ячейкой памяти, и каждая ячейка памяти имеет свой адрес, к которому можно обратиться, используя оператор амперсанда (&), который обозначает адрес в памяти. Рассмотрим следующий пример, который выведет адрес определенных переменных:

Live Demo

#import <Foundation/Foundation.h>

int main () {
   int  var1;
   char var2[10];

   NSLog(@"Address of var1 variable: %x\n", &var1 );
   NSLog(@"Address of var2 variable: %x\n", &var2 );

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он выдает результат примерно так:

2013-09-13 03:18:45.727 demo[17552] Address of var1 variable: 1c0843fc
2013-09-13 03:18:45.728 demo[17552] Address of var2 variable: 1c0843f0

Итак, вы поняли, что такое адрес памяти и как к нему обращаться, так что основа концепции окончена. Теперь давайте посмотрим, что такое указатель.

Что такое указатели?

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

type *var-name;

Здесь тип — это базовый тип указателя; это должен быть допустимый тип данных Objective C, а var-name — это имя переменной указателя. Звездочка *, которую вы использовали для объявления указателя, та же, что и для умножения. Однако в этом утверждении звездочка используется для обозначения переменной в качестве указателя. Следующее является действительным объявлением указателя —

int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

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

Как использовать указатели?

Есть несколько важных операций, которые мы будем делать с помощью указателей очень часто. (а) мы определяем переменную указателя, (б) присваиваем адрес переменной указателю и (в) наконец получаем доступ к значению по адресу, доступному в переменной указателя. Это делается с помощью унарного оператора *, который возвращает значение переменной, расположенной по адресу, указанному ее операндом. Следующий пример использует эти операции —

Live Demo

#import <Foundation/Foundation.h>

int main () {
   int  var = 20;    /* actual variable declaration */
   int  *ip;         /* pointer variable declaration */  
   ip = &var;       /* store address of var in pointer variable*/

   NSLog(@"Address of var variable: %x\n", &var  );

   /* address stored in pointer variable */
   NSLog(@"Address stored in ip variable: %x\n", ip );

   /* access the value using the pointer */
   NSLog(@"Value of *ip variable: %d\n", *ip );

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он выдает результат примерно так:

2013-09-13 03:20:21.873 demo[24179] Address of var variable: 337ed41c
2013-09-13 03:20:21.873 demo[24179] Address stored in ip variable: 337ed41c
2013-09-13 03:20:21.874 demo[24179] Value of *ip variable: 20

NULL-указатели в Objective-C

Хорошей практикой всегда является присвоение значения NULL переменной-указателю, если у вас нет точного адреса для назначения. Это делается во время объявления переменной. Указатель, которому присвоен NULL, называется нулевым указателем.

Указатель NULL — это константа со значением ноль, определенная в нескольких стандартных библиотеках. Рассмотрим следующую программу —

Live Demo

#import <Foundation/Foundation.h>

int main () {
   int  *ptr = NULL;
   NSLog(@"The value of ptr is : %x\n", ptr  );
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-13 03:21:19.447 demo[28027] The value of ptr is : 0

В большинстве операционных систем программам не разрешен доступ к памяти по адресу 0, поскольку эта память зарезервирована операционной системой. Однако адрес памяти 0 имеет особое значение; он сигнализирует о том, что указатель не предназначен для указания на доступную ячейку памяти. Но по соглашению, если указатель содержит нулевое (нулевое) значение, предполагается, что он ничего не указывает.

Чтобы проверить нулевой указатель, вы можете использовать оператор if следующим образом:

if(ptr)     /* succeeds if p is not null */
if(!ptr)    /* succeeds if p is null */

Objective-C Указатели в деталях

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

Sr.No. Концепция и описание
1 Objective-C — арифметика указателя

Существует четыре арифметических оператора, которые можно использовать в указателях: ++, -, +, —

2 Objective-C — Массив указателей

Вы можете определить массивы для хранения нескольких указателей.

3 Objective-C — указатель на указатель

Objective-C позволяет вам иметь указатель на указатель и так далее.

4 Передача указателей на функции в Objective-C

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

5 Возврат указателя из функций в Objective-C

Objective-C позволяет функции возвращать указатель на локальную переменную, статическую переменную и динамически распределенную память.

Существует четыре арифметических оператора, которые можно использовать в указателях: ++, -, +, —

Вы можете определить массивы для хранения нескольких указателей.

Objective-C позволяет вам иметь указатель на указатель и так далее.

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

Objective-C позволяет функции возвращать указатель на локальную переменную, статическую переменную и динамически распределенную память.

Строки Objective-C

Строка в языке программирования Objective-C представляется с использованием NSString, а ее подкласс NSMutableString предоставляет несколько способов создания строковых объектов. Самый простой способ создать строковый объект — использовать конструкцию Objective-C @ «…» —

NSString *greeting = @"Hello";

Простой пример создания и печати строки показан ниже.

Live Demo

#import <Foundation/Foundation.h>

int main () {
   NSString *greeting = @"Hello";
   NSLog(@"Greeting message: %@\n", greeting );

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он выдает результат, который выглядит следующим образом:

2013-09-11 01:21:39.922 demo[23926] Greeting message: Hello

Objective-C поддерживает широкий спектр методов для работы со строками —

Sr.No. Метод и цель
1

— (NSString *) capitalizedString;

Возвращает заглавное представление получателя.

2

— (unichar) characterAtIndex: (NSUInteger) индекс;

Возвращает символ в заданной позиции массива.

3

— (double) doubleValue;

Возвращает значение с плавающей запятой текста получателя как double.

4

— (float) floatValue;

Возвращает значение с плавающей запятой текста получателя в виде числа с плавающей запятой.

5

— (BOOL) hasPrefix: (NSString *) aString;

Возвращает логическое значение, которое указывает, соответствует ли данная строка начальным символам получателя.

6

— (BOOL) имеет суффикс: (NSString *) aString;

Возвращает логическое значение, которое указывает, соответствует ли данная строка конечным символам получателя.

7

— (id) initWithFormat: (NSString *) формат …;

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

8

— (NSInteger) integerValue;

Возвращает значение NSInteger текста получателя.

9

— (BOOL) isEqualToString: (NSString *) aString;

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

10

— (NSUInteger) длина;

Возвращает количество символов Unicode в получателе.

11

— (NSString *) lowercaseString;

Возвращает представление получателя в нижнем регистре.

12

— (NSRange) rangeOfString: (NSString *) aString;

Находит и возвращает диапазон первого вхождения данной строки в получателе.

13

— (NSString *) stringByAppendingFormat: (NSString *) формат …;

Возвращает строку, созданную добавлением к получателю строки, составленной из заданной строки формата и следующих аргументов.

14

— (NSString *) stringByTrimmingCharactersInSet: (NSCharacterSet *) set;

Возвращает новую строку, созданную удалением с обоих концов символов получателя, содержащихся в данном наборе символов.

15

— (NSString *) substringFromIndex: (NSUInteger) anIndex;

Возвращает новую строку, содержащую символы получателя, от строки с заданным индексом до конца.

— (NSString *) capitalizedString;

Возвращает заглавное представление получателя.

— (unichar) characterAtIndex: (NSUInteger) индекс;

Возвращает символ в заданной позиции массива.

— (double) doubleValue;

Возвращает значение с плавающей запятой текста получателя как double.

— (float) floatValue;

Возвращает значение с плавающей запятой текста получателя в виде числа с плавающей запятой.

— (BOOL) hasPrefix: (NSString *) aString;

Возвращает логическое значение, которое указывает, соответствует ли данная строка начальным символам получателя.

— (BOOL) имеет суффикс: (NSString *) aString;

Возвращает логическое значение, которое указывает, соответствует ли данная строка конечным символам получателя.

— (id) initWithFormat: (NSString *) формат …;

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

— (NSInteger) integerValue;

Возвращает значение NSInteger текста получателя.

— (BOOL) isEqualToString: (NSString *) aString;

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

— (NSUInteger) длина;

Возвращает количество символов Unicode в получателе.

— (NSString *) lowercaseString;

Возвращает представление получателя в нижнем регистре.

— (NSRange) rangeOfString: (NSString *) aString;

Находит и возвращает диапазон первого вхождения данной строки в получателе.

— (NSString *) stringByAppendingFormat: (NSString *) формат …;

Возвращает строку, созданную добавлением к получателю строки, составленной из заданной строки формата и следующих аргументов.

— (NSString *) stringByTrimmingCharactersInSet: (NSCharacterSet *) set;

Возвращает новую строку, созданную удалением с обоих концов символов получателя, содержащихся в данном наборе символов.

— (NSString *) substringFromIndex: (NSUInteger) anIndex;

Возвращает новую строку, содержащую символы получателя, от строки с заданным индексом до конца.

Следующий пример использует несколько из вышеупомянутых функций —

Live Demo

#import <Foundation/Foundation.h>

int main () {
   NSString *str1 = @"Hello";
   NSString *str2 = @"World";
   NSString *str3;
   int  len ;

   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

   /* uppercase string */
   str3 = [str2 uppercaseString];
   NSLog(@"Uppercase String :  %@\n", str3 );

   /* concatenates str1 and str2 */
   str3 = [str1 stringByAppendingFormat:@"World"];
   NSLog(@"Concatenated string:   %@\n", str3 );

   /* total length of str3 after concatenation */
   len = [str3 length];
   NSLog(@"Length of Str3 :  %d\n", len );

   /* InitWithFormat */
   str3 = [[NSString alloc] initWithFormat:@"%@ %@",str1,str2];	
   NSLog(@"Using initWithFormat:   %@\n", str3 );
   [pool drain];

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он выдает результат, который выглядит следующим образом:

2013-09-11 01:15:45.069 demo[30378] Uppercase String :  WORLD
2013-09-11 01:15:45.070 demo[30378] Concatenated string:   HelloWorld
2013-09-11 01:15:45.070 demo[30378] Length of Str3 :  10
2013-09-11 01:15:45.070 demo[30378] Using initWithFormat:   Hello World

Вы можете найти полный список связанных с NSString методов Objective-C в Справочнике по классам NSString.

Objective-C Структуры

Массивы Objective C позволяют вам определять тип переменных, которые могут содержать несколько элементов данных одного типа, но структура — это еще один определенный пользователем тип данных, доступный в программировании Objective C, который позволяет комбинировать элементы данных разных видов.

Структуры используются для представления записей. Предположим, вы хотите отслеживать свои книги в библиотеке. Вы можете отслеживать следующие атрибуты о каждой книге —

  • заглавие
  • автор
  • Предмет
  • ID книги

Определение структуры

Чтобы определить структуру, вы должны использовать инструкцию struct . Оператор struct определяет новый тип данных с более чем одним членом для вашей программы. Формат инструкции struct такой:

struct [structure tag] {
   member definition;
   member definition;
   ...
   member definition;
} [one or more structure variables];  

Тег структуры является необязательным, и каждое определение члена является обычным определением переменной, например int i; или плавать f; или любое другое допустимое определение переменной. В конце определения структуры перед последней точкой с запятой вы можете указать одну или несколько переменных структуры, но это не обязательно. Вот как вы бы объявили структуру Книги —

struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int   book_id;
} book;  

Доступ к членам структуры

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

Live Demo

#import <Foundation/Foundation.h>

struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int   book_id;
};
 
int main() {
   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = @"Objective-C Programming";
   Book1.author = @"Nuha Ali"; 
   Book1.subject = @"Objective-C Programming Tutorial";
   Book1.book_id = 6495407;

   /* book 2 specification */
   Book2.title = @"Telecom Billing";
   Book2.author = @"Zara Ali";
   Book2.subject = @"Telecom Billing Tutorial";
   Book2.book_id = 6495700;
 
   /* print Book1 info */
   NSLog(@"Book 1 title : %@\n", Book1.title);
   NSLog(@"Book 1 author : %@\n", Book1.author);
   NSLog(@"Book 1 subject : %@\n", Book1.subject);
   NSLog(@"Book 1 book_id : %d\n", Book1.book_id);

   /* print Book2 info */
   NSLog(@"Book 2 title : %@\n", Book2.title);
   NSLog(@"Book 2 author : %@\n", Book2.author);
   NSLog(@"Book 2 subject : %@\n", Book2.subject);
   NSLog(@"Book 2 book_id : %d\n", Book2.book_id);

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 04:20:07.947 demo[20591] Book 1 title : Objective-C Programming
2013-09-14 04:20:07.947 demo[20591] Book 1 author : Nuha Ali
2013-09-14 04:20:07.947 demo[20591] Book 1 subject : Objective-C Programming Tutorial
2013-09-14 04:20:07.947 demo[20591] Book 1 book_id : 6495407
2013-09-14 04:20:07.947 demo[20591] Book 2 title : Telecom Billing
2013-09-14 04:20:07.947 demo[20591] Book 2 author : Zara Ali
2013-09-14 04:20:07.947 demo[20591] Book 2 subject : Telecom Billing Tutorial
2013-09-14 04:20:07.947 demo[20591] Book 2 book_id : 6495700

Структуры как аргументы функций

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

Live Demo

#import <Foundation/Foundation.h>

struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int   book_id;
};

@interface SampleClass:NSObject
/* function declaration */
- (void) printBook🙁 struct Books) book ;
@end

@implementation SampleClass 

- (void) printBook🙁 struct Books) book {
   NSLog(@"Book title : %@\n", book.title);
   NSLog(@"Book author : %@\n", book.author);
   NSLog(@"Book subject : %@\n", book.subject);
   NSLog(@"Book book_id : %d\n", book.book_id);
}

@end

int main() {
   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = @"Objective-C Programming";
   Book1.author = @"Nuha Ali"; 
   Book1.subject = @"Objective-C Programming Tutorial";
   Book1.book_id = 6495407;

   /* book 2 specification */
   Book2.title = @"Telecom Billing";
   Book2.author = @"Zara Ali";
   Book2.subject = @"Telecom Billing Tutorial";
   Book2.book_id = 6495700;
 
   SampleClass *sampleClass = [[SampleClass alloc]init];
   /* print Book1 info */
   [sampleClass printBook: Book1];

   /* Print Book2 info */
   [sampleClass printBook: Book2];

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 04:34:45.725 demo[8060] Book title : Objective-C Programming
2013-09-14 04:34:45.725 demo[8060] Book author : Nuha Ali
2013-09-14 04:34:45.725 demo[8060] Book subject : Objective-C Programming Tutorial
2013-09-14 04:34:45.725 demo[8060] Book book_id : 6495407
2013-09-14 04:34:45.725 demo[8060] Book title : Telecom Billing
2013-09-14 04:34:45.725 demo[8060] Book author : Zara Ali
2013-09-14 04:34:45.725 demo[8060] Book subject : Telecom Billing Tutorial
2013-09-14 04:34:45.725 demo[8060] Book book_id : 6495700

Указатели на структуры

Вы можете определить указатели на структуры очень похожим образом, как вы определяете указатель на любую другую переменную следующим образом:

struct Books *struct_pointer;

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

struct_pointer = &Book1;

Чтобы получить доступ к членам структуры, используя указатель на эту структуру, вы должны использовать оператор -> следующим образом —

struct_pointer->title;

Давайте перепишем приведенный выше пример, используя указатель структуры, надеюсь, вам будет легко понять концепцию —

Live Demo

#import <Foundation/Foundation.h>

struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int   book_id;
};

@interface SampleClass:NSObject
/* function declaration */
- (void) printBook🙁 struct Books *) book ;
@end

@implementation SampleClass 
- (void) printBook🙁 struct Books *) book {
   NSLog(@"Book title : %@\n", book->title);
   NSLog(@"Book author : %@\n", book->author);
   NSLog(@"Book subject : %@\n", book->subject);
   NSLog(@"Book book_id : %d\n", book->book_id);
}

@end

int main() {
   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = @"Objective-C Programming";
   Book1.author = @"Nuha Ali"; 
   Book1.subject = @"Objective-C Programming Tutorial";
   Book1.book_id = 6495407;

   /* book 2 specification */
   Book2.title = @"Telecom Billing";
   Book2.author = @"Zara Ali";
   Book2.subject = @"Telecom Billing Tutorial";
   Book2.book_id = 6495700;
 
   SampleClass *sampleClass = [[SampleClass alloc]init];
   /* print Book1 info by passing address of Book1 */
   [sampleClass printBook:&Book1];

   /* print Book2 info by passing address of Book2 */
   [sampleClass printBook:&Book2];

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 04:38:13.942 demo[20745] Book title : Objective-C Programming
2013-09-14 04:38:13.942 demo[20745] Book author : Nuha Ali
2013-09-14 04:38:13.942 demo[20745] Book subject : Objective-C Programming Tutorial
2013-09-14 04:38:13.942 demo[20745] Book book_id : 6495407
2013-09-14 04:38:13.942 demo[20745] Book title : Telecom Billing
2013-09-14 04:38:13.942 demo[20745] Book author : Zara Ali
2013-09-14 04:38:13.942 demo[20745] Book subject : Telecom Billing Tutorial
2013-09-14 04:38:13.942 demo[20745] Book book_id : 6495700

Битовые поля

Битовые поля позволяют упаковывать данные в структуру. Это особенно полезно, когда память или хранилище данных стоят дорого. Типичные примеры —

  • Упаковка нескольких объектов в машинное слово. например, 1-битные флаги могут быть сжаты.

  • Чтение внешних форматов файлов — могут быть прочитаны нестандартные форматы файлов. Например, 9-битные целые числа.

Упаковка нескольких объектов в машинное слово. например, 1-битные флаги могут быть сжаты.

Чтение внешних форматов файлов — могут быть прочитаны нестандартные форматы файлов. Например, 9-битные целые числа.

Objective-C позволяет нам делать это в определении структуры, помещая: bit length после переменной. Например —

struct packed_struct {
   unsigned int f1:1;
   unsigned int f2:1;
   unsigned int f3:1;
   unsigned int f4:1;
   unsigned int type:4;
   unsigned int my_int:9;
} pack;

Здесь pack_struct содержит 6 членов: четыре 1-битных флага f1..f3, 4-битный тип и 9-битный my_int.

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

Препроцессоры Objective-C

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

Все команды препроцессора начинаются с символа решетки (#). Это должен быть первый непустой символ, и для удобства чтения директива препроцессора должна начинаться с первого столбца. В следующем разделе перечислены все важные директивы препроцессора —

Sr.No. Директива и описание
1

#define

Заменяет макрос препроцессора

2

#включают

Вставляет определенный заголовок из другого файла

3

#undef

Определяет макрос препроцессора

4

#ifdef

Возвращает true, если этот макрос определен

5

#ifndef

Возвращает true, если этот макрос не определен

6

#если

Проверяет, верно ли условие времени компиляции

7

#else

Альтернатива для #if

8

#elif

# еще #if в одном утверждении

9

#endif

Завершает препроцессор условно

10

#ошибка

Распечатывает сообщение об ошибке на stderr

11

#pragma

Выдает специальные команды компилятору с использованием стандартизированного метода

#define

Заменяет макрос препроцессора

#включают

Вставляет определенный заголовок из другого файла

#undef

Определяет макрос препроцессора

#ifdef

Возвращает true, если этот макрос определен

#ifndef

Возвращает true, если этот макрос не определен

#если

Проверяет, верно ли условие времени компиляции

#else

Альтернатива для #if

#elif

# еще #if в одном утверждении

#endif

Завершает препроцессор условно

#ошибка

Распечатывает сообщение об ошибке на stderr

#pragma

Выдает специальные команды компилятору с использованием стандартизированного метода

Примеры препроцессоров

Проанализируйте следующие примеры, чтобы понять различные директивы.

#define MAX_ARRAY_LENGTH 20

Эта директива указывает OCPP заменять экземпляры MAX_ARRAY_LENGTH на 20. Используйте #define для констант, чтобы повысить удобочитаемость.

#import <Foundation/Foundation.h>
#include "myheader.h"

Эти директивы сообщают OCPP, что нужно получить файл foundation.h из Foundation Framework и добавить текст в текущий исходный файл. Следующая строка говорит OCPP, чтобы получить myheader.h из локального каталога и добавить содержимое в текущий исходный файл.

#undef  FILE_SIZE
#define FILE_SIZE 42

Это говорит OCPP отменить определение существующего FILE_SIZE и определить его как 42.

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

Это говорит OCPP определять MESSAGE, только если MESSAGE еще не определен.

#ifdef DEBUG
   /* Your debugging statements here */
#endif

Это говорит OCPP, что нужно выполнить обработку вложенных операторов, если определен DEBUG. Это полезно, если вы передаете флаг -DDEBUG компилятору gcc во время компиляции. Это определит DEBUG, так что вы можете включать и выключать отладку на лету во время компиляции.

Предопределенные макросы

ANSI C определяет количество макросов. Хотя каждый из них доступен для использования в программировании, предопределенные макросы не должны изменяться напрямую.

Sr.No. Макрос и описание
1

__ДАТА__

Текущая дата в виде символьного литерала в формате «МММ ДД ГГГГ»

2

__ВРЕМЯ__

Текущее время как символьный литерал в формате «ЧЧ: ММ: СС»

3

__ФАЙЛ__

Это содержит текущее имя файла в виде строкового литерала.

4

__ЛИНИЯ__

Он содержит номер текущей строки в виде десятичной константы.

5

__STDC__

Определяется как 1, когда компилятор соответствует стандарту ANSI.

__ДАТА__

Текущая дата в виде символьного литерала в формате «МММ ДД ГГГГ»

__ВРЕМЯ__

Текущее время как символьный литерал в формате «ЧЧ: ММ: СС»

__ФАЙЛ__

Это содержит текущее имя файла в виде строкового литерала.

__ЛИНИЯ__

Он содержит номер текущей строки в виде десятичной константы.

__STDC__

Определяется как 1, когда компилятор соответствует стандарту ANSI.

Давайте попробуем следующий пример —

Live Demo

#import <Foundation/Foundation.h>

int main() {
   NSLog(@"File :%s\n", __FILE__ );
   NSLog(@"Date :%s\n", __DATE__ );
   NSLog(@"Time :%s\n", __TIME__ );
   NSLog(@"Line :%d\n", __LINE__ );
   NSLog(@"ANSI :%d\n", __STDC__ );
   
   return 0;
}

Когда приведенный выше код в файле main.m компилируется и выполняется, он дает следующий результат —

2013-09-14 04:46:14.859 demo[20683] File :main.m
2013-09-14 04:46:14.859 demo[20683] Date :Sep 14 2013
2013-09-14 04:46:14.859 demo[20683] Time :04:46:14
2013-09-14 04:46:14.859 demo[20683] Line :8
2013-09-14 04:46:14.859 demo[20683] ANSI :1

Операторы препроцессора

Препроцессор Objective-C предлагает следующие операторы, которые помогут вам в создании макросов:

Продолжение макроса (\)

Макрос обычно должен содержаться в одной строке. Оператор продолжения макроса используется для продолжения макроса, который слишком длинный для одной строки. Например —

#define  message_for(a, b)  \
   NSLog(@#a " and " #b ": We love you!\n")

Stringize (#)

Оператор stringize или number-sign (‘#’), когда используется в определении макроса, преобразует параметр макроса в строковую константу. Этот оператор может использоваться только в макросе, который имеет указанный аргумент или список параметров. Например —

Live Demo

#import <Foundation/Foundation.h>

#define  message_for(a, b)  \
   NSLog(@#a " and " #b ": We love you!\n")

int main(void) {
   message_for(Carole, Debra);
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 05:46:14.859 demo[20683] Carole and Debra: We love you!

Вставка токена (##)

Оператор вставки токена (##) в определении макроса объединяет два аргумента. Он позволяет объединить два отдельных токена в определении макроса в один токен. Например —

Live Demo

#import <Foundation/Foundation.h>

#define tokenpaster(n) NSLog (@"token" #n " = %d", token##n)

int main(void) {
   int token34 = 40;
   
   tokenpaster(34);
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 05:48:14.859 demo[20683] token34 = 40

Как это произошло, потому что этот пример приводит к следующему фактическому выводу препроцессора —

NSLog (@"token34 = %d", token34);

В этом примере показано объединение токена ## n в token34, и здесь мы использовали как stringize, так и вставку токена .

Определенный () оператор

Определяемый препроцессором оператор используется в константных выражениях, чтобы определить, определен ли идентификатор с помощью #define. Если указанный идентификатор определен, значение равно true (не ноль). Если символ не определен, значение равно false (ноль). Определенный оператор указан следующим образом:

Live Demo

#import <Foundation/Foundation.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
   NSLog(@"Here is the message: %s\n", MESSAGE);  
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 05:48:19.859 demo[20683] Here is the message: You wish!

Параметризованные макросы

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

int square(int x) {
   return x * x;
}

Мы можем переписать приведенный выше код с помощью макроса следующим образом:

#define square(x) ((x) * (x))

Макросы с аргументами должны быть определены с использованием директивы #define, прежде чем их можно будет использовать. Список аргументов заключен в круглые скобки и должен следовать сразу за именем макроса. Пробелы между именем макроса и открытыми скобками не допускаются. Например —

Live Demo

#import <Foundation/Foundation.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void) {
   NSLog(@"Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 05:52:15.859 demo[20683] Max between 20 and 10 is 20

Objective-C Typedef

Язык программирования Objective-C предоставляет ключевое слово typedef , которое можно использовать для присвоения типу нового имени. Ниже приведен пример определения термина BYTE для однобайтовых чисел:

typedef unsigned char BYTE;

После определения этого типа идентификатор BYTE можно использовать как сокращение для типа unsigned char, например:.

BYTE  b1, b2;

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

typedef unsigned char byte;

Вы также можете использовать typedef для присвоения имени пользовательскому типу данных. Например, вы можете использовать typedef со структурой для определения нового типа данных, а затем использовать этот тип данных для непосредственного определения структурных переменных следующим образом:

Live Demo

#import <Foundation/Foundation.h>

typedef struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int book_id;
} Book;
 
int main() {
   Book book;
   book.title = @"Objective-C Programming";
   book.author = @"TutorialsPoint";
   book.subject = @"Programming tutorial";
   book.book_id = 100;
   
   NSLog( @"Book title : %@\n", book.title);
   NSLog( @"Book author : %@\n", book.author);
   NSLog( @"Book subject : %@\n", book.subject);
   NSLog( @"Book Id : %d\n", book.book_id);

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-12 12:21:53.745 demo[31183] Book title : Objective-C Programming
2013-09-12 12:21:53.745 demo[31183] Book author : TutorialsPoint
2013-09-12 12:21:53.745 demo[31183] Book subject : Programming tutorial
2013-09-12 12:21:53.745 demo[31183] Book Id : 100

typedef против #define

#Define — это директива Objective-C, которая также используется для определения псевдонимов для различных типов данных, аналогичных typedef, но со следующими различиями:

  • Функция typedef ограничена предоставлением символических имен только для типов, тогда как #define также может использоваться для определения псевдонима для значений, например, вы можете определить 1 как ONE и т. Д.

  • Интерпретация typedef выполняется компилятором, где операторы #define обрабатываются препроцессором.

Функция typedef ограничена предоставлением символических имен только для типов, тогда как #define также может использоваться для определения псевдонима для значений, например, вы можете определить 1 как ONE и т. Д.

Интерпретация typedef выполняется компилятором, где операторы #define обрабатываются препроцессором.

Ниже приведено простейшее использование #define —

Live Demo

#import <Foundation/Foundation.h>
 
#define TRUE  1
#define FALSE 0
 
int main( ) {
   NSLog( @"Value of TRUE : %d\n", TRUE);
   NSLog( @"Value of FALSE : %d\n", FALSE);

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-12 12:23:37.993 demo[5160] Value of TRUE : 1
2013-09-12 12:23:37.994 demo[5160] Value of FALSE : 0

Objective-C Тип Кастинг

Приведение типов — это способ преобразования переменной из одного типа данных в другой тип данных. Например, если вы хотите сохранить длинное значение в простое целое число, вы можете набрать cast long для int. Вы можете явно преобразовать значения из одного типа в другой, используя оператор приведения, следующим образом:

(type_name) expression

В Objective-C мы обычно используем CGFloat для выполнения операции с плавающей запятой, которая получена из базового типа с плавающей запятой в случае 32-разрядного и двойного в случае 64-разрядного. Рассмотрим следующий пример, где оператор приведения заставляет деление одной целочисленной переменной на другую как операцию с плавающей запятой:

Live Demo

#import <Foundation/Foundation.h>

int main() {
   int sum = 17, count = 5;
   CGFloat mean;

   mean = (CGFloat) sum / count;
   NSLog(@"Value of mean : %f\n", mean );

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-11 01:35:40.047 demo[20634] Value of mean : 3.400000

Здесь следует отметить, что оператор приведения имеет приоритет над делением, поэтому значение суммы сначала преобразуется в тип double и, наконец, оно делится на число, что приводит к двойному значению.

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

Целочисленное продвижение

Целочисленное продвижение — это процесс, при котором значения целочисленного типа «меньше», чем int или unsigned int , преобразуются либо в int, либо в unsigned int . Рассмотрим пример добавления символа в int —

Live Demo

#import <Foundation/Foundation.h>

int main() {
   int  i = 17;
   char c = 'c';  /* ascii value is 99 */
   int sum;

   sum = i + c;
   NSLog(@"Value of sum : %d\n", sum );

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-11 01:38:28.492 demo[980] Value of sum : 116

Здесь значение sum приходит как 116, потому что компилятор выполняет целочисленное продвижение и преобразует значение ‘c’ в ascii перед выполнением фактической операции сложения.

Обычное Арифметическое Преобразование

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

Обычное Арифметическое Преобразование

Обычные арифметические преобразования не выполняются ни для операторов присваивания, ни для логических операторов && и ||. Давайте возьмем следующий пример, чтобы понять концепцию —

Live Demo

#import <Foundation/Foundation.h>

int main() {
   int  i = 17;
   char c = 'c';  /* ascii value is 99 */
   CGFloat sum;

   sum = i + c;
   NSLog(@"Value of sum : %f\n", sum );
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-11 01:41:39.192 demo[15351] Value of sum : 116.000000

Здесь легко понять, что первый c преобразуется в целое число, но поскольку конечное значение равно float, то применяется обычное арифметическое преобразование, и компилятор преобразует i и c в float и добавляет их, получая результат float.

Objective-C Журнал Обработка

NSLog метод

Для печати журналов мы используем метод NSLog на языке программирования Objective-C, который мы использовали прямо из примера Hello World.

Давайте посмотрим на простой код, который будет печатать слова «Hello World» —

Live Demo

#import <Foundation/Foundation.h>

int main() {
   NSLog(@"Hello, World! \n");
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-16 00:32:50.888 demo[16669] Hello, World! 

Отключение журналов в Live-приложениях

Так как NSLogs мы используем в нашем приложении, он будет напечатан в журналах устройства, и нецелесообразно печатать журналы в живом билде. Следовательно, мы используем определение типа для печати журналов и можем использовать их, как показано ниже.

Live Demo

#import <Foundation/Foundation.h>

#if DEBUG == 0
#define DebugLog(...)
#elif DEBUG == 1
#define DebugLog(...) NSLog(__VA_ARGS__)
#endif

int main() {
   DebugLog(@"Debug log, our custom addition gets \
   printed during debug only" );
   NSLog(@"NSLog gets printed always" );     
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу в режиме отладки, мы получим следующий результат.

2013-09-11 02:47:07.723 demo[618] Debug log, our custom addition gets printed during debug only
2013-09-11 02:47:07.723 demo[618] NSLog gets printed always

Теперь, когда мы скомпилируем и запустим программу в режиме выпуска, мы получим следующий результат.

2013-09-11 02:47:45.248 demo[3158] NSLog gets printed always

Обработка ошибок Objective C

В программировании Objective C обработка ошибок обеспечивается классом NSError, доступным в платформе Основы.

Объект NSError инкапсулирует более обширную и расширяемую информацию об ошибках, чем это возможно, используя только код ошибки или строку ошибки. Основными атрибутами объекта NSError являются домен ошибок (представленный строкой), код ошибки, специфичный для домена, и словарь информации о пользователе, содержащий информацию, специфичную для приложения.

NSError

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

NSError Object состоит из —

  • Домен — домен ошибки может быть одним из предопределенных доменов NSError или произвольной строкой, описывающей пользовательский домен, и домен не должен быть равен нулю.

  • Код — код ошибки для ошибки.

  • Информация о пользователе — словарь userInfo для ошибки и userInfo может быть ноль.

Домен — домен ошибки может быть одним из предопределенных доменов NSError или произвольной строкой, описывающей пользовательский домен, и домен не должен быть равен нулю.

Код — код ошибки для ошибки.

Информация о пользователе — словарь userInfo для ошибки и userInfo может быть ноль.

В следующем примере показано, как создать пользовательскую ошибку

NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";
NSString *desc = NSLocalizedString(@"Unable to complete the process", @"");
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };
NSError *error = [NSError errorWithDomain:domain code:-101 userInfo:userInfo];

Вот полный код вышеприведенного примера ошибки, переданного как ссылка на указатель:

Live Demo

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
-(NSString *) getEmployeeNameForID🙁int) id withError🙁NSError **)errorPtr;
@end

@implementation SampleClass

-(NSString *) getEmployeeNameForID🙁int) id withError🙁NSError **)errorPtr {
   if(id == 1) {
      return @"Employee Test Name";
   } else {
      NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";
      NSString *desc =@"Unable to complete the process";
      NSDictionary *userInfo = [[NSDictionary alloc] 
      initWithObjectsAndKeys:desc,
      @"NSLocalizedDescriptionKey",NULL];  
      *errorPtr = [NSError errorWithDomain:domain code:-101 
      userInfo:userInfo];
      return @"";
   }
}

@end

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   SampleClass *sampleClass = [[SampleClass alloc]init];
   NSError *error = nil;
   NSString *name1 = [sampleClass getEmployeeNameForID:1 withError:&error];
  
   if(error) {
      NSLog(@"Error finding Name1: %@",error);
   } else {
      NSLog(@"Name1: %@",name1);
   }
   
   error = nil;
   NSString *name2 = [sampleClass getEmployeeNameForID:2 withError:&error];

   if(error) {
      NSLog(@"Error finding Name2: %@",error);
   } else {
      NSLog(@"Name2: %@",name2);
   }

   [pool drain];
   return 0; 
}

В приведенном выше примере мы возвращаем имя, если идентификатор равен 1, в противном случае мы устанавливаем пользовательский объект ошибки.

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-14 18:01:00.809 demo[27632] Name1: Employee Test Name
2013-09-14 18:01:00.809 demo[27632] Error finding Name2: Unable to complete the process

Аргументы командной строки

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

Аргументы командной строки обрабатываются с помощью аргументов функции main (), где argc ссылается на количество переданных аргументов, а argv [] — массив указателей, который указывает на каждый аргумент, переданный программе. Ниже приведен простой пример, который проверяет, есть ли какой-либо аргумент из командной строки, и предпринимает соответствующие действия:

#import <Foundation/Foundation.h>

int main( int argc, char *argv[] ) {
   if( argc == 2 ) {
      NSLog(@"The argument supplied is %s\n", argv[1]);
   } else if( argc > 2 ) {
      NSLog(@"Too many arguments supplied.\n");
   } else {
      NSLog(@"One argument expected.\n");
   }
}

Когда приведенный выше код компилируется и выполняется с одним аргументом, скажем, «тестирование», он дает следующий результат.

2013-09-13 03:01:17.333 demo[7640] The argument supplied is testing

Когда приведенный выше код компилируется и выполняется с двумя аргументами, скажем, testing1 и testing2, он дает следующий результат.

2013-09-13 03:01:18.333 demo[7640] Too many arguments supplied.

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

2013-09-13 03:01:18.333 demo[7640] One argument expected

Следует отметить, что argv [0] содержит имя самой программы, а argv [1] — указатель на первый предоставленный аргумент командной строки, а * argv [n] — последний аргумент. Если аргументы не предоставлены, argc будет один, иначе, если вы передадите один аргумент, тогда argc будет установлен в 2.

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

Live Demo

#import <Foundation/Foundation.h>

int main( int argc, char *argv[] ) {
   NSLog(@"Program name %s\n", argv[0]);
 
   if( argc == 2 ) {
      NSLog(@"The argument supplied is %s\n", argv[1]);
   } else if( argc > 2 ) {
      NSLog(@"Too many arguments supplied.\n");
   } else {
      NSLog(@"One argument expected.\n");
   }
   
   return 0;
}

Когда вышеприведенный код компилируется и выполняется с одним аргументом, разделенным пробелом, но внутри двойных кавычек с надписью «Testing1 Testing2», он дает следующий результат.

2017-11-30 06:36:59.081 main[71010] Program name main
2017-11-30 06:36:59.082 main[71010] One argument expected.

Objective-C Классы и Объекты

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

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

Характеристики Objective-C

  • Класс определяется в двух разных разделах, а именно: @interface и @implementation .

  • Почти все в форме объектов.

  • Объекты получают сообщения, а объекты часто называют получателями.

  • Объекты содержат переменные экземпляра.

  • Объекты и переменные экземпляра имеют область видимости.

  • Классы скрывают реализацию объекта.

  • Свойства используются для предоставления доступа к переменным экземпляра класса в других классах.

Класс определяется в двух разных разделах, а именно: @interface и @implementation .

Почти все в форме объектов.

Объекты получают сообщения, а объекты часто называют получателями.

Объекты содержат переменные экземпляра.

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

Классы скрывают реализацию объекта.

Свойства используются для предоставления доступа к переменным экземпляра класса в других классах.

Определения класса Objective-C

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

Определение класса начинается с ключевого слова @interface, за которым следует имя интерфейса (класса); и тело класса, заключенное в пару фигурных скобок. В Objective-C все классы являются производными от базового класса, называемого NSObject . Это суперкласс всех классов Objective-C. Он предоставляет основные методы, такие как выделение памяти и инициализация. Например, мы определили тип данных Box, используя ключевое слово class следующим образом:

@interface Box:NSObject {
   //Instance variables
   double length;    // Length of a box
   double breadth;   // Breadth of a box
}
@property(nonatomic, readwrite) double height;  // Property

@end

Переменные экземпляра являются частными и доступны только внутри реализации класса.

Выделение и инициализация объектов Objective C

Класс предоставляет чертежи для объектов, поэтому в основном объект создается из класса. Мы объявляем объекты класса точно так же, как мы объявляем переменные базовых типов. Следующие операторы объявляют два объекта класса Box —

Box box1 = [[Box alloc]init];     // Create box1 object of type Box
Box box2 = [[Box alloc]init];     // Create box2 object of type Box

Оба объекта box1 и box2 будут иметь свою собственную копию элементов данных.

Доступ к членам данных

К свойствам объектов класса можно получить доступ с помощью оператора прямого доступа к члену (.). Давайте попробуем следующий пример, чтобы прояснить ситуацию:

Live Demo

#import <Foundation/Foundation.h>

@interface Box:NSObject {
   double length;    // Length of a box
   double breadth;   // Breadth of a box
   double height;    // Height of a box
}

@property(nonatomic, readwrite) double height;  // Property
-(double) volume;
@end

@implementation Box

@synthesize height; 

-(id)init {
   self = [super init];
   length = 1.0;
   breadth = 1.0;
   return self;
}

-(double) volume {
   return length*breadth*height;
}

@end

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    
   Box *box1 = [[Box alloc]init];    // Create box1 object of type Box
   Box *box2 = [[Box alloc]init];    // Create box2 object of type Box

   double volume = 0.0;             // Store the volume of a box here
 
   // box 1 specification
   box1.height = 5.0; 

   // box 2 specification
   box2.height = 10.0;
  
   // volume of box 1
   volume = [box1 volume];
   NSLog(@"Volume of Box1 : %f", volume);
   
   // volume of box 2
   volume = [box2 volume];
   NSLog(@"Volume of Box2 : %f", volume);
   
   [pool drain];
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-22 21:25:33.314 ClassAndObjects[387:303] Volume of Box1 : 5.000000
2013-09-22 21:25:33.316 ClassAndObjects[387:303] Volume of Box2 : 10.000000

свойства

Свойства введены в Objective-C, чтобы обеспечить доступ к переменной экземпляра класса вне класса.

Различные части объявления свойства заключаются в следующем.

  • Свойства начинаются с @property , который является ключевым словом

  • За ним следуют спецификаторы доступа, которые являются неатомарными или атомарными, доступны для чтения или записи и только для чтения, сильные, unsafe_unretained или слабые. Это зависит от типа переменной. Для любого типа указателя мы можем использовать сильный, unsafe_unretained или слабый. Аналогично для других типов мы можем использовать readwrite или readonly.

  • Далее следует тип данных переменной.

  • Наконец, у нас есть имя свойства, оканчивающееся точкой с запятой.

  • Мы можем добавить синтезирующий оператор в классе реализации. Но в последнем XCode, часть синтеза позаботилась о XCode, и вам не нужно включать оператор синтеза.

Свойства начинаются с @property , который является ключевым словом

За ним следуют спецификаторы доступа, которые являются неатомарными или атомарными, доступны для чтения или записи и только для чтения, сильные, unsafe_unretained или слабые. Это зависит от типа переменной. Для любого типа указателя мы можем использовать сильный, unsafe_unretained или слабый. Аналогично для других типов мы можем использовать readwrite или readonly.

Далее следует тип данных переменной.

Наконец, у нас есть имя свойства, оканчивающееся точкой с запятой.

Мы можем добавить синтезирующий оператор в классе реализации. Но в последнем XCode, часть синтеза позаботилась о XCode, и вам не нужно включать оператор синтеза.

Это возможно только со свойствами, которые мы можем получить доступ к переменным экземпляра класса. На самом деле, для свойств создаются методы getter и setter.

Например, предположим, что у нас есть свойство @property (nonatomic, readonly) BOOL isDone . Под капотом находятся сеттеры и геттеры, созданные как показано ниже.

-(void)setIsDone(BOOL)isDone;
-(BOOL)isDone;

Objective-C Наследование

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

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

Идея наследования реализует отношения. Например, млекопитающее IS-A животное, собака IS-A млекопитающее, следовательно, собака IS-A животное, а также и так далее.

Базовые и производные классы

Objective-C допускает только многоуровневое наследование, т. Е. Он может иметь только один базовый класс, но допускает многоуровневое наследование. Все классы в Objective-C являются производными от суперкласса NSObject .

@interface derived-class: base-class

Рассмотрим базовый класс Person и его производный класс Employee следующим образом:

Live Demo

#import <Foundation/Foundation.h>
 
@interface Person : NSObject {
   NSString *personName;
   NSInteger personAge;
}

- (id)initWithName🙁NSString *)name andAge🙁NSInteger)age;
- (void)print;

@end

@implementation Person

- (id)initWithName🙁NSString *)name andAge🙁NSInteger)age {
   personName = name;
   personAge = age;
   return self;
}

- (void)print {
   NSLog(@"Name: %@", personName);
   NSLog(@"Age: %ld", personAge);
}

@end

@interface Employee : Person {
   NSString *employeeEducation;
}

- (id)initWithName🙁NSString *)name andAge🙁NSInteger)age 
  andEducation🙁NSString *)education;
- (void)print;
@end

@implementation Employee

- (id)initWithName🙁NSString *)name andAge🙁NSInteger)age 
   andEducation: (NSString *)education {
      personName = name;
      personAge = age;
      employeeEducation = education;
      return self;
   }

- (void)print {
   NSLog(@"Name: %@", personName);
   NSLog(@"Age: %ld", personAge);
   NSLog(@"Education: %@", employeeEducation);
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];        
   NSLog(@"Base class Person Object");
   Person *person = [[Person alloc]initWithName:@"Raj" andAge:5];
   [person print];
   NSLog(@"Inherited Class Employee Object");
   Employee *employee = [[Employee alloc]initWithName:@"Raj" 
   andAge:5 andEducation:@"MBA"];
   [employee print];        
   [pool drain];
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-22 21:20:09.842 Inheritance[349:303] Base class Person Object
2013-09-22 21:20:09.844 Inheritance[349:303] Name: Raj
2013-09-22 21:20:09.844 Inheritance[349:303] Age: 5
2013-09-22 21:20:09.845 Inheritance[349:303] Inherited Class Employee Object
2013-09-22 21:20:09.845 Inheritance[349:303] Name: Raj
2013-09-22 21:20:09.846 Inheritance[349:303] Age: 5
2013-09-22 21:20:09.846 Inheritance[349:303] Education: MBA

Контроль доступа и наследование

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

Мы можем суммировать различные типы доступа в зависимости от того, кто может получить к ним доступ следующим образом —

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

  • Переменные, объявленные в файле реализации с помощью расширений, недоступны.

  • Методы, объявленные в файле реализации с помощью расширений, недоступны.

  • Если унаследованный класс реализует метод в базовом классе, то выполняется метод в производном классе.

Переменные, объявленные в файле реализации с помощью расширений, недоступны.

Методы, объявленные в файле реализации с помощью расширений, недоступны.

Если унаследованный класс реализует метод в базовом классе, то выполняется метод в производном классе.

Objective-C Полиморфизм

Слово полиморфизм означает наличие многих форм. Как правило, полиморфизм возникает, когда существует иерархия классов, и они связаны наследованием.

Полиморфизм Objective-C означает, что вызов функции-члена приведет к выполнению другой функции в зависимости от типа объекта, который вызывает функцию.

Рассмотрим пример, у нас есть класс Shape, который предоставляет базовый интерфейс для всех фигур. Квадрат и прямоугольник являются производными от базового класса Shape.

У нас есть метод printArea, который собирается показать о полиморфизме функции ООП.

Live Demo

#import <Foundation/Foundation.h>

@interface Shape : NSObject {
   CGFloat area;
}

- (void)printArea;
- (void)calculateArea;
@end

@implementation Shape
- (void)printArea {
   NSLog(@"The area is %f", area);
}

- (void)calculateArea {

}

@end

@interface Square : Shape {
   CGFloat length;
}

- (id)initWithSide🙁CGFloat)side;
- (void)calculateArea;

@end

@implementation Square
- (id)initWithSide🙁CGFloat)side {
   length = side;
   return self;
}

- (void)calculateArea {
   area = length * length;
}

- (void)printArea {
   NSLog(@"The area of square is %f", area);
}

@end

@interface Rectangle : Shape {
   CGFloat length;
   CGFloat breadth;
}

- (id)initWithLength🙁CGFloat)rLength andBreadth🙁CGFloat)rBreadth;
@end

@implementation Rectangle
- (id)initWithLength🙁CGFloat)rLength andBreadth🙁CGFloat)rBreadth {
   length = rLength;
   breadth = rBreadth;
   return self;
}

- (void)calculateArea {
   area = length * breadth;
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   Shape *square = [[Square alloc]initWithSide:10.0];
   [square calculateArea];
   [square printArea];
   Shape *rect = [[Rectangle alloc]
   initWithLength:10.0 andBreadth:5.0];
   [rect calculateArea];
   [rect printArea];        
   [pool drain];
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-22 21:21:50.785 Polymorphism[358:303] The area of square is 100.000000
2013-09-22 21:21:50.786 Polymorphism[358:303] The area is 50.000000

В вышеприведенном примере, основанном на доступности методов executeArea и printArea, выполняется либо метод в базовом классе, либо производный класс.

Полиморфизм обрабатывает переключение методов между базовым классом и производным классом на основе реализации метода двух классов.

Инкапсуляция данных в Objective-C

Все программы Objective-C состоят из следующих двух основных элементов:

  • Программные операторы (код) — это часть программы, которая выполняет действия, и они называются методами.

  • Данные программы. Данные — это информация о программе, на которую влияют функции программы.

Программные операторы (код) — это часть программы, которая выполняет действия, и они называются методами.

Данные программы. Данные — это информация о программе, на которую влияют функции программы.

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

Инкапсуляция данных — это механизм связывания данных и функций, которые их используют, а абстракция данных — это механизм, который раскрывает только интерфейсы и скрывает детали реализации от пользователя.

Objective-C поддерживает свойства инкапсуляции и сокрытия данных посредством создания пользовательских типов, называемых классами . Например —

@interface Adder : NSObject {
   NSInteger total;
}

- (id)initWithInitialNumber🙁NSInteger)initialNumber;
- (void)addNumber🙁NSInteger)newNumber;
- (NSInteger)getTotal;

@end

Переменная total является закрытой, и мы не можем получить доступ извне класса. Это означает, что к ним могут получить доступ только другие члены класса Adder, а не любая другая часть вашей программы. Это один из способов инкапсуляции.

Методы внутри файла интерфейса доступны и являются общедоступными.

Существуют частные методы, которые написаны с помощью расширений , которые мы изучим в следующих главах.

Пример инкапсуляции данных

Любая программа Objective-C, в которой вы реализуете класс с переменными открытого и закрытого членов, является примером инкапсуляции данных и абстракции данных. Рассмотрим следующий пример —

Live Demo

#import <Foundation/Foundation.h>

@interface Adder : NSObject {
   NSInteger total;
}

- (id)initWithInitialNumber🙁NSInteger)initialNumber;
- (void)addNumber🙁NSInteger)newNumber;
- (NSInteger)getTotal;

@end

@implementation Adder
-(id)initWithInitialNumber🙁NSInteger)initialNumber {
   total = initialNumber;
   return self;
}

- (void)addNumber🙁NSInteger)newNumber {
   total = total + newNumber;
}

- (NSInteger)getTotal {
   return total;
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];        
   Adder *adder = [[Adder alloc]initWithInitialNumber:10];
   [adder addNumber:5];
   [adder addNumber:4];
   
   NSLog(@"The total is %ld",[adder getTotal]);
   [pool drain];
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

2013-09-22 21:17:30.485 DataEncapsulation[317:303] The total is 19

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

Разработка стратегии

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

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

Objective-C Категории

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

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

Синтаксис для объявления категории использует ключевое слово @interface, как и стандартное описание класса Objective-C, но не указывает на какое-либо наследование от подкласса. Вместо этого в скобках указывается название категории, например:

@interface ClassName (CategoryName)

@end

Характеристики категории

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

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

  • Во время выполнения нет никакой разницы между методом, добавленным категорией, и тем, который реализован исходным классом.

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

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

Во время выполнения нет никакой разницы между методом, добавленным категорией, и тем, который реализован исходным классом.

Теперь давайте посмотрим на пример реализации категории. Давайте добавим категорию к классу какао NSString. Эта категория позволит нам добавить новый метод getCopyRightString, который поможет нам вернуть строку авторских прав. Это показано ниже.

Live Demo

#import <Foundation/Foundation.h>

@interface NSString(MyAdditions)
+(NSString *)getCopyRightString;
@end

@implementation NSString(MyAdditions)

+(NSString *)getCopyRightString {
   return @"Copyright TutorialsPoint.com 2013";
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   NSString *copyrightString = [NSString getCopyRightString];
   NSLog(@"Accessing Category: %@",copyrightString);
   
   [pool drain];
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-22 21:19:12.125 Categories[340:303] Accessing Category: Copyright TutorialsPoint.com 2013

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

В нашем примере, поскольку у нас есть только один класс, мы не включили заголовочные файлы, в таком случае мы должны включить заголовочные файлы, как сказано выше.

Objective-C Позирует

Прежде чем приступить к Posing в Objective-C, я хотел бы обратить ваше внимание на то, что Posing объявлен устаревшим в Mac OS X 10.5 и после этого не будет доступен для использования. Так что для тех, кто не обеспокоен этими устаревшими методами, можете пропустить эту главу.

Objective-C позволяет классу полностью заменить другой класс в программе. Говорят, что замещающий класс «представляет собой» целевой класс.

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

NSObject содержит poseAsClass: метод, который позволяет нам заменить существующий класс, как сказано выше.

Ограничения в позе

  • Класс может представлять собой только один из своих прямых или косвенных суперклассов.

  • Класс позирования не должен определять какие-либо новые переменные экземпляра, которые отсутствуют в целевом классе (хотя он может определять или переопределять методы).

  • Целевой класс, возможно, не получил никаких сообщений до постановки.

  • Класс представления может вызывать переопределенные методы через super, включая реализацию целевого класса.

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

Класс может представлять собой только один из своих прямых или косвенных суперклассов.

Класс позирования не должен определять какие-либо новые переменные экземпляра, которые отсутствуют в целевом классе (хотя он может определять или переопределять методы).

Целевой класс, возможно, не получил никаких сообщений до постановки.

Класс представления может вызывать переопределенные методы через super, включая реализацию целевого класса.

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

#import <Foundation/Foundation.h>

@interface MyString : NSString

@end

@implementation MyString

- (NSString *)stringByReplacingOccurrencesOfString🙁NSString *)target
withString🙁NSString *)replacement {
   NSLog(@"The Target string is %@",target);
   NSLog(@"The Replacement string is %@",replacement);
}

@end

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   [MyString poseAsClass:[NSString class]];
   NSString *string = @"Test";
   [string stringByReplacingOccurrencesOfString:@"a" withString:@"c"];
   
   [pool drain];
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу в более старой Mac OS X (V_10.5 или более ранней), мы получим следующий результат.

2013-09-22 21:23:46.829 Posing[372:303] The Target string is a
2013-09-22 21:23:46.830 Posing[372:303] The Replacement string is c

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

Расширения Objective-C

Расширение класса имеет некоторое сходство с категорией, но оно может быть добавлено только к классу, для которого у вас есть исходный код во время компиляции (класс компилируется одновременно с расширением класса).

Методы, объявленные расширением класса, реализованы в блоке реализации исходного класса, поэтому вы не можете, например, объявить расширение класса в классе платформы, таком как класс Touch Cocoa или Cocoa, например NSString.

Расширения на самом деле являются категориями без названия категории. Это часто называют анонимными категориями .

Синтаксис для объявления расширения использует ключевое слово @interface, как и стандартное описание класса Objective-C, но не указывает на какое-либо наследование от подкласса. Вместо этого он просто добавляет скобки, как показано ниже —

@interface ClassName ()

@end

Характеристики расширений

  • Расширение не может быть объявлено ни для какого класса, только для классов, которые имеют оригинальную реализацию исходного кода.

  • Расширение добавляет частные методы и частные переменные, которые относятся только к классу.

  • Любой метод или переменная, объявленная внутри расширений, недоступна даже для унаследованных классов.

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

Расширение добавляет частные методы и частные переменные, которые относятся только к классу.

Любой метод или переменная, объявленная внутри расширений, недоступна даже для унаследованных классов.

Пример расширений

Давайте создадим класс SampleClass, который имеет расширение. В расширении у нас будет приватная переменная internalID.

Затем, давайте получим метод getExternalID, который возвращает externalID после обработки internalID.

Пример показан ниже, и он не будет работать на онлайн-компиляторе.

#import <Foundation/Foundation.h>

@interface SampleClass : NSObject {
   NSString *name;
}

- (void)setInternalID;
- (NSString *)getExternalID;

@end

@interface SampleClass() {
   NSString *internalID;
}

@end

@implementation SampleClass

- (void)setInternalID {
   internalID = [NSString stringWithFormat: 
   @"UNIQUEINTERNALKEY%dUNIQUEINTERNALKEY",arc4random()%100];
}

- (NSString *)getExternalID {
   return [internalID stringByReplacingOccurrencesOfString: 
   @"UNIQUEINTERNALKEY" withString:@""];
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   SampleClass *sampleClass = [[SampleClass alloc]init];
   [sampleClass setInternalID];
   NSLog(@"ExternalID: %@",[sampleClass getExternalID]);        
   [pool drain];
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-22 21:18:31.754 Extensions[331:303] ExternalID: 51

В приведенном выше примере мы видим, что internalID не возвращается напрямую. Здесь мы удаляем UNIQUEINTERNALKEY и делаем оставшееся значение доступным для метода getExternalID.

В приведенном выше примере используется только строковая операция, но она может иметь множество функций, таких как шифрование / дешифрование и так далее.

Протоколы Objective-C

Objective-C позволяет вам определять протоколы, которые объявляют методы, которые предполагается использовать для конкретной ситуации. Протоколы реализуются в классах, соответствующих протоколу.

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

Синтаксис протокола показан ниже.

@protocol ProtocolName
@required
// list of required methods
@optional
// list of optional methods
@end

Методы под ключевым словом @required должны быть реализованы в классах, соответствующих протоколу, а методы под ключевым словом @optional являются необязательными для реализации.

Вот синтаксис для класса, соответствующего протоколу

@interface MyClass : NSObject <MyProtocol>
...
@end

Это означает, что любой экземпляр MyClass будет реагировать не только на методы, объявленные специально в интерфейсе, но и на то, что MyClass также обеспечивает реализацию необходимых методов в MyProtocol. Нет необходимости переопределять методы протокола в интерфейсе класса — достаточно принятия протокола.

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

Пример показан ниже.

Live Demo

#import <Foundation/Foundation.h>

@protocol PrintProtocolDelegate
- (void)processCompleted;

@end

@interface PrintClass :NSObject {
   id delegate;
}

- (void) printDetails;
- (void) setDelegate🙁id)newDelegate;
@end

@implementation PrintClass
- (void)printDetails {
   NSLog(@"Printing Details");
   [delegate processCompleted];
}

- (void) setDelegate🙁id)newDelegate {
   delegate = newDelegate;
}

@end

@interface SampleClass:NSObject<PrintProtocolDelegate>
- (void)startAction;

@end

@implementation SampleClass
- (void)startAction {
   PrintClass *printClass = [[PrintClass alloc]init];
   [printClass setDelegate:self];
   [printClass printDetails];
}

-(void)processCompleted {
   NSLog(@"Printing Process Completed");
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   SampleClass *sampleClass = [[SampleClass alloc]init];
   [sampleClass startAction];
   [pool drain];
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-22 21:15:50.362 Protocols[275:303] Printing Details
2013-09-22 21:15:50.364 Protocols[275:303] Printing Process Completed

В приведенном выше примере мы увидели, как методы delgate вызываются и выполняются. Он начинается с startAction, после завершения процесса вызывается метод делегата processCompleted для информирования о завершении операции.

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

Objective-C Динамическое связывание

Динамическое связывание определяет способ вызова во время выполнения, а не во время компиляции. Динамическое связывание также называется поздним связыванием.

В Objective-C все методы разрешаются динамически во время выполнения. Точный исполняемый код определяется как именем метода (селектором), так и принимающим объектом.

Динамическое связывание позволяет полиморфизм. Например, рассмотрим коллекцию объектов, включая Rectangle и Square. Каждый объект имеет свою собственную реализацию метода printArea.

В следующем фрагменте кода фактический код, который должен выполняться выражением [anObject printArea], определяется во время выполнения. Система времени выполнения использует селектор для запуска метода, чтобы идентифицировать соответствующий метод в любом классе anObject.

Давайте посмотрим на простой код, который объясняет динамическое связывание.

Live Demo

#import <Foundation/Foundation.h>

@interface Square:NSObject {
   float area;
}

- (void)calculateAreaOfSide🙁CGFloat)side;
- (void)printArea;
@end

@implementation Square
- (void)calculateAreaOfSide🙁CGFloat)side {
   area = side * side;
}

- (void)printArea {
   NSLog(@"The area of square is %f",area);
}

@end

@interface Rectangle:NSObject {
   float area;
}

- (void)calculateAreaOfLength🙁CGFloat)length andBreadth🙁CGFloat)breadth;
- (void)printArea;
@end

@implementation  Rectangle

- (void)calculateAreaOfLength🙁CGFloat)length andBreadth🙁CGFloat)breadth {
   area = length * breadth;
}

- (void)printArea {
   NSLog(@"The area of Rectangle is %f",area);
}

@end

int main() {
   Square *square = [[Square alloc]init];
   [square calculateAreaOfSide:10.0];
   
   Rectangle *rectangle = [[Rectangle alloc]init];
   [rectangle calculateAreaOfLength:10.0 andBreadth:5.0];
   
   NSArray *shapes = [[NSArray alloc]initWithObjects: square, rectangle,nil];
   id object1 = [shapes objectAtIndex:0];
   [object1 printArea];
   
   id object2 = [shapes objectAtIndex:1];
   [object2 printArea];
   
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-28 07:42:29.821 demo[4916] The area of square is 100.000000
2013-09-28 07:42:29.821 demo[4916] The area of Rectangle is 50.000000

Как видно из приведенного выше примера, метод printArea динамически выбирается во время выполнения. Это пример динамического связывания и весьма полезен во многих ситуациях при работе с объектами подобного типа.

Objective-C Композитные объекты

Мы можем создать подкласс в кластере классов, который определяет класс, который встраивает в него объект. Эти объекты класса являются составными объектами.

Так что вам может быть интересно, что такое кластер классов. Итак, сначала мы увидим, что такое кластер классов.

Кластеры классов

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

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

Например, в NSNumber у нас есть много кластеров классов, таких как char, int, bool и так далее. Мы группируем их все в один класс, который заботится об обработке подобных операций в одном классе. NSNumber фактически оборачивает значение этих примитивных типов в объекты.

Так что же такое составной объект?

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

Это объясняется на следующем рисунке.

Objective-C Композитные объекты

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

Метод count класса NSArray является примером; реализация метода объекта, который он переопределяет, может быть настолько простой, как:

- (unsigned)count  {
   return [embeddedObject count];
}

В приведенном выше примере встроенный объект на самом деле имеет тип NSArray.

Пример составного объекта

Теперь, чтобы увидеть полный пример, давайте посмотрим на пример из документации Apple, которая приведена ниже.

Live Demo

#import <Foundation/Foundation.h>

@interface ValidatingArray : NSMutableArray {
   NSMutableArray *embeddedArray;
}

+ validatingArray;
- init;
- (unsigned)count;
- objectAtIndex🙁unsigned)index;
- (void)addObject:object;
- (void)replaceObjectAtIndex🙁unsigned)index withObject:object;
- (void)removeLastObject;
- (void)insertObject:object atIndex🙁unsigned)index;
- (void)removeObjectAtIndex🙁unsigned)index;

@end

@implementation ValidatingArray
- init {
   self = [super init];
   if (self) {
      embeddedArray = [[NSMutableArray allocWithZone:[self zone]] init];
   }
   return self;
}

+ validatingArray {
   return [[self alloc] init] ;
}

- (unsigned)count {
   return [embeddedArray count];
}

- objectAtIndex🙁unsigned)index {
   return [embeddedArray objectAtIndex:index];
}

- (void)addObject🙁id)object {
   if (object != nil) {
      [embeddedArray addObject:object];
   }
}

- (void)replaceObjectAtIndex🙁unsigned)index withObject🙁id)object; {
   if (index <[embeddedArray count] && object != nil) {
      [embeddedArray replaceObjectAtIndex:index withObject:object];
   }
}

- (void)removeLastObject; {
   if ([embeddedArray count] > 0) {
      [embeddedArray removeLastObject];
   }
}

- (void)insertObject🙁id)object atIndex🙁unsigned)index; {
   if (object != nil) {
      [embeddedArray insertObject:object atIndex:index];
   }
}

- (void)removeObjectAtIndex🙁unsigned)index; {
   if (index <[embeddedArray count]) {
      [embeddedArray removeObjectAtIndex:index];
   }
}

@end

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   ValidatingArray *validatingArray = [ValidatingArray validatingArray];
   
   [validatingArray addObject:@"Object1"];
   [validatingArray addObject:@"Object2"];
   [validatingArray addObject:[NSNull null]];
   [validatingArray removeObjectAtIndex:2];
   NSString *aString = [validatingArray objectAtIndex:1];
   NSLog(@"The value at Index 1 is %@",aString);
   [pool drain];
   
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-28 22:03:54.294 demo[6247] The value at Index 1 is Object2

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

Основы Obj-C Foundation

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

Платформа Foundation определяет базовый уровень классов Objective-C. В дополнение к предоставлению набора полезных примитивных классов объектов, он вводит несколько парадигм, которые определяют функциональные возможности, не охватываемые языком Objective-C. Основа фонда разработана с учетом этих целей —

  • Предоставить небольшой набор базовых служебных классов.

  • Упростите разработку программного обеспечения, введя согласованные соглашения для таких вещей, как освобождение.

  • Поддержка Unicode-строк, постоянство объектов и распределение объектов.

  • Обеспечение уровня независимости ОС для повышения мобильности.

Предоставить небольшой набор базовых служебных классов.

Упростите разработку программного обеспечения, введя согласованные соглашения для таких вещей, как освобождение.

Поддержка Unicode-строк, постоянство объектов и распределение объектов.

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

Фреймворк был разработан NeXTStep, который был приобретен Apple, и эти базовые классы стали частью Mac OS X и iOS.

Поскольку он был разработан NeXTStep, он имеет префикс класса «NS».

Мы использовали Foundation Framework во всех наших примерах программ. Почти необходимо использовать Foundation Framework.

Обычно мы используем что-то вроде #import <Foundation / NSString.h> для импорта класса Objective-C, но во избежание импорта слишком большого числа классов все это импортируется в #import <Foundation / Foundation.h> .

NSObject — это базовый класс всех объектов, включая классы базового набора. Он предоставляет методы для управления памятью. Он также предоставляет базовый интерфейс к системе времени выполнения и возможность вести себя как объекты Objective-C. Он не имеет базового класса и является корнем для всех классов.

Базовые классы на основе функциональности

Sr.No. Тип и описание петли
1 Хранилище данных

NSArray, NSDictionary и NSSet предоставляют хранилище для объектов Objective-C любого класса.

2 Текст и строки

NSCharacterSet представляет различные группы символов, которые используются классами NSString и NSScanner. Классы NSString представляют текстовые строки и предоставляют методы для поиска, объединения и сравнения строк. Объект NSScanner используется для сканирования чисел и слов из объекта NSString.

3 Даты и время

Классы NSDate, NSTimeZone и NSCalendar хранят время и даты и представляют календарную информацию. Они предлагают методы для расчета даты и времени. Вместе с NSLocale они предоставляют методы для отображения даты и времени во многих форматах и ​​для корректировки времени и даты в зависимости от местоположения в мире.

4 Обработка исключений

Обработка исключений используется для обработки непредвиденных ситуаций и предлагается в Objective-C с NSException.

5 Обработка файлов

Обработка файлов осуществляется с помощью класса NSFileManager.

6 Система загрузки URL

Набор классов и протоколов, обеспечивающих доступ к общим интернет-протоколам.

NSArray, NSDictionary и NSSet предоставляют хранилище для объектов Objective-C любого класса.

NSCharacterSet представляет различные группы символов, которые используются классами NSString и NSScanner. Классы NSString представляют текстовые строки и предоставляют методы для поиска, объединения и сравнения строк. Объект NSScanner используется для сканирования чисел и слов из объекта NSString.

Классы NSDate, NSTimeZone и NSCalendar хранят время и даты и представляют календарную информацию. Они предлагают методы для расчета даты и времени. Вместе с NSLocale они предоставляют методы для отображения даты и времени во многих форматах и ​​для корректировки времени и даты в зависимости от местоположения в мире.

Обработка исключений используется для обработки непредвиденных ситуаций и предлагается в Objective-C с NSException.

Обработка файлов осуществляется с помощью класса NSFileManager.

Набор классов и протоколов, обеспечивающих доступ к общим интернет-протоколам.

Objective-C Быстрое перечисление

Быстрое перечисление — это функция Objective-C, которая помогает в перечислении через коллекцию. Итак, чтобы узнать о быстром перечислении, нам нужно сначала узнать о коллекции, что будет объяснено в следующем разделе.

Коллекции в Objective-C

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

Существует несколько разных типов коллекций. Хотя все они выполняют одну и ту же цель, заключающуюся в том, что они могут содержать другие объекты, они различаются в основном способом извлечения объектов. Наиболее распространенные коллекции, используемые в Objective-C, —

  • NSSet
  • NSArray
  • NSDictionary
  • NSMutableSet
  • NSMutableArray
  • NSMutableDictionary

Если вы хотите узнать больше об этих структурах, обратитесь к хранилищу данных в Foundation Framework .

Синтаксис быстрого перечисления

for (classType variable in collectionObject ) { 
  statements 
}

Вот пример для быстрого перечисления.

Live Demo

#import <Foundation/Foundation.h>

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   NSArray *array = [[NSArray alloc]
   initWithObjects:@"string1", @"string2",@"string3",nil];
   
   for(NSString *aString in array) {
      NSLog(@"Value: %@",aString);
   }
   
   [pool drain];
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-28 06:26:22.835 demo[7426] Value: string1
2013-09-28 06:26:22.836 demo[7426] Value: string2
2013-09-28 06:26:22.836 demo[7426] Value: string3

Как вы можете видеть в выводе, каждый из объектов в массиве печатается в порядке.

Быстрое перечисление в обратном направлении

for (classType variable in [collectionObject reverseObjectEnumerator] ) { 
  statements 
}

Вот пример для reverseObjectEnumerator в быстром перечислении.

Live Demo

#import <Foundation/Foundation.h>

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   NSArray *array = [[NSArray alloc]
   initWithObjects:@"string1", @"string2",@"string3",nil];
   
   for(NSString *aString in [array reverseObjectEnumerator]) {
      NSLog(@"Value: %@",aString);
   }
   
   [pool drain];
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий результат.

2013-09-28 06:27:51.025 demo[12742] Value: string3
2013-09-28 06:27:51.025 demo[12742] Value: string2
2013-09-28 06:27:51.025 demo[12742] Value: string1

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

Управление памятью Obj-C

Управление памятью является одним из наиболее важных процессов в любом языке программирования. Это процесс, посредством которого память объектов выделяется, когда они требуются, и освобождается, когда они больше не требуются.

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

Objective-C Методы управления памятью можно разделить на два типа.

  • «Ручное удержание-отпускание» или MRR
  • «Автоматический подсчет ссылок» или ARC

«Ручное удержание-отпускание» или MRR

В MRR мы явно управляем памятью, отслеживая объекты самостоятельно. Это реализовано с использованием модели, известной как подсчет ссылок, которую NSObject класса Foundation предоставляет в сочетании со средой выполнения.

Единственная разница между MRR и ARC заключается в том, что удержание и разблокирование обрабатываются нами вручную в первом, а в последнем автоматически.

На следующем рисунке представлен пример того, как работает управление памятью в Objective-C.

Objective-C Управление памятью

Жизненный цикл памяти объекта класса A показан на рисунке выше. Как вы можете видеть, счет сохранения отображается под объектом, когда счет сохранения объекта становится равным 0, объект полностью освобождается, и его память освобождается для использования другими объектами.

Объект класса A сначала создается с использованием метода alloc / init, доступного в NSObject. Теперь счет удержания становится 1.

Теперь класс B сохраняет объект класса A, а количество сохраняемых объектов класса A становится равным 2.

Затем класс C делает копию объекта. Теперь он создается как еще один экземпляр класса A с такими же значениями для переменных экземпляра. Здесь счет сохранения равен 1, а не счет хранения исходного объекта. Это представлено пунктирной линией на рисунке.

Скопированный объект высвобождается классом C с использованием метода release, и счет сохранения становится равным 0, и, следовательно, объект уничтожается.

В случае начального объекта класса A, счет удержания равен 2, и его необходимо дважды разблокировать, чтобы уничтожить. Это делается с помощью инструкций выпуска класса A и класса B, которые уменьшают количество сохраняемых данных до 1 и 0 соответственно. Наконец, объект уничтожен.

Основные правила MRR

  • У нас есть любой объект, который мы создаем: мы создаем объект, используя метод, имя которого начинается с «alloc», «new», «copy» или «mutableCopy»

  • Мы можем вступить во владение объектом, используя retain: полученный объект обычно гарантированно остается действительным в методе, в котором он был получен, и этот метод также может безопасно вернуть объект своему вызывающему. Мы используем удержание в двух ситуациях —

    • В реализации метода доступа или метода init, чтобы стать владельцем объекта, мы хотим сохранить его в качестве значения свойства.

    • Для предотвращения признания объекта недействительным в качестве побочного эффекта какой-либо другой операции.

  • Когда он нам больше не нужен, мы должны отказаться от права собственности на принадлежащий нам объект: мы отказываемся от права собственности на объект, отправив ему сообщение о выпуске или сообщение об автоматическом выпуске. Таким образом, в терминологии какао отказ от владения объектом обычно называется «высвобождением» объекта.

  • Вы не должны отказываться от владения объектом, который вам не принадлежит: это всего лишь следствие предыдущих правил политики, установленных в явном виде.

У нас есть любой объект, который мы создаем: мы создаем объект, используя метод, имя которого начинается с «alloc», «new», «copy» или «mutableCopy»

Мы можем вступить во владение объектом, используя retain: полученный объект обычно гарантированно остается действительным в методе, в котором он был получен, и этот метод также может безопасно вернуть объект своему вызывающему. Мы используем удержание в двух ситуациях —

В реализации метода доступа или метода init, чтобы стать владельцем объекта, мы хотим сохранить его в качестве значения свойства.

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

Когда он нам больше не нужен, мы должны отказаться от права собственности на принадлежащий нам объект: мы отказываемся от права собственности на объект, отправив ему сообщение о выпуске или сообщение об автоматическом выпуске. Таким образом, в терминологии какао отказ от владения объектом обычно называется «высвобождением» объекта.

Вы не должны отказываться от владения объектом, который вам не принадлежит: это всего лишь следствие предыдущих правил политики, установленных в явном виде.

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
- (void)sampleMethod;
@end

@implementation SampleClass
- (void)sampleMethod {
   NSLog(@"Hello, World! \n");
}

- (void)dealloc  {
  NSLog(@"Object deallocated");
  [super dealloc];
}

@end

int main() {
   
   /* my first program in Objective-C */
   SampleClass *sampleClass = [[SampleClass alloc]init];
   [sampleClass sampleMethod];
   
   NSLog(@"Retain Count after initial allocation: %d", 
   [sampleClass retainCount]);
   [sampleClass retain];
   
   NSLog(@"Retain Count after retain: %d", [sampleClass retainCount]);
   [sampleClass release];
   NSLog(@"Retain Count after release: %d", [sampleClass retainCount]);
   [sampleClass release];
   NSLog(@"SampleClass dealloc will be called before this");
   
   // Should set the object to nil
   sampleClass = nil;
   return 0;
}

Когда мы скомпилируем вышеуказанную программу, мы получим следующий вывод.

2013-09-28 04:39:52.310 demo[8385] Hello, World!
2013-09-28 04:39:52.311 demo[8385] Retain Count after initial allocation: 1
2013-09-28 04:39:52.311 demo[8385] Retain Count after retain: 2
2013-09-28 04:39:52.311 demo[8385] Retain Count after release: 1
2013-09-28 04:39:52.311 demo[8385] Object deallocated
2013-09-28 04:39:52.311 demo[8385] SampleClass dealloc will be called before this

«Автоматический подсчет ссылок» или ARC

В автоматическом подсчете ссылок или ARC система использует ту же систему подсчета ссылок, что и MRR, но она вставляет соответствующие вызовы метода управления памятью для нас во время компиляции. Мы настоятельно рекомендуем использовать ARC для новых проектов. Если мы используем ARC, обычно нет необходимости понимать основную реализацию, описанную в этом документе, хотя в некоторых ситуациях это может быть полезно. Для получения дополнительной информации о ARC см. Переход к примечаниям к выпуску ARC.

Как уже упоминалось выше, в ARC нам не нужно добавлять методы release и retain, поскольку об этом позаботится компилятор. На самом деле, основной процесс Objective-C все тот же. Он использует операции сохранения и выпуска для внутреннего использования, что облегчает разработчику кодирование, не беспокоясь об этих операциях, что уменьшит как объем написанного кода, так и возможность утечек памяти.

Был еще один принцип, называемый сборкой мусора, который используется в Mac OS-X вместе с MRR, но с момента его устаревания в OS-X Mountain Lion он не обсуждался вместе с MRR. Кроме того, объекты iOS никогда не имели функции сборки мусора. А с ARC также нет необходимости в сборке мусора в OS-X.

Вот простой пример ARC. Обратите внимание, что это не будет работать на онлайн-компиляторе, так как он не поддерживает ARC.

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
- (void)sampleMethod;
@end

@implementation SampleClass
- (void)sampleMethod {
   NSLog(@"Hello, World! \n");
}

- (void)dealloc  {
  NSLog(@"Object deallocated");
}

@end

int main() {
   /* my first program in Objective-C */
   @autoreleasepool {
      SampleClass *sampleClass = [[SampleClass alloc]init];
      [sampleClass sampleMethod];
      sampleClass = nil;
   }
   return 0;
}

Когда мы скомпилируем вышеуказанную программу, мы получим следующий вывод.