├── .DS_Store
├── Answers
├── .DS_Store
├── General
│ ├── .DS_Store
│ ├── 1.General.md
│ ├── 2.OOP.md
│ ├── 3.Data_structures.md
│ ├── OOP
│ │ ├── .DS_Store
│ │ ├── Abstract_class_vs_interface.md
│ │ ├── Encapsulation.md
│ │ └── Polymorphism.md
│ ├── Pattern
│ │ ├── .DS_Store
│ │ ├── Little_bit_about_patterns.md
│ │ ├── MVC_active_vs_passive.md
│ │ ├── Singleton.md
│ │ └── Singleton_arc_non_arc.md
│ └── SOLID.md
├── Multithreading
│ ├── Deadlock.md
│ ├── Livelock.md
│ ├── Race_condition.md
│ ├── another_thread_technology.md
│ ├── deadlock_example_1.md
│ ├── dispatch_sync_vs_async.md
│ ├── mutex.md
│ └── semaphore.md
├── Networking
│ └── .DS_Store
├── UIKit
│ ├── .DS_Store
│ ├── App_lifecycle.md
│ ├── Frame_vs_Bounds.md
│ ├── How_to_work_with_push_notification.md
│ ├── IBOutlet_vs_IBAction.md
│ ├── Multithreading_with_UI
│ │ ├── .DS_Store
│ │ ├── Async.png
│ │ ├── Multithreading_with_UI.md
│ │ └── Sync.png
│ ├── Responder_chain.md
│ ├── Size_of_iPhone_and_different_between_points_and_pixels.md
│ ├── UIViewController_lifecycle.md
│ └── Use_UITableView.md
├── code_puzzles
│ ├── GCD_example_1.md
│ ├── code_puzzles_1.md
│ ├── code_puzzles_2.md
│ └── method_classA_and_classB.md
├── coredata
│ ├── coredata.md
│ ├── coredata_vs_threads.md
│ ├── nsfetchresultcontroller.md
│ └── sqlite_vs_coredata.md
├── logical
│ └── bridge.md
├── memory_managment
│ ├── arc.md
│ ├── atomic_vs_nonatomic.md
│ ├── autorelease_pool.md
│ ├── autorelease_vs_release.md
│ ├── how_use_non_arc_libs.md
│ ├── manual_allocation.md
│ ├── memory_warning.md
│ ├── mrc.md
│ ├── retain_delegate.md
│ └── weak_vs_assign__strong_vs_copy.md
├── networking
│ ├── difference_between_head_get_post_put.md
│ ├── http_tcp.md
│ └── rest.md
├── objective_c
│ ├── NSSet_NSArray.md
│ ├── add_property_in_runtime.md
│ ├── autorelease.md
│ ├── base_oop_term_per_objc.md
│ ├── category_vs_extention.md
│ ├── category_vs_inheritance.md
│ ├── delegate.md
│ ├── delegate_vs_notification.md
│ ├── designated_initializer.md
│ ├── fast_enumeration.md
│ ├── formal_vs_informal_protocol.md
│ ├── how_get_current_coordinate.md
│ ├── implicit_property.md
│ ├── instancetype.md
│ ├── isa.md
│ ├── ivar_access.md
│ ├── ivar_in_category.md
│ ├── kvo.md
│ ├── new_methods.md
│ ├── nil_Nil_NSNull.md
│ ├── noname_methods.md
│ ├── not_find_method_in_object.md
│ ├── nsarray_nsmutablearray.md
│ ├── nsfastenumaration.md
│ ├── nsobject_vs_id.md
│ ├── print_autoreleasepool.md
│ ├── private_and_protected_methods.md
│ ├── proxing.md
│ ├── root_classes.md
│ ├── run_loop.md
│ ├── runtime.md
│ ├── selector.md
│ ├── send_message_to_id.md
│ └── uinavigationcontroller.md
└── swift
│ └── weak_vs_unowned.md
└── README.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/.DS_Store
--------------------------------------------------------------------------------
/Answers/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/.DS_Store
--------------------------------------------------------------------------------
/Answers/General/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/General/.DS_Store
--------------------------------------------------------------------------------
/Answers/General/1.General.md:
--------------------------------------------------------------------------------
1 | # Основные понятия программирования
2 |
3 | ### Бит и байт
4 | Информация –– мера разрешения неопределенности.
5 | Бит (Binary digIT, bit – кусочек) выбран как мера неопределенности с двумя возможными состояниями: истина | ложь, да | нет, 1 | 0. Любые данные в компьютере представлены в виде последовательности битов. Цифровая информация хранится благодаря различию между разными величинами какой-либо физической характеристики (ток, напряжение) => чем больше велечин, которые нужно различать, тем меньше различий между смежными величинами => тем менее надежна память. В двоичной системе следует различать всего два состояния => это самый надеждный метод кодирования информации.
6 | Байт — совокупность битов, обрабатываемая компьютером одномоментно. В современных вычислительных системах байт состоит из восьми битов и, соответственно, может принимать одно из 256 (`2^8 = 256`) различных значений (состояний, кодов).
7 | ### Память
8 | Сверхоперативная, оперативная и внешняя. Некоторые регистры сверхоперативной памяти, в которые могут помещаться аргументы арифметических операций, находятся в ЦП. Также они используются для хранения текущих или следующих команд. Оперативная память служит для запоминания более постоянной информации. Каждая ячейка оперативной памяти имеет свой идентификатор (адрес) в массиве ячеек памяти. Самая маленькая ячейка имеет размер 8 бит (байт). Внешняя память служит для долговременного хранения информации, используется для хранения самих программ.
9 | ### Тип данных
10 | Тип данных характеризует одновременно:
11 | - множество допустимых значений, которые могут принимать данные, принадлежащие к этому типу;
12 | - набор операций, которые можно осуществлять над данными, принадлежащими к этому типу.
13 |
14 | Распространённые типы данных:
15 | - Логический
16 | - Целочисленный
17 | - Числа с плавающей запятой
18 | - Строковый
19 | - Указатели
20 |
21 | Тип данных указывает, как будут использоваться определенные наборы битов. Функция задает операции, выполняемые над данными. Структура служит для группировки порций информации. Указатели – для непрямой ссылки на информацию. Абстрактный тип данных – тип данных с доступом через интерфейс, реализация которого скрыта. Доступ к переменным – через операции, определенные в интерфейсе.
22 | ### Структура данных
23 | Пространственное понятие: схема организации информации в компьютере. Множество элементов данных и множество связей между ними. От выбора структуры данных зависит производительность программы. Тип структуры данных определяет:
24 |
25 | - Как хранятся данные в структуре (выделение памяти, представление данных)
26 | - Множество допустимых значений, который принимает объект в структуре данных
27 | - Множество операций, которые могут применяться к объекту
28 |
29 | Операции над структурами данных – __CRUD__:
30 | - CREATE
31 | - READ
32 | - UPDATE
33 | - DELETE
34 |
35 | Структура данных в ООП реализуется в виде классов, данные хранятся в переменных класса, системе предписаний соответстует набор методов класса.
36 | - ПРОСТЫЕ БАЗОВЫЕ (числовые, символьные, логические, перечисление, интервал, указатели)
37 | - СТАТИЧЕСКИЕ (вектор, массив, множество, запись, таблица)
38 | - ПОЛУСТАТИЧЕСКИЕ (стек, очередь, дек, строка)
39 | - ДИНАМИЧЕСКИЕ (связный список, граф, дерево)
40 | ### Алгоритмы
41 | «Рецепт расчета» – метод, разработанный для решения задачи, пригодный для реализации в компьютерной программе. Сам алгоритм является абстракцией, но его представление – конкретно и может меняться в зависимости от архитектуры компьютера, языка программирования и т. д. Представление алгоритма конструируется из блоков – примитивов. Набор примитивов и правил, как комбинировать эти примитивы для воплощения более сложных идей организуют язык программирования. Примитив состоит из синтаксической и семантической части. Описание алгоритма на низком уровне – неудобно, поэтому используются абстракции для примитивов более высокого уровня, которые состоят из примитивов низкого. Итерационная структура – выполнение набора инструкций в циклическом режиме. Рекурсивная – каждая стадия повторения цикла реализуется как подзадача предыдущей стадии. Чтобы оценить производительность нужно подсчитать количество операций. Различают временную сложность и пространственную (используемая память).
42 |
43 | `О` – (сложность в наихудшем случае), асимптотическая верхняя оценка количества операций => времени работы (худший вариант). При оценке берется количество операций, возрастающих быстрее всего.
44 |
45 | `Ω` – сложность в лучшем случае
46 |
47 | `Θ` – сложность в среднем, когда оценка `Ω = О`
48 |
49 | Наилучшая оценка алгоритма – `О(1)`, константная, когда алгоритм без циклов и рекурсии.
50 | ### Программирование
51 | Процесс создания компьютерных программ. В узком смысле (так называемое кодирование) под программированием понимается написание инструкций (программ) на конкретном языке программирования (часто по уже имеющемуся алгоритму — плану, методу решения поставленной задачи). В настоящее время активно используются интегрированные среды разработки (IDE), включающие в свой состав также редактор для ввода и редактирования текстов программ, отладчики для поиска и устранения ошибок, трансляторы с различных языков программирования, компоновщики для сборки программы из нескольких модулей и другие служебные модули. С помощью текстового редактора программист производит набор и редактирования текста создаваемой программы, который называют исходным кодом. Язык программирования определяет синтаксис и изначальную семантику исходного кода. Компилятор преобразует текст программы в машинный код, непосредственно исполняемый электронными компонентами компьютера. Интерпретатор создаёт виртуальную машину для выполнения программы, которая полностью или частично берёт на себя функции исполнения программ.
52 | Код –> препроцессор (#define, etc. – развертывание, замена) –> компилятор –> машинный код
53 |
54 | Язык программирования — формальная знаковая система, предназначенная для записи компьютерных программ. Служит для точного описания абстрактных структур данных и алгоритмов. Компилятор транслирует текст программы на языке программирования в машинный код, связывая каждый идентификатор (имя) с адресом памяти.
55 |
56 | Классы языков программирования:
57 |
58 | * Функциональные
59 |
60 | _Lisp, Erlang, Haskell, Scala_
61 |
62 | На основе достаточно строгих абстрактных понятий и методов символьной обработки данных. Тексты программ на функциональных языках программирования описывают «как решить задачу», но не предписывают последовательность действий для решения.
63 |
64 | * Процедурные (императивные)
65 |
66 | _C, Basic, Pascal_
67 |
68 | Последовательно выполняемые операторы можно собрать в подпрограммы, то есть более крупные целостные единицы кода, с помощью механизмов самого языка. Процедурное программирование является отражением архитектуры традиционных ЭВМ. Процедурный язык программирования предоставляет возможность программисту определять каждый шаг в процессе решения задачи. Особенность таких языков программирования состоит в том, что задачи разбиваются на шаги и решаются шаг за шагом. Используя процедурный язык, программист определяет языковые конструкции для выполнения последовательности алгоритмических шагов.
69 |
70 | * Динамические
71 |
72 | _Perl, Tcl, Python, PHP, Ruby, Smalltalk, JavaScript_
73 |
74 | Позволяют определять типы данных и осуществлять синтаксический анализ и компиляцию «на лету», на этапе выполнения программы. Динамические языки удобны для быстрой разработки приложений. Динамическая типизация (при котором перемен-ная связывается с типом в момент присваивания значения, а не в момент объявления переменной. Таким образом, в различных участках программы одна и та же переменная мо-жет принимать значения разных типов) является основным, но не единственным критерием динамического языка программирования.
75 |
76 | * Объектно-ориентированные
77 |
78 | _C#, C++, Java. Objective-C, Perl, Python, Scala, Ruby, Smaltalk, PHP_
79 |
80 | Язык, построенный на принципах объектно-ориентированного программирования. В основе концепции объектно-ориентированного программирования лежит понятие объекта — некой сущности, которая объединяет в себе поля (данные) и методы (выполняемые объектом действия).
81 | ### API
82 | Интерфейс программирования приложений (иногда интерфейс прикладного программирования) (application programming interface) — набор готовых классов, процедур, функций, структур и констант, предоставляемых приложением (библиотекой, сервисом) для использования во внешних программных продуктах. Используется программистами для написания всевозможных приложений. API операционных систем: Cocoa, Windows API. API не решение для системы (как фреймворк), а доступ к функциям другой системы.
83 | ### IDE
84 | Интегрированная среда разработки (integrated development environment) — система программных средств, используемая программистами для разработки программного обеспечения.
85 | Обычно, среда разработки включает в себя:
86 |
87 | * текстовый редактор
88 | * компилятор и/или интерпретатор
89 | * средства автоматизации сборки
90 | * отладчик
91 | ### Высокоуровневый язык программирования
92 | Язык программирования, разработанный для быстроты и удобства использования программистом. Основная черта высокоуровневых языков — это абстракция, то есть введение смысловых конструкций, кратко описывающих такие структуры данных и операции над ними, описания которых на машинном коде (или другом низкоуровневом языке программирования) очень длинны и сложны для понимания.
93 | ### Компиляция
94 | Трансляция программы, составленной на исходном языке высокого уровня, в эквивалентную программу на низкоуровневом языке, близком машинному коду (абсолютный код, объектный модуль, иногда на язык ассемблера). Входной информацией для компилятора (исходный код) является описание алгоритма или программа на проблемно-ориентированном языке, а на выходе компилятора — эквивалентное описание алгоритма на машинно-ориентированном языке (объектный код). Компилировать — проводить трансляцию машинной программы с проблемно-ориентированного языка на машинно-ориентированный язык.
95 | ### Программа
96 | Структуры данных и алгоритмы – это материалы, из которых строятся программы и сам компьютер. В основе работы компьютера – умение работать с двоичными данными, битами, под командами центрального процессора в виде специальных инструкций – алгоритмов. Задачи редко выражаются в виде битов: они выражаются в виде чисел, символов, строк и более сложных структур – последовательностей, списков, деревьев и т. д. Задача, которую решает программа – преобразование входных данных в выходные.
97 |
--------------------------------------------------------------------------------
/Answers/General/2.OOP.md:
--------------------------------------------------------------------------------
1 | ### Объект
2 | Сущность в виртуальном пространстве, которой можно посылать сообщения и которая может на них реагировать, используя свои данные, появляющаяся при создании экземпляра класса или копирования прототипа, обладающая определённым состоянием и поведением, имеющая заданные значения свойств (атрибутов) и операций над ними (методов). Как правило, при рассмотрении объектов выделяется то, что объекты принадлежат одному или нескольким классам, которые определяют поведение или роль (являются моделями) объекта. Объект, наряду с понятием класс, является важным понятием объектно-ориентированного подхода. Объекты обладают свойствами наследования, инкапсуляции и полиморфизма.
3 | ### Прототип
4 | Объект-образец, по образу и подобию которого создаются другие объекты. Объекты-копии могут сохранять связь с родительским объектом, автоматически наследуя изменения в прототипе.
5 | ### Класс
6 | Модель еще не существующей сущности (объекта). Описывает устройство объекта, является как бы чертежом объекта.
7 | ### Метод
8 | Это функция или процедура, принадлежащая какому-то классу или объекту. Методы предоставляют интерфейс, при помощи которого осуществляется доступ к данным объекта некоторого класса, тем самым, обеспечивая инкапсуляцию данных. Метод класса может использоваться для создания новых объектов и называется фабричным методом.
9 | ### Глобальная переменная
10 | Объявляется в начале программы вне любого метода, значение которой можно использовать из любого места модуля или другого файла.
11 | ### Локальная переменная
12 | Существует только во время выполнения метода и доступ к ним может выполняться только внутри метода, в котором она определена.
13 | ### Статическая переменная
14 | Сохраняет свое значение при нескольких вызовах метода, в отличие от локальной переменной. Инициализируется только один раз в начале выполнения программы.
15 | ### Переменная экземпляра, instance variable, ivar
16 | Данные, которые может содержать объект класса. Каждый раз создавая новый объект, создается и новый, причем уникальный, набор переменных экземпляра объекта. Поэтому, если у вас имеется два экземпляра объекта класса `Fraction`, к примеру, `fractionA` и `fractionB`, то каждый из них будет иметь свой собственный набор переменных. То есть, `fractionA` и `fractionB` будут иметь свои собственные `numerator` и `denominator`.
17 |
18 | ### Абстракция
19 | Смысловая конструкция, кратко описывающая структуру данных и операции над ними для упрощения понимания. Отделение объекта от его реализации (данные обрабатываются функцией высокого уровня с помощью функции низкого уровня). Существует из-за неудобства описания операций на низком уровне.
20 |
21 | ### Наследование
22 | Процесс при котором один объект приобретает свойства и методы другого объекта.
23 |
24 | ### Инкапсуляция
25 | ```Инкапсуляция (англ. encapsulation)``` это фундаментальная объектно-ориентированная концепция, позволяющая упаковывать данные и поведение в единый компонент с разделением его на обособленные части - интерфейс и реализацию.
26 |
27 | Еще одно описание:
28 | * механизм языка, позволяющий ограничить доступ одних компонентов программы к другим;
29 | * языковая конструкция, позволяющая связать данные с методами, предназначенными для обработки этих данных.
30 |
31 | Говоря бытовым языком: мы скрываем реализацию от пользователя, предоставляя ему интерфейс. Как класс или метод реализован на самом деле - пользователю знать не обязательно. Для этого существуют уровни доступа.
32 |
33 | Swift предлагает четыре различных уровня доступа для объектов вашего кода. Эти уровни доступа относительны исходному файлу, в котором определен объект, и так же они относительны модулю, которому принадлежит исходный файл:
34 |
35 | Открытый доступ и публичный доступ (**open access** и **public access**). Этот уровень доступа позволяет использовать объекты внутри любого исходного файла из определяющего их модуля и так же в любом исходном файле из другого модуля, который импортирует определяющий модуль. Вы обычно используете открытый и публичный доступы, когда указываете общий интерфейс фреймворка.
36 |
37 | Внутренний (**internal access**). Этот уровень доступа позволяет использовать объекты внутри любого исходного файла из их определяющего модуля, но не исходного файла не из этого модуля. Вы обычно указываете внутренний доступ , когда определяете внутреннюю структуру приложения или фреймворка.
38 |
39 | Файл-частный (**file private**). Этот уровень доступа позволяет использовать объект в пределах его исходного файла. Используйте файл-частный уровень доступа для того, чтобы спрятать детали реализации определенной части функциональности, когда эти части функциональности будут используются внутри другого файла.
40 |
41 | Частный (**private**). Этот уровень доступа позволяет использовать сущность только в пределах области ее реализации. Используйте частный доступ для того, чтобы спрятать детали реализации конкретной части функциональности, когда они используются только внутри области объявления.
42 |
43 | Классы, с уровнем доступа **public**, могут наследоваться только в том модуле, в котором они определены.
44 | Члены класса с уровнем доступа public или с более строгим уровнем доступа могут быть переопределены подклассами только в том модуле, в котором они определены.
45 | Открытые классы могут наследоваться внутри модуля, в котором они определены и внутри модуля, который импортирует модуль, в котором они определены.
46 | Открытые члены класса могут переопределяться подклассами внутри модуля, в котором они были определены или внутри модуля, который импортирует модуль, в котором они были определены.
47 |
48 | ### Полиморфизм
49 | Полиморфизм - это один из базовых принципов объектно-ориентированного программирования (ООП). Полиморфизмом называется возможность работать с несколькими типами так, как будто это один и тот же тип и в то же время поведение каждого типа будет уникальным в зависимости от его реализации.
50 |
51 | Звучит достаточно трудно, поэтому попробую привести пример:
52 | ```swift
53 | func a() {
54 | print("First function")
55 | }
56 |
57 | func a (b: String) {
58 | print(b)
59 | }
60 | ```
61 |
62 | Таким образом у нас 2 функции с одним именем, но разница в принимаемых значениях и теперь мы можем вызывать обе функции.
63 | ```swift
64 | a() //First function
65 |
66 | a(b: "Second function") //Second function
67 | ```
--------------------------------------------------------------------------------
/Answers/General/3.Data_structures.md:
--------------------------------------------------------------------------------
1 | - [Структуры данных](#структуры-данных)
2 | - [Массив](#массив)
3 | - [Ассоциативный массив](#ассоциативный-массив)
4 | - [Хеш-таблица](#xеш-таблица)
5 | - [Множество](#множество)
6 | - [Список](#список)
7 | - [Связный список ](#связный-список)
8 | - [Двусвязный список ](#двусвязный-список)
9 | - [Кольцевой список ](#кольцевой-список)
10 | - [Очередь](#очередь)
11 | - [Стек ](#стек)
12 | - [Дек](#дек)
13 | - [Куча](#куча)
14 | - [Граф](#граф)
15 | - [Дерево](#дерево)
16 | - [Бинарное дерево поиска](#бинарное-дерево-поиска)
17 | - [Красно-черное дерево](#красно-черное-дерево)
18 |
19 |
20 | # Структуры данных
21 |
22 |
23 |
24 |
25 |
26 |
27 | ## Массив
28 | _array_
29 |
30 | Фиксированный набор данных одного типа в виде непрерывного ряда. Простая базовая статическая структура данных с последовательным распределением элементов в памяти с прямым или произвольным доступом (одномерный массив – вектор, двухмерный – матрица).
31 |
32 |
33 |
34 | Операции:
35 | * Получить элемент за время `log(n)`
36 | * Записать элемент
37 |
38 | Плюсы:
39 | * Доступ за постоянное время
40 | * Память тратится только на данные
41 |
42 | Минусы:
43 | * Статичная, неизменяемая структура
44 |
45 |
46 | ### Ассоциативный массив
47 | _associative array, map, symbol table, dictionary_
48 |
49 | An associative array, map, symbol table, or dictionary is an abstract data type composed of a collection of pairs, such that each possible key appears at most once in the collection.
50 | Operations associated with this data type allow:
51 | * the addition of pairs to the collection
52 | * the removal of pairs from the collection
53 | * the modification of the values of existing pairs
54 | * the lookup of the value associated with a particular key
55 |
56 | Ассоциативный массив еще называют нагруженным множеством (data + info), где data – ключ, а нагрузка – значение ключа.
57 |
58 |
59 | #### Хеш-таблица
60 | _hash table, hash map_
61 |
62 | Ассоциативный массив, хранит пары в виде связанного списка (open hash, closed address) или массива пар (closed hash, open address). Индекс элемента равен хеш-функции от ключа i = hash(key). Разбиение множества на подмножества происходит с помощью хеш функции (пример: телефонная книга).
63 |
64 |
65 |
66 |
67 | ## Множество
68 | _set_
69 |
70 | A set is an abstract data structure that can store certain values, without any particular order, and no repeated values. It is a computer implementation of the mathematical concept of a finite set. Unlike most other collection types, rather than retrieving a specific element from a set, one typically tests a value for membership in a set. Some set data structures are designed for static or frozen sets that do not change after they are constructed. Static sets allow only query operations on their elements — such as checking whether a given value is in the set, or enumerating the values in some arbitrary order. Other variants, called dynamic or mutable sets, allow also the insertion and deletion of elements from the set.
71 |
72 |
73 | ## Список
74 | _list_
75 |
76 | Простейшая динамическая структура, упорядоченное множество с переменным числом элементов.
77 |
78 |
79 | ### Связный список
80 | _linked list_
81 |
82 |
83 |
84 |
85 | ### Двусвязный список
86 | _doubly linked list_
87 |
88 |
89 |
90 |
91 | ### Кольцевой список
92 | _circular Linked list_
93 |
94 |
95 |
96 | Плюсы
97 | * Движение в обе стороны
98 | * Добавление элемента за `O(1)` время
99 | * Удаление за `O(1)` время
100 |
101 | Минусы
102 | * На указатели тратится дополнительная память
103 | * Поиск только последовательный путем перебора за `O(n)`
104 |
105 | Отличие списка от массива:
106 |
107 | Массив имеет фиксированное время перехода по индексу, но нуждается в монолитном секторе памяти, обладает нефиксированным временем вставки и удаления.
108 | Список более требователен к памяти, дольше переход по индексу, но значительно быстрее вставка и удаление за `O(1)`. В Java и в C++ явно различаются `List` и `Array`, в Objective-C `NSMutableArray` скорее список, чем массив.
109 |
110 |
111 | ## Очередь
112 | _queue_
113 |
114 | Абстрактный тип данных с дисциплиной доступа к элементам «первый пришёл — первый вышел» (FIFO, first-in-first-out). Добавление элемента (принято обозначать словом enqueue — поставить в очередь) возможно лишь в конец очереди, выборка — только из начала очереди (что принято называть словом dequeue — убрать из очереди), при этом выбранный элемент из очереди удаляется.
115 |
116 |
117 | ### Стек
118 | _stack_
119 |
120 | Стек – реализация очереди LIFO (last-in-first-out) и является структурированной областью памяти, в отличие от кучи. Последовательный список с переменной длинной, включение и исключение только из вершины стека. Состоит из последовательности фреймов.
121 | Пример: после вызова метода из стека выделяется запрошенная область памяти – фрейм, который хранит значения объявленных переменных.
122 |
123 | Операции:
124 | * Включение
125 | * Исключение
126 | * Определение размера
127 | * Очистка
128 | * Неразрушающее чтение
129 |
130 | Функция стека – сохранить работу, невыполненную до конца, с возможностью переключения на другую работу.
131 |
132 |
133 |
134 |
135 | ### Дек
136 | _double ended queue, dequeue_
137 |
138 | Очередь с двумя концами, включение и исключение из любого конца (левого или правого).
139 |
140 |
141 |
142 |
143 | ## Куча
144 | _heap_
145 |
146 | Куча как структура данных представляет собой дерево, где родитель A >= ребенка B => A – корень кучи. Max куча, Min куча.
147 |
148 | Операции:
149 | * Найти max или min
150 | * Удалить max или min
151 | * Увеличить ключи или уменьшить
152 | * Добавить
153 | * Слияние
154 |
155 | Куча как область памяти – реализация динамически распределяемой памяти, в которой хранятся все объекты (вызов `alloc` в Objective-C выделяет из кучи требуемую область памяти).
156 |
157 |
158 | ## Граф
159 | _graph_
160 |
161 | Фигура, состоящая из вершин и ребер, соединяющих вершины. Направленный и ненаправленный.
162 |
163 |
164 | ## Дерево
165 | _tree_
166 |
167 | Связаный граф без циклов. Выделена одна вершина – корень. Остальные – сыновья. Если нет ребенка – терминальная вершина
168 |
169 |
170 |
171 |
172 | ### Бинарное дерево поиска
173 | _binary search tree_
174 |
175 | Состоит из узлов (записей) вида `data`, `left`, `right`, где
176 | ```
177 | key[left[x]] < key[x] <= key[right[x]]
178 | ```
179 | Ключ данных родительского узла больше левого сына и нестрого меньше правого.
180 |
181 |
182 | ### Красно-черное дерево
183 | _red-black tree, rb-tree_
184 |
185 |
186 |
187 |
188 |
189 | Одно из самобалансирующихся двоичных деревьев поиска, гарантирующих логарифмический рост высоты дерева от числа узлов и быстро выполняющее основные операции дерева поиска: добавление, удаление и поиск узла. Сбалансированность достигается за счёт введения дополнительного атрибута узла дерева — «цвета». Этот атрибут может принимать одно из двух возможных значений — «чёрный» или «красный».
190 | * Узел либо красный, либо чёрный.
191 | * Корень — чёрный. (В других определениях это правило иногда опускается. Это правило слабо влияет на анализ, так как корень всегда может быть изменен с красного на чёрный, но не обязательно наоборот).
192 | * Все листья (NIL) — черные.
193 | * Оба потомка каждого красного узла — черные.
194 | * Всякий простой путь от данного узла до любого листового узла, являющегося его потомком, содержит одинаковое число черных узлов.
195 |
--------------------------------------------------------------------------------
/Answers/General/OOP/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/General/OOP/.DS_Store
--------------------------------------------------------------------------------
/Answers/General/OOP/Abstract_class_vs_interface.md:
--------------------------------------------------------------------------------
1 | ## Чем `абстрактный` класс отличается от `интерфейса`
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 |
6 | `Абстрактный класс` - это класс, у которого не реализован один или больше методов.
7 |
8 | Для тех кто пришел из мира C++/C#/Java в Swift интерфейсом называют протокол.
9 |
10 | `Протокол` - это абстрактный класс, у которого все методы не реализованы, все публичные и нет переменных класса.
11 |
12 | `Протокол` нужен обычно, когда описывается только интерфейс. Например, один класс хочет дать другому возможность доступа к некоторым своим методам, но не хочет себя "раскрывать". Поэтому он просто реализует протокол.
13 |
14 | `Абстрактный класс` нужен, когда нужно семейство классов, у которых есть много общего. Конечно, можно применить и интерфейс, но тогда нужно будет писать много идентичного кода.
15 |
16 | В некоторых языках (С++) специального ключевого слова для обозначения интерфейсов нет.
17 | Можно считать, что любой протокол - это уже абстрактный класс, но не наоборот.
18 |
19 |
20 |
21 | ### Статьи по теме
22 |
23 | * [Протоколы](http://severe-programmer.com/swift-dokumentaciya/swift-protocols-protokoly/)
24 |
--------------------------------------------------------------------------------
/Answers/General/OOP/Encapsulation.md:
--------------------------------------------------------------------------------
1 | ## Инкапсуляция
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | ```Инкапсуляция (англ. encapsulation)``` это фундаментальная объектно-ориентированная концепция, позволяющая упаковывать данные и поведение в единый компонент с разделением его на обособленные части - интерфейс и реализацию.
6 |
7 | Еще одно описание:
8 | * механизм языка, позволяющий ограничить доступ одних компонентов программы к другим;
9 | * языковая конструкция, позволяющая связать данные с методами, предназначенными для обработки этих данных.
10 |
11 | Говоря бытовым языком: мы скрываем реализацию от пользователя, предоставляя ему интерфейс. Как класс или метод реализован на самом деле - пользователю знать не обязательно. Для этого существуют уровни доступа.
12 |
13 | Swift предлагает четыре различных уровня доступа для объектов вашего кода. Эти уровни доступа относительны исходному файлу, в котором определен объект, и так же они относительны модулю, которому принадлежит исходный файл:
14 |
15 | Открытый доступ и публичный доступ (**open access** и **public access**). Этот уровень доступа позволяет использовать объекты внутри любого исходного файла из определяющего их модуля и так же в любом исходном файле из другого модуля, который импортирует определяющий модуль. Вы обычно используете открытый и публичный доступы, когда указываете общий интерфейс фреймворка.
16 |
17 | Внутренний (**internal access**). Этот уровень доступа позволяет использовать объекты внутри любого исходного файла из их определяющего модуля, но не исходного файла не из этого модуля. Вы обычно указываете внутренний доступ , когда определяете внутреннюю структуру приложения или фреймворка.
18 |
19 | Файл-частный (**file private**). Этот уровень доступа позволяет использовать объект в пределах его исходного файла. Используйте файл-частный уровень доступа для того, чтобы спрятать детали реализации определенной части функциональности, когда эти части функциональности будут используются внутри другого файла.
20 |
21 | Частный (**private**). Этот уровень доступа позволяет использовать сущность только в пределах области ее реализации. Используйте частный доступ для того, чтобы спрятать детали реализации конкретной части функциональности, когда они используются только внутри области объявления.
22 |
23 | Классы, с уровнем доступа **public**, могут наследоваться только в том модуле, в котором они определены.
24 | Члены класса с уровнем доступа public или с более строгим уровнем доступа могут быть переопределены подклассами только в том модуле, в котором они определены.
25 | Открытые классы могут наследоваться внутри модуля, в котором они определены и внутри модуля, который импортирует модуль, в котором они определены.
26 | Открытые члены класса могут переопределяться подклассами внутри модуля, в котором они были определены или внутри модуля, который импортирует модуль, в котором они были определены.
27 |
28 |
29 | ### Статьи по теме
30 |
31 | * [Уровни доступа](http://swiftbook.ru/doc/access-control/access-levels)
--------------------------------------------------------------------------------
/Answers/General/OOP/Polymorphism.md:
--------------------------------------------------------------------------------
1 | ## Полиморфизм
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | Полиморфизм - это один из базовых принципов объектно-ориентированного программирования (ООП). Полиморфизмом называется возможность работать с несколькими типами так, как будто это один и тот же тип и в то же время поведение каждого типа будет уникальным в зависимости от его реализации.
6 |
7 | Звучит достаточно трудно, поэтому попробую привести пример:
8 | ```swift
9 | func a() {
10 | print("First function")
11 | }
12 |
13 | func a (b: String) {
14 | print(b)
15 | }
16 | ```
17 |
18 | Таким образом у нас 2 функции с одним именем, но разница в принимаемых значениях и теперь мы можем вызывать обе функции.
19 | ```swift
20 | a() //First function
21 |
22 | a(b: "Second function") //Second function
23 | ```
24 |
25 | Полиморфизм может быть:
26 | * Статическим
27 | * Динамический
28 | * Параметрический
29 |
30 |
31 | ### Статьи по теме
32 |
33 | * [Полиморфизм для начинающих](https://habrahabr.ru/post/37576/)
34 | * [Пример полиморфизма на Java](http://java-course.ru/begin/polymorphism/)
35 |
--------------------------------------------------------------------------------
/Answers/General/Pattern/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/General/Pattern/.DS_Store
--------------------------------------------------------------------------------
/Answers/General/Pattern/Little_bit_about_patterns.md:
--------------------------------------------------------------------------------
1 | ## Какие еще `паттерны` знаете?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | * Паттерны порождающие, создания объектов (Creational):
6 | * [Singleton (Одиночка)](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/General/Pattern/Singleton.md)
7 | * Abstarct Factory (Абстрактная фабрика)
8 | * Abstract method (Абстрактный метод)
9 | * Паттерны структурные (Structural):
10 | * [MVC](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/General/Pattern/Singleton.md)
11 | * Decorator (Декоратор)
12 | * Adapter/Bridge (Адаптер/Мост)
13 | * Facade (Фасад)
14 | * Composite (Компоновщик)
15 | * Патерны поведения и взаимодействия объектов (Behavioral):
16 | * Observer: Notification, KVO (Наблюдатель: нотификация, Наблюдение свойствами)
17 | * Memento(Archiving+UserDefaults)
18 | * Command(Target-Action mechanism) (Команда)
19 | * Template method (Шаблонный метод)
20 | * Strategy/State (Стратегия/Состояние)
21 |
--------------------------------------------------------------------------------
/Answers/General/Pattern/MVC_active_vs_passive.md:
--------------------------------------------------------------------------------
1 | ## Расскажите о `паттерне MVC`. Чем отличается `пассивная` модель от `активной`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | `Model-view-controller` (`MVC`, «модель-представление-контроллер», «модель-вид-контроллер») — схема использования нескольких шаблонов проектирования, с помощью которых модель приложения, пользовательский интерфейс и взаимодействие с пользователем разделены на три отдельных компонента таким образом, чтобы модификация одного из компонентов оказывала минимальное воздействие на остальные.
6 |
7 | 1. Модель - данные
8 | 2. Представление - то, что видит пользователь (TextField и т.п.)
9 | 3. Контроллер связывает между собой 2 предыдущих (если пользователь вводит какую-то информацию и передает куда-либо, то контроллер берет эти данные и отправляет в модель.
10 |
11 | Приложение может быть без модели, но всегда должно содержать представление и контроллер (это связка и есть ViewController)
12 |
13 | Оценим его с точки зрения признаков хорошей архитектуры, определенных в начале статьи:
14 | распределение:
15 | * View и Model на самом деле разделены, но View и Controller тесно связаны;
16 | * Тестируемость: из-за плохого распределения вы, вероятно, будете тестировать только Model;
17 | * Простота использования: наименьшее количество кода среди других паттернов. К тому же он выглядит понятным, поэтому его легко может поддерживать даже неопытный разработчик.
18 |
19 |
20 | Две основные модификации:
21 |
22 | * Пассивная модель — модель не имеет никаких способов воздействовать на представление или контроллер, и используется ими в качестве источника данных для отображения. Все изменения модели отслеживаются контроллером и он же отвечает за перерисовку представления, если это необходимо. Такая модель чаще используется в структурном программировании, так как в этом случае модель представляет просто структуру данных, без методов их обрабатывающих;
23 | * Активная модель — модель оповещает о произошедших в ней изменениях т.е. представления, которые подписались на получение таких оповещений. Это позволяет сохранить независимость модели от контроллеров и представлений.
24 |
25 |
26 | ### Статьи по теме
27 |
28 | * [Архитектурные паттерны в iOS](https://habrahabr.ru/company/badoo/blog/281162/)
--------------------------------------------------------------------------------
/Answers/General/Pattern/Singleton.md:
--------------------------------------------------------------------------------
1 | ## Паттерн Singleton?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 |
6 | Основная задача синглтона — предоставить пользователю один и только один объект определенного класса на весь жизненный цикл приложения. В iOS-разработке, как по мне — самый лучший пример необходимости такого объекта — класс UIApplication. Вполне логично, что в течение жизни нашего приложения у нас должен быть один-единственный объект класса UIApplication.
7 |
8 | Очень подробно и достаточно понятно описал этот паттерн автор одной из статей на habrahabr
9 |
10 | ### Статьи по теме
11 |
12 | * [Синглтон-Одиночка](https://habrahabr.ru/post/320728/)
--------------------------------------------------------------------------------
/Answers/General/Pattern/Singleton_arc_non_arc.md:
--------------------------------------------------------------------------------
1 | ## Реализация синглтона в ARC и в non-ARC?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | **ARC**
6 | ```objective-c
7 | + (CustomClass *)shared
8 | {
9 | static CustomClass *singleton = nil;
10 | static dispatch_once_t onceToken;
11 | dispatch_once(&onceToken, ^{
12 | singleton = [[CustomClass alloc] init];
13 | });
14 | return singleton;
15 | }
16 | ```
17 |
18 | **NON-ARC**
19 |
20 | `AppTools.h`
21 | ```Objective-C
22 | @interface AppTools : NSObject {
23 |
24 | NSString *className;
25 | }
26 |
27 | @property ( nonatomic, retain ) NSString *className;
28 |
29 | + ( id ) sharedInstance;
30 |
31 | @end // AppTools
32 | ```
33 |
34 |
35 | `AppTools.m`
36 | ```Objective-c
37 | static AppTools *sharedAppToolsInstance = nil;
38 |
39 | @implementation AppTools
40 |
41 | @synthesize className;
42 |
43 | - ( id ) init {
44 |
45 | self = [ super init ];
46 | if ( self ) {
47 | className = [ [ NSString alloc ] initWithString: @"AppTools" ];
48 | }
49 | return self;
50 | } // init
51 |
52 | - ( void ) dealloc {
53 |
54 | // Should never be called, but just here for clarity really.
55 | [ className release ];
56 | [ super dealloc ];
57 | } // dealloc
58 |
59 | + ( id ) sharedInstance {
60 |
61 | @synchronized( self ) {
62 | if ( sharedAppToolsInstance == nil )
63 | sharedAppToolsInstance = [ [ super allocWithZone: NULL ] init ];
64 | }
65 | return sharedAppToolsInstance;
66 | } // sharedInstance
67 |
68 | + ( id ) allocWithZone: ( NSZone * )zone {
69 |
70 | return [ [ self sharedInstance ] retain ];
71 | } // allocWithZone:
72 |
73 | - ( id ) copyWithZone: ( NSZone * )zone {
74 |
75 | return self;
76 | } // copyWithZone:
77 |
78 | - ( id ) retain {
79 |
80 | return self;
81 | } // retain
82 |
83 | - ( unsigned int ) retainCount {
84 |
85 | return UINT_MAX; // denotes an object that cannot be released
86 | } // retainCount
87 |
88 | - ( oneway void ) release {
89 |
90 | // never release
91 | } // release
92 |
93 | - ( id ) autorelease {
94 |
95 | return self;
96 | } // autorelease
97 | @end
98 | ```
99 |
--------------------------------------------------------------------------------
/Answers/General/SOLID.md:
--------------------------------------------------------------------------------
1 |
2 | ## Что такое `SOLID` принципы?
3 |
4 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
5 |
6 | **S - Single responsibility principle - Принцип единственной обязанности:**
7 |
8 | На каждый класс должна быть возложена одна-единственная обязанность.
9 |
10 | **O - Open/closed principle - Принцип открытости/закрытости:**
11 |
12 | Программные сущности должны быть открыты для расширения, но закрыты для изменения.**
13 |
14 | **L - Liskov substitution principle - Принцип подстановки Барбары Лисков:**
15 |
16 | Функции, которые используют базовый тип, должны иметь возможность использовать подтипы
17 | базового типа, не зная об этом.
18 |
19 | **I - Interface segregation principle - Принцип разделения интерфейса:**
20 | Много специализированных интерфейсов лучше, чем один универсальный.
21 |
22 | **D - Dependency inversion principle - Принцип инверсии зависимостей:**
23 |
24 | Зависимости внутри системы строятся на основе абстракций.
25 | Модули верхнего уровня не зависят от модулей нижнего уровня.
26 | Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
27 |
--------------------------------------------------------------------------------
/Answers/Multithreading/Deadlock.md:
--------------------------------------------------------------------------------
1 | ## Что такое `deadlock`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | `Deadlock` - это тупик. Один поток ждет освобождения второго, а второй ждет освобождения первого. Таким образом происходит зависание приложения.
6 | Пример: в качестве делегата передаем себя как сильную ссылку. А в контроллере делегате пытаемся удалить делегат. В случае с потоками происходит зависание.
7 |
8 | Обратная ситуация - [`livelock`](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/Multithreading/Livelock.md)
9 |
10 |
11 | Хороший пример deadlock привели на хабре
12 |
13 | Допустим в системе существуют две задачи с низким (А) и высоким (Б) приоритетом, которые используют два ресурса — X и Y:
14 |
15 |
16 | 
17 |
18 | В момент времени T1 задача (А) блокирует ресурс X. Затем в момент времени T2 задачу (А) вытесняет более приоритетная задача (Б), которая в момент времени T3 блокирует ресурс Y. Если задача (Б) попытается заблокировать ресурс X (T4) не освободив ресурс Y, то она будет переведена в состояние ожидания, а выполнение задачи (А) будет продолжено. Если в момент времени T5 задача (А) попытается заблокировать ресурс Y, не освободив X, возникнет состояние взаимной блокировки — ни одна из задач (А) и (Б) не сможет получить управление.
19 |
20 |
21 | Как избежать?
22 | Взаимная блокировка возможна только тогда, когда в системе используется зависимый (вложенный) многопоточный доступ к ресурсам. Взаимной блокировки можно избежать, если не использовать вложенность, или если ресурс использует протокол увеличения приоритета.
23 | Если после получения данных из сети в фоновой очереди, попытаемся использовать для возвращения на main queue метод sync, то мы мы получим взаимную блокировку (deadock).
24 |
25 |
26 | **НИКОГДА НЕ вызывайте** метод sync на main queue, потому что это приведет к взаимной блокировке (deadlock) вашего приложения!
27 |
28 | ### Статьи по теме
29 | [Многопоточность](https://habrahabr.ru/post/320152/)
--------------------------------------------------------------------------------
/Answers/Multithreading/Livelock.md:
--------------------------------------------------------------------------------
1 | ## Что такое `livelock`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | Это слово означает такую ситуацию: система не «застревает» (как в обычной взаимной блокировке), а занимается бесполезной работой, её состояние постоянно меняется — но, тем не менее, она «зациклилась», не производит никакой полезной работы.
6 |
7 | Жизненный пример такой ситуации: двое встречаются лицом к лицу. Каждый из них пытается посторониться, но они не расходятся, а несколько секунд сдвигаются в одну и ту же сторону.
8 |
--------------------------------------------------------------------------------
/Answers/Multithreading/Race_condition.md:
--------------------------------------------------------------------------------
1 | ## Что такое `состояние гонки`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | При работе многопоточного кода один поток может зависеть от результатов работы другого. И если мы неправильно запрограммируем код, будет получатся, что
6 | разные потоки выполняются в разное время, и поток зависящий от результатов другого потока будет получать неверные значения.
7 |
8 | На практике будет следующее: программа по непонятным причинам будет возвращать неверный результат. Но при попытке отладить - программа будет возвращать верное решение. Это происходит из-за того, что во время отладки, поток успеет выдать результат. Также ошибка может появится в случае с переходом на новое устройство. В старом был более слабый процессор и приложение работало как надо, а на новом устройстве приложение в одном из 1000 случаев не справляется.
9 |
10 | Вместо того чтобы правильно расставить "барьеры" (в `GCD`) или зависимости операций (`NSOperationQueue`), разработчики начинают в потоке искусственно ставить торможение, чтобы другие потоки успели докачаться либо как-то иначе извращаются.
11 |
12 |
13 | Мы можем воспроизвести простейший случай race condition, если будем изменять переменную value асинхронно на private очереди, а показывать value на текущем потоке:
14 |
15 | ‘’’Swift
16 |
17 | print("--- Имитация race condition ---")
18 | var value = "😇"
19 | func changeValue(variant: Int) {
20 | sleep(1)
21 | value = value + "🐔"; print ("\(value) - \(variant)");
22 | }
23 | //: Запускаем `changeValue()` АСИНХРОННО и показываем `value` на текущем потоке
24 | mySerialQueue.async {
25 | changeValue(variant: 1)
26 | }
27 | value
28 | //: Теперь переустановим `value`, а затем выполним `changeValue()` __СИНХРОННО__, блокируя текущий поток до тех пор, пока задание `changeValue` не закончится, убирая таким образом
29 | race condition:
30 | value = "🦊"
31 | mySerialQueue.sync {
32 | changeValue(variant:2)
33 | }
34 | value
35 | sleep(3)
36 | ‘’’
37 |
38 | У нас есть обычная переменная value и обычная функция changeValue для ее изменения, причем умышленно мы сделали с помощью оператора sleep(1) так, что изменение переменной value требует значительного времени. Если мы будем запускать функцию changeValue АСИНХРОННО с помощью async, то прежде, чем дойдет дело до размещения измененного значения в переменной value, на текущем потоке переменная value может быть переустановлена в другое значение, это и есть race condition.
39 |
40 | Давайте заменим метод async на sync:
41 |
42 | ‘’’Swift
43 | //: Запускаем `changeValue()` СИНХРОННО и показываем `value` на текущем потоке
44 | print("--- Убираем race condition с помощью sync---")
45 | value = "😇"
46 | mySerialQueue.sync {
47 | changeValue(variant: 1)
48 | }
49 | value
50 | //: Теперь переустановим `value`, а затем выполним `changeValue()` __СИНХРОННО__, блокируя текущий поток до тех пор, пока задание `changeValue` не закончится, убирая таким образом
51 | race condition:
52 | value = "🦊"
53 | mySerialQueue.sync {
54 | changeValue(variant:2)
55 | }
56 | value
57 | sleep(2)
58 | ‘’’
59 |
60 | Мы видим, что хотя нужно быть очень внимательным с методом sync для очередей, потому что «текущий поток» вынужден ждать окончания выполнения задания на другой очереди, метод sync оказывается очень полезным для того, чтобы избежать race conditions.
61 |
62 | ### Статьи по теме
63 | [Многопоточность](https://habrahabr.ru/post/320152/)
--------------------------------------------------------------------------------
/Answers/Multithreading/another_thread_technology.md:
--------------------------------------------------------------------------------
1 | ## Какие технологии в iOS возможно использовать для работы с потоками. Преимущества и недостатки.
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | ### NSObject
7 | В iOS и OSx 10.5+ объекты могут порождать потоки и использовать их для вызова одного из их методов
8 | ```objective-c
9 | performSelectorInBackground:withObject: метод создает новый отдельный поток.
10 | [myObj performSelectorInBackground:@selector(doSomething) withObject:nil];
11 | ```
12 | Эффект такой же если бы мы вызвыали метод NSThread с текущим объектом, селектором и параметреами объекта. Новый поток порождает немедленное использование дефолтной конфигурации и начинает выполняться.
13 |
14 | * (-) Не позволяет ограничивать потоки.
15 | * (+) Простота создания
16 |
17 | ### POSIX Thread.
18 | Про них только слышал. Работать не приходилось.
19 | Отличие POSIX Thread от NSThread - в том что в первом случае это библиотека Си, во втором - библиотеки obj-c.
20 |
21 | ##### Ссылки
22 | * [StackOverFlow](http://stackoverflow.com/questions/4358976/nsthread-vs-pthreads)
23 | * [Apple documentation (thread, posix thread etc...)](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html)
24 |
25 |
26 | ### NSThread
27 | Обычный класс obj-c.
28 | [Документация apple: ](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSThread_Class/)
29 |
30 | * (+): Покторное использование кода, требует передачи селектора и объекта, позволяет настраивать некоторые параметры (приоритет и размер стека)
31 | * (-) сложно управлять потоками.
32 |
33 | ### GCD
34 |
35 | Grand Central Dispatch
36 | Обертка над `NSThread`. Делает работу с потоками более удобной.
37 |
38 | ##### Ссылки
39 | * [Туториал по GCD на swift. Часть 1](http://swiftbook.ru/content/tutorials/grand-central-dispatch-part1)
40 | * [Туториал по GCD на swift. Часть 2](http://swiftbook.ru/content/tutorials/grand-central-dispatch-part2)
41 |
42 | В `GCD` можно (и нужно) использовать под разные нужны различные типы очередей.
43 |
44 | #### Типы очередей в GCD
45 |
46 | Во-первых, система представляет вам специальную последовательную очередь - основную очередь (main queue). Как и в любой последовательной очереди, задачи в этой очереди выполняются по одной. Тем не менее, это гарантирует, что все задачи будут выполняться на главном потоке, который является единственным потоком, которому разрешено обновить ваш пользовательский интерфейс. Только эта очередь используется для отправки сообщений на объекты UIView или для размещения уведомлений.
47 |
48 | Система также предоставляет вам несколько согласованных очередей. Эти очереди связаны с их собственным классом QoS (Quality of Service). Классы QoS предназначены, чтобы выразить намерения представленной задачи, так чтобы GCD смог определить, как лучше расставить приоритеты:
49 |
50 | * `QOS_CLASS_USER_INTERACTIVE`: Интерактивный пользовательский класс (user interactive) представляет задачи, которые необходимо сделать немедленно. Используйте его для обновления пользовательского интерфейса, обработки событий или небольших работ, которые должны быть выполнены с небольшими задержками. Общий объем работ, сделанный в этом классе во время выполнения вашего приложения, должен быть небольшим.
51 | * `QOS_CLASS_USER_INITIATED`: Инициированный пользовательский класс представляет задачи, которые инициируются из пользовательского интерфейса и могут быть выполнены асинхронно. Его нужно использовать, когда пользователь ждет немедленных результатов, и для задач, требующих продолжения взаимодействия с пользователем.
52 | * `QOS_CLASS_UTILITY`: Класс Утилит (utility) представляет длительные по исполнению задачи, как правило, с видимым для пользователя индикатором загрузки. Используйте его для вычислений, I/O, при работе с сетями, непрерывных каналов передачи данных и подобных друг другу задач. Этот класс является энергоэффективным, к тому же имеет низкое энергопотребление.
53 | * `QOS_CLASS_BACKGROUND`: Класс background представляет задачи, о которых пользователь может не знать напрямую. Используйте его для предварительной выборки, технического обслуживания и других задач, которые не требуют взаимодействия с пользователем и не требовательны ко времени исполнения.
54 | Помните, что Apple API-интерфейсы также использует глобальные очереди отправки, так что задачи, которые вы добавляете, не будут единственными в этих очередях.
55 |
56 | Наконец, вы можете создать свою собственную последовательную или согласованную очередь. Это означает, что у вас есть по крайней мере пять очередей в вашем распоряжении: главная очередь, четыре глобальные очереди отправки, плюс любые пользовательские очереди, которые вы добавляете сами!
57 |
58 | Вот такая картина вырисовывается об "очередях отправки"!
59 |
60 | "Искусство" в GCD сводится к выбору правильной функции очереди отправки для добавления работы в очередь. Лучший способ научиться - это поэксперементировать в приведенных ниже примерах, где мы представили некоторые общие рекомендации.
61 |
62 |
63 | ### NSOperationQueue
64 | Это обертка над GCD. Apple рекомендует использовать эту технологию по работе с потоками.
65 |
66 | (+)Автоматически создает и управляет потоками, позволяет ограничивать одновременно выполняющиеся потоки
67 | (-)Более сложный механизм. Необходим для управления потоками.
68 |
69 | ### NSOperation
70 | (+)Позволяет переопределять любые аспекты реализации. Может выполнять такие важные действия, как завершение , приостановка и возобновление потока.
71 | (-)Необходим новый класс. Более сложный механизм, поэтому велика вероятность ошибок.
72 |
73 |
74 | ### NSInvocationOperation
75 | (+)Автоматически создает и у правляет потоками. Метод может меняться в зависимости от ввода пользователя за счет создания нового объекта операции вызова.
76 | (-)Трудно специализировать поведение каждого потока.
77 |
--------------------------------------------------------------------------------
/Answers/Multithreading/deadlock_example_1.md:
--------------------------------------------------------------------------------
1 | ## Выведется ли в дебагер «Hello world»? Почему?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | ```Objective-C
6 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
7 | {
8 | dispatch_sync(dispatch_get_main_queue(), ^{
9 | NSLog(@"Hello world");
10 | });
11 |
12 | /* Another implementation */
13 | return YES;
14 | }
15 | ```
16 | Здесь имеет место быть классический deadlock. Чтобы вывести в лог, программа должна быть загружена. И выполнение блока
17 | ждет когда вернется признак YES. В тоже время, признак YES не возвращается, так как ждет выполнение блока.
18 |
--------------------------------------------------------------------------------
/Answers/Multithreading/dispatch_sync_vs_async.md:
--------------------------------------------------------------------------------
1 | ## Чем отличается `dispatch_async от dispatch_sync`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | * `dispatch_async` - асинхронное выполнение кода. Программа недожидается выполнения блока кода и идет дальше.
6 | * `dispatch_sync` - программа дожидается выполнения кода и только потом идет выполненение последующих строчек.
7 |
--------------------------------------------------------------------------------
/Answers/Multithreading/mutex.md:
--------------------------------------------------------------------------------
1 | ## Что такое `мьютекс (mutex)`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | `Мью́текс` (англ. `mutex`, от `mutual exclusion` — «взаимное исключение») — аналог одноместного [`семафора`](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/multithreading/semaphore.md), служащий в программировании для синхронизации одновременно выполняющихся потоков.
6 |
7 | Мьютекс отличается от семафора тем, что только владеющий им поток может его освободить, т.е. перевести в отмеченное состояние. Мьютексы — это один из вариантов семафорных механизмов для организации взаимного исключения. Они реализованы во многих ОС, их основное назначение — организация взаимного исключения для потоков из одного и того же или из разных процессов.
8 |
9 | Мьютексы — это простейшие двоичные семафоры, которые могут находиться в одном из двух состояний — отмеченном или неотмеченном (открыт и закрыт соответственно). Когда какой-либо поток, принадлежащий любому процессу, становится владельцем объекта mutex, последний переводится в неотмеченное состояние. Если задача освобождает мьютекс, его состояние становится отмеченным.
10 |
11 | Задача мьютекса — защита объекта от доступа к нему других потоков, отличных от того, который завладел мьютексом. В каждый конкретный момент только один поток может владеть объектом, защищённым мьютексом. Если другому потоку будет нужен доступ к переменной, защищённой мьютексом, то этот поток засыпает до тех пор, пока мьютекс не будет освобождён.
12 |
13 | Цель использования мьютексов — защита данных от повреждения в результате асинхронных изменений (состояние гонки), однако могут порождаться другие проблемы — такие, как взаимная блокировка (клинч).
14 |
15 | Мьютекс — одна из реализаций спинлока.
16 |
--------------------------------------------------------------------------------
/Answers/Multithreading/semaphore.md:
--------------------------------------------------------------------------------
1 | ## Что такое `семафор (semafor)`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | `Семафо́р` (англ. `semaphore`) — объект, ограничивающий количество потоков, которые могут войти в заданный участок кода.
6 | Определение введено Эдсгером Дейкстрой. Семафоры используются для синхронизации и защиты передачи данных через разделяемую
7 | память, а также для синхронизации работы процессов и потоков.
8 |
9 | Проблемы семафоров:
10 | Во-первых, можно написать программу с «утечкой семафора», вызвав `enter()` и забыв вызвать `leave()`. Реже встречаются
11 | ошибки, когда дважды вызывается `leave()`.
12 |
13 | Во-вторых, семафоры чреваты взаимной блокировкой потоков. В частности, опасен такой код:
14 |
15 | ```objective-c
16 | // Поток 1:
17 | semaphore1.enter();
18 | semaphore2.enter();
19 | // ...
20 | semaphore2.leave();
21 | semaphore1.leave();
22 |
23 | // Поток 2:
24 | semaphore2.enter();
25 | semaphore1.enter();
26 | // ...
27 | semaphore1.leave();
28 | semaphore2.leave();
29 | ```
30 |
--------------------------------------------------------------------------------
/Answers/Networking/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/Networking/.DS_Store
--------------------------------------------------------------------------------
/Answers/UIKit/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/UIKit/.DS_Store
--------------------------------------------------------------------------------
/Answers/UIKit/App_lifecycle.md:
--------------------------------------------------------------------------------
1 | ## Цикл жизни ios-приложения. Какие бывают `состояния` у приложения?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | Сначала приложение не запущенно. Потом пользователь запускает приложение. Оно переходит в состояние Foreground, в котором приложение становится сначала Inactive — на этом этапе выполняется код программы, но не обрабатываются события интерфейса пользователя (интерфейс не отображается, касания не обрабатываются и.т.п.). Затем переходит в этап Active, в котором выполняется код и обрабатываются все события UI.
6 | Если пользователь запустит другое приложение, то текущее приложение перейдет в состояние Inactive и затем в состояние Background. В этом состоянии коды выполняется ограниченное время, и не обрабатываются события UI. Нужно понимать, что именно в этом состоянии можно заставить приложения получить, допустим, из интернета самые свежие обновления чего либо, и дать их приложению, что бы когда пользователь вернул приложение в Foreground он мог увидеть эту информацию.
7 | После весьма короткого состояния Background приложение переходит в состояние Suspended. В этом состоянии код не выполняется вовсе и система может убить приложение для освобождения памяти, если оно потребуется.
8 |
9 | P.S. Ниже вы можете прочитать подробную информацию по жизненному циклу iOS-приложений на английском языке взятой с официальной документации Apple.
10 |
11 | 
12 |
13 | |State | Description|
14 | |-----------|------------|
15 | |Not running|The app has not been launched or was running but was terminated by the system.|
16 | |Inactive| The app is running in the foreground but is currently not receiving events. (It may be executing other code though.) An app usually stays in this state only briefly as it transitions to a different state.|
17 | |Active|The app is running in the foreground and is receiving events. This is the normal mode for foreground apps.|
18 | |Background|The app is in the background and executing code. Most apps enter this state briefly on their way to being suspended. However, an app that requests extra execution time may remain in this state for a period of time. In addition, an app being launched directly into the background enters this state instead of the inactive state. For information about how to execute code while in the background, see Background Execution.|
19 | |Suspended| The app is in the background but is not executing code. The system moves apps to this state automatically and does not notify them before doing so. While suspended, an app remains in memory but does not execute any code. When a low-memory condition occurs, the system may purge suspended apps without notice to make more space for the foreground app.|
20 |
21 |
22 | 
23 |
24 |
25 | ### Статьи по теме
26 | [Описание в документации apple](https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html)
27 |
28 | [Описание на русском](http://proswift.ru/ios-application-lifecycle-ili-zhiznennyj-cikl-ios-prilozheniya/)
29 |
--------------------------------------------------------------------------------
/Answers/UIKit/Frame_vs_Bounds.md:
--------------------------------------------------------------------------------
1 | ## Разница между свойствами bounds и frame объекта UIView? Понимание системы координат?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | Frame – это прямоугольник описываемый положением location(x, y) и размерами size (width, height) view относительно ее superview в которой она содержится.
6 |
7 | Bounds – это прямоугольник описываемый положением location(x, y) и размерами size (width, height) view относительно ее собственной системы координат (0, 0).
8 |
9 |
10 | ### Статьи по теме
11 |
12 | * [UIView — UIView.frame и UIView.bounds](http://proswift.ru/poleznye-svojstva-cgrect-a-takzhe-svojstva-uiview-frame-i-bounds/)
13 | * [Понимание системы координат](http://spec-zone.ru/RU/XCode/documentation/General/Conceptual/Devpedia-CocoaApp/CoordinateSystem.html)
--------------------------------------------------------------------------------
/Answers/UIKit/How_to_work_with_push_notification.md:
--------------------------------------------------------------------------------
1 | ## Как работают `push нотификации`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | 1. Apple Push Notification Service (APNS) запрашивает у устройства token, своеобразный ключ, который можно считать "адресом".
6 | 2. Есть сервер (наш или иной сервис):
7 | 3. Приложение отправляет token на сервер, коткорый занимается отправкой push-уведомлений.
8 | 4. Когда произойдёт какое-либо событие для вашего приложения, сервер отправит push-уведомление в APNS.
9 | 5. APNS отправит push-уведомление на девайс пользователя.
10 |
11 | Для разработки push-нотификаций, надо учитывать:
12 |
13 | 1. iPhone, iPad или iPod touch. Push-уведомления не работают в симуляторе, поэтому для тестирования нужен девайс.
14 | 2. Регистрация в iOS Developer Program. Для каждого приложения, в котором будет интегрирован механизм push-уведомлений, необходимо создать новый App ID и provisioning profile, а также SSL-сертификат для сервера. Эти действия выполняются на iOS Provisioning Portal.
15 | 3. Необходимо создать provisioning profile и SSL-сертификат.
16 | 4. Сервер, подключенный к интернету. Push-уведомления всегда отправляются сервером.
17 |
18 |
19 | Push-уведомление — это короткое сообщение, состоящее из токена девайса, полезной нагрузки (payload) и ещё некоторой информации. Полезная нагрузка — это актуальные данные, которые будут отправляться на девайс.
20 |
21 |
22 | Push-уведомления — это нечто довольно маленькое; размер полезной нагрузки не может превышать 256 байт. Это примерно столько же, сколько позволяет вместить в себя СМС или твит. Push-сервер не будет тратиться на переносы на новую строку и пробелы.
23 |
24 |
25 | Понимание push-уведомлений
26 |
27 | 1. Они не надёжны! Нет гарантий, что push-уведомления будут доставлены, даже если APNS примет их.
28 | 2. Как только ваш сервер сформировал push-уведомление, он безответно отправляет его в APNS. Нет способа узнать статус доставки уведомления конечному пользователю после отправки. Время доставки может варьироваться от нескольких секунд до получаса.
29 | 3. Кроме этого, у пользователей i-девайсов может не быть возможности получать push-уведомления всё время. Например, рядом нет Wi-Fi сети с доступом в интернет либо девайс может быть вообще выключен.
30 | 4. APNS будет пытаться доставить последнее отправленное уведомление, когда девайс станет доступен для приёма. Но эти попытки ограничены по времени. После тайм-аута push-уведомление будет потеряно навсегда!
31 | 5. Они могут быть дорогими! Добавить push-функционал в приложение довольно просто и недорого, если вы владеете данными. Однако если у вас много пользователей либо необходимо запрашивать данные, то затраты резко возрастают.
32 |
--------------------------------------------------------------------------------
/Answers/UIKit/IBOutlet_vs_IBAction.md:
--------------------------------------------------------------------------------
1 | ## Что означают IBOutlet и IBAction, для чего они нужны, и что значат для препроцессора?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | Ключевое слово IBOutlet предназначено для связи элемента интерфейса на форме созданным дизайнером форм и кодом.
6 |
7 | Ключевое слово IBAction предназначено для сообщения Interface Builder’у, что этот метод будет вызван из интерфейса.
--------------------------------------------------------------------------------
/Answers/UIKit/Multithreading_with_UI/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/UIKit/Multithreading_with_UI/.DS_Store
--------------------------------------------------------------------------------
/Answers/UIKit/Multithreading_with_UI/Async.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/UIKit/Multithreading_with_UI/Async.png
--------------------------------------------------------------------------------
/Answers/UIKit/Multithreading_with_UI/Multithreading_with_UI.md:
--------------------------------------------------------------------------------
1 | ## Как многопоточность работает с UIKit?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | Apple обеспечивает нас единственной ГЛОБАЛЬНОЙ serial (ПОСЛЕДОВАТЕЛЬНОЙ) очередью — это упомянутая выше Main queue. На этой очереди нежелательно выполнять ресурс-емкие операции (например, загрузку данных из сети), не относящиеся с изменению UI, чтобы не «замораживать» UI на время выполнения этой операции и сохранить отзывчивость пользовательского интерфейса на действия пользователя в любой момент времени, например, на жесты.
6 |
7 | 
8 | Настоятельно рекомендуется «уводить» такие ресурс-емкие операции на другие потоки или очереди:
9 | 
10 | Есть и еще одно жесткое требование — ТОЛЬКО на Main queue мы можем изменять UI элементы.
11 |
12 | Это потому, что мы хотим, чтобы Main queue была не только “отзывчивой” на действия с UI (да, это основная причина), но мы хотим также, чтобы пользовательский интерфейс был защищен от “разлаживания” в многопоточной среде, то есть реакция на действия пользователя выполнялась бы строго последовательно в упорядоченной манере. Если мы разрешим нашим элементам UI выполнять свои действия в различных очередях, то может случиться, что рисование будет происходить с разной скоростью, и действия будет пересекаться, что приведет к полной непредсказуемости на экране. Мы используем Main queue как своего рода “точку синхронизации”, в которую возвращается каждый, кто хочет “рисовать” на экране.
--------------------------------------------------------------------------------
/Answers/UIKit/Multithreading_with_UI/Sync.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoBug92/iOS_Guide/a6ee6ad5a1d2b05a53a18ac5813fee3006467bcb/Answers/UIKit/Multithreading_with_UI/Sync.png
--------------------------------------------------------------------------------
/Answers/UIKit/Responder_chain.md:
--------------------------------------------------------------------------------
1 | ## Что такое responder chain?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 |
6 |
7 | **Иерархия компонентов**
8 | * Основой иерархии UI-компонентов iOS приложения является объект UIWindow.
9 | * UIWindow создается при запуске приложения. Далее, все UI-компоненты добавляются как дочерние на UIWindow.
10 | * Обычно, приложение содержит только один объект типа UIWindow.
11 |
12 |
13 | **UIWindow занимается следующим:**
* Отображает ваш контент
* Сообщает своим под-компонентам о событиях взаимодействия пользователя с UI
14 | * Сообщает контроллерам о поворотах устройства
15 |
16 | **Обработка touch-событий**
17 | Для обработки взаимодействия пользователя с UI и внешних событий в iOS используется механизм Responder Chain.
18 |
**Для touch-событий:**
* UIWindow пытается передать touch в объект типа UIView, в котором он был вызван (hit-testing).
* Если UIView не может обработать данный touch (например, объект в данный момент невидим, либо отключил возможность взаимодействия с собой), touch передается в superview данного компонента, и так далее вверх, пока он не будет обработан.
19 |
20 | **Responder chain**
Классы UIApplication, UIViewController и UIView наследуются от класса UIResponder.
* UIResponder определяет порядок, в котором объекты обрабатывают события (touch-события, события от элементов UI (кнопки, слайдеры), изменение текста)
* UIResponder объявляет методы, которые позволяют объектам определять, кто первым будет отвечать и обрабатывать сообщения:
* becomeFirstResponder — объект-получатель сообщения будет первым получать все события, посылаемые системой.
* resignFirstResponder — объект-получатель отказывается от обработки сообщений первым.
21 |
22 | 
23 |
24 |
25 | **UIControl: Target-action**
26 | Для обработки стандартных действий пользователя с UI (нажатие кнопки, изменение значения слайдера и тд) в UIKit / AppKit используется механизм target-action.
* UI-компоненты, которые могут посылать сообщения, наследуются от UIControl — класс-наследник UIView, конкретизирующий обработку действий пользователя и выполнения связанных с ними действий.
* Так же позволяют задать внешний вид компонента при определенном состоянии (выбран, нажат)
27 |
28 | ```swift
29 | //допустим, мы создаем кнопку в методе viewDidLoad UIButton* button = [UIButton new];
30 |
[button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchDown];
31 |
....
32 |
- (void) buttonPressed:(id) sender {
33 |
}
34 |
35 | ```
36 |
37 | ### Статьи по теме
38 |
39 | * [Лекция от Sibers](http://www.sibers.ru/wp-content/uploads/sibers-iOS-Lectures-5.pdf)
40 | * [Habrahabr](https://habrahabr.ru/post/276799/)
--------------------------------------------------------------------------------
/Answers/UIKit/Size_of_iPhone_and_different_between_points_and_pixels.md:
--------------------------------------------------------------------------------
1 | ## Какого разрешение экранов iphon'ов, и в чем разница между points (точками) и пикселями (pixels)?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 |
6 | 
7 |
8 | DPI или (Dots Per Inch) «точек на дюйм» является мерой пространственной плотности точек, первоначально использовавшейся в печати. Это количество капель чернил, которое ваш принтер может вместить в один дюйм. Меньшее DPI дает менее детальное изображение.
9 |
10 | Эта концепция применяется к компьютерным экранам под названием PPI (пикселей на дюйм). Тот же принцип: подсчитывается количество пикселей, которые экран может отображать на дюйм. Название DPI также используется в экранах.
11 |
12 | Вот прикладной пример: экран Mac Cinema 27 дюймов имеет 109 PPI, что означает, что он отображает 109 пикселей на дюйм экрана. Ширина с рамкой является 25,7 дюймов (65 см). Ширина фактического экрана составляет примерно 23,5 дюйма, так 23,5 * 109 ~ 2560, что делает физическое разрешение экрана 2560x1440px. *Я знаю, что 23,5 * 109 не равно точно 2560. Это на самом деле +23,486238532 дюймов. Было бы точнее пикселей на сантиметр, но вы меня поняли.
13 |
14 |
15 | ### Статьи по теме
16 |
17 | * [Разрешение экранов](http://appleinsider.ru/developer/pamyatka-razrabotchiku-i-dizajneru-ios-prilozhenij.html)
18 | * [Подробнее о пикселях и точках](https://habrahabr.ru/post/237931/)
--------------------------------------------------------------------------------
/Answers/UIKit/UIViewController_lifecycle.md:
--------------------------------------------------------------------------------
1 | ## Цикл жизни UIViewController.
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 |
6 |
7 | Жизненный цикл контроллера начинает с создания. В 99% случаях создание происходит в storyboard, и «за сценой» происходит инициализация, а потом:
8 | 1. Подготовка к переходу в контроллер:
Другой контроллер приготавливается к переходу в наш. При этой подготовке outlet свойства еще не установлены. К ним обращаться нельзя!
9 |
10 | ```swift
11 |
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
12 |
13 | ```
14 |
15 | 2. Установка outlet свойств
16 |
17 | ```swift
18 |
@IBOutlet weak var pannableView: UIView {
19 |
}
20 |
21 | ```
22 |
23 | 3. Появление на экране и уход с экрана
Это самое отличное место чтобы выполнить большинство установок для контроллера. Посудите сами — в подготовке все нужные данные переданы, свойства установлены — самое время что-то настроить.
24 |
25 | ```swift
26 |
override func viewDidLoad() {
27 |
super.viewDidLoad() // всегда вызываем метод жизненного цикла у суперкласса
28 |
// настраиваем наш MVC
29 |
}
30 |
31 | ```
Далее появления на экране: прямо перед появлением view на экране мы получаем уведомление вызовом
32 |
33 | ```swift
34 |
override func viewWillAppear(animated: Bool) {
35 |
super.viewWillAppear(animated)
36 |
}
37 |
38 | ```
Далее, сразу после появления view на экране вызывается метод
39 |
40 | ```swift
41 | override func viewDidAppear(animated: Bool) {
42 | super.viewDidAppear(animated)
43 | }
44 |
45 | ```
Если view ушло с экрана вызываются методы
46 |
47 | ```swift
48 | override func viewWillDisappear(animated: Bool) {
49 | super.viewWillDisappear(animated)
50 | }
51 | override func viewDidDisappear(animated: Bool) {
52 | super.viewDidDisappear(animated)
53 | }
54 |
55 | ```
56 |
57 | 4. Изменение геометрии (поворот, изменение границ)
Система знает когда поменялись границы нашего view. И она вызывает методы
58 |
59 | ```swift
60 | super.viewWillLayoutSubviews()
61 | }
62 | // Autolayout происходит тут - между двумя этими методами
63 | override func viewDidLayoutSubviews() {
64 | super.viewDidLayoutSubviews()
65 | }
66 |
67 | ```
68 | Нужно понимать, что это не функция ВьюВКонтроллереИзменилаГраницы(). Расположение всех элементов пользовательского интерфейса задаются параметрами Autolayout , и эти два метода вызываются чтобы убедится, что расстановка выполнена правильно (до начала расстановки и сразу после нее)
Обработка поворота экрана обрабатывается автоматически, и задается в настройках приложения. Однако если нужно самостоятельно обработать анимацию при повороте, то можно использовать следующий метод, который также является частью жизненного цикла ViewController:
69 |
70 | ```swift
71 | func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator:
72 |
73 | UIViewControllerTransitionCoordinator)
74 |
75 | ```
76 |
77 | 5. Ситуация с недостатком памяти устройства
Ну и в очень редких случаях система может послать сообщение о нехватке памяти
78 |
79 | ```swift
80 | override func didReceiveMemoryWarning()
81 |
82 | ```
83 | Тут можно попробовать обнулить объекты, которые не используются.
84 |
85 |
--------------------------------------------------------------------------------
/Answers/UIKit/Use_UITableView.md:
--------------------------------------------------------------------------------
1 | ## Как работает UITableView?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/CoBug92/Interview_iOS/blob/master/README.md)
4 |
5 | Таблица имеет три основных составляющие: саму таблицу, разделы таблицы (или группировки) и ячейки таблицы (отдельные строки в таблице). Данные в таблицы помещаются в очередь из источника данных таблицы. Источник данных - это объект, предоставляющий таблице информацию о том, какие данные отображать, например, имена файлов, сообщения электронной почты и т. д. Для облегчения понимания работы с таблицей возьмем обычный массив, в который будут включены только строки.
6 |
7 | При работе с таблицами есть несколько обязательных функций:
8 |
9 |
10 | К примеру у нас есть массив restaurant: [String] = [«Barrafina», «Cafe Deadend», «Confessional»]
11 |
12 | 1. В первую очередь, следует указать сколько секций будет в нашей таблице. Делается это с помощью метода numberOfSectionsInTableView. Так как я изначально хочу чтобы была только 1 секция содержащая название ресторанов, то я так и указываю.
13 |
14 | ```swift
15 |
16 | override func numberOfSections(in tableView: UITableView) -> Int {
17 |
18 | return 1 //Count of sections in TableView
19 |
20 | }
21 | ```
22 |
23 | 2. Чтобы "сказать" нашей таблице сколько в ней будет строк (а их будет столько же, сколько и элементов в источнике данных) используйте метод numberOfRowsInSection
24 |
25 | Встроенной функцией подсчитываю кол-во элементов в массиве restaurant.
26 |
27 | ```swift
28 |
29 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
30 |
31 | return restaurants.count
32 |
33 | }
34 | ```
35 |
36 | 3. Теперь нам нужно заполнить ячейки нашей таблицы. Для заполнения воспользуйтесь методом cellForRowAtIndexPath. Он предоставляет нам “indexPath” (тип “NSIndexPath“). С помощью данного значения мы сможем выяснить текущий номер строки, чтобы заполнить ее элементом источника с таким же индексом. В самом методе cellForRowAtIndexPath уже имеется код, отвечающий за поиск и создание ячейки.
37 |
38 | Присваиваем лейблу в ячейке значение элемента массива с индексом indexPath
39 |
40 | ```swift
41 |
42 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
43 |
44 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
45 |
46 | //Configurate the cell:
47 |
48 | cell.nameLabel.text = restaurant.name
49 |
50 | return cell
51 |
52 | }
53 | ```
54 |
--------------------------------------------------------------------------------
/Answers/code_puzzles/GCD_example_1.md:
--------------------------------------------------------------------------------
1 | ## Что выведется в консоль?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | ```Objective-C
7 | dispatch_async(dispatch_get_main_queue(), ^
8 | {
9 | NSLog(@"A %d", [object retainCount]);
10 | dispatch_async(dispatch_get_main_queue(), ^
11 | {
12 | NSLog(@"B %d", [object retainCount]);
13 | });
14 | NSLog(@"C %d", [object retainCount]);
15 | });
16 | NSLog(@"D %d", [object retainCount]);
17 | ```
18 |
19 | В коде надо добавить хотя бы это:
20 | ```Objective-C
21 | NSObject *object = [NSObject new]
22 | ```
23 | Иначе проект не скомпилируется. После добавления в лог выведется следующее:
24 | ```
25 | >> D 2
26 | >> A 2
27 | >> C 3
28 | >> B 2
29 | ```
30 |
--------------------------------------------------------------------------------
/Answers/code_puzzles/code_puzzles_1.md:
--------------------------------------------------------------------------------
1 | ## Что произойдет при исполнении следующего кода?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | ```Objective-C
6 | Ball *ball = [[[[Ball alloc] init] autorelease] autorelease];
7 | ```
8 |
9 | Код скомпилируется. Но в будущем может упасть. Так как `release` в конце `Eventloop` будет послан уже удаленному объекту.
10 |
11 | |№|Код|Описание|
12 | |---|---|---|
13 | |1| [Ball alloc]| Создаем объект `Ball` и в последствии он должен быть уничтожен.|
14 | |2|[Ball alloc] init]| Инициализируем объект.|
15 | |3|[[[Ball alloc] init] autorelease]| Добавляем объект в текущий `autorelease pool`,таким образом память будет освобождена когда `pool` будет очищаться.|
16 | |4|[[[[Ball alloc] init] autorelease] autorelease]|Снова добавляем `Ball` в autorelease pool. На 100% неправильно! Код скомпилируется, запуститься. Но в определенный момент приложение "упадет".|
17 |
--------------------------------------------------------------------------------
/Answers/code_puzzles/code_puzzles_2.md:
--------------------------------------------------------------------------------
1 | ## Что не так с этим кодом? Зачем нужны `инициализаторы`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | ```objective-c
6 | [[[SomeClass alloc] init] init];
7 | ```
8 |
9 | `Retain count` не увеличится. В лучшем случае, произойдет учетчка объекта созданного первым init.
10 | В худшем - учетчка памяти может привести к падению приложения.
11 |
12 | Если необходимо вызвать конструктор с другими параметрами, то проще создать еще один объект.
13 |
--------------------------------------------------------------------------------
/Answers/code_puzzles/method_classA_and_classB.md:
--------------------------------------------------------------------------------
1 | ## Какой метод вызовется: класса A или класса B? Как надо изменить код, чтобы вызвался метод класса A?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | ```objective-c
7 | @interface A : NSObject
8 | - (void)someMethod;
9 | @end
10 |
11 | @implementation A
12 | - (void)someMethod
13 | {
14 | NSLog(@"This is class A");
15 | }
16 | @end
17 |
18 | @interface B : A
19 | @end
20 |
21 | @implementation B
22 | - (void)someMethod
23 | {
24 | NSLog(@"This is class B");
25 | }
26 | @end
27 |
28 | @interface C : NSObject
29 | @end
30 |
31 | @implementation C
32 | - (void)method
33 | {
34 | A *a = [B new];
35 | [a someMethod];
36 | }
37 | ```
38 |
39 | Вызовется метод `класса B`.
40 | Чтобы вызвался метод `класса А` надо изменить код одним из двух способов:
41 |
42 | I способ:
43 | Создаем объект класса А.
44 |
45 | ```objective-c
46 | @implementation C
47 | - (void)method
48 | {
49 | A *a = [B new];
50 | [a someMethod];
51 | }
52 | ```
53 |
54 | II способ:
55 | В имплементации класс B вызываем метод его супер-класса
56 |
57 | ```objective-c
58 | @implementation B
59 | - (void)someMethod
60 | {
61 | [super someMethod];
62 | }
63 | @end
64 | ```
65 |
--------------------------------------------------------------------------------
/Answers/coredata/coredata.md:
--------------------------------------------------------------------------------
1 | ## Что такое `Core Data`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | Фреймворк разрааботанный apple для работы с данными. Большинство деталей по работе с хранилищем данных Core Data скрывает, позволяя вам сконцентрироваться на том, что действительно делает ваше приложение веселым, уникальным и удобным в использовании.
7 |
8 | 1. `NSPersistentStore`, которым может выступать бинарный файл, `XML`, `SQLite` файл.
9 | 2. `NSManagedObjectModel`, которая является скомпилированной бинарной версией модели данных.
10 | 3. `NSPersistentStoreCoordinator`, занимается загрузкой данных из `NSPersistentStore` и `NSManagedObjectModel`, сохранением и кешированием.
11 | 4. `NSManagedObjectContext`, загрузка данных из `NSPersistentStore` в память, операции с экземплярами.
12 | 5. `NSManagedObject` — объект модели данных.
13 |
14 |
15 | Не смотря на то, что Core Data может хранить данные в реляционной базе данных вроде SQLite, Core Data не является СУБД. По-правде Core Data в качестве хранилища может вообще не использовать реляционные базы данных. Core Data не является чем-то вроде Hibernate, хотя и предоставляет некоторые возможности ORM. Core Data скорее является оболочкой/фрэймворком для работы с данными, которая позволяет работать с сущностями и их связями (отношениями к другим объектами), атрибутами, в том виде, который напоминает работы с объектным графом в обычном объектно-ориентированном программировании.
16 |
17 | Core Data был внедрён лишь начиная с Mac OS X 10.4 Tiger и iPhone SDK 3.0
18 |
19 | Объекты, которые находятся под управлением фрэймворка (Core Data) должны наследовать методы/свойства класса NSManagedObject.
20 |
21 | Так же, как и людям, объектам нужна среда в которой они могут существовать, такая среда есть и, называется она managed object context (среда управляемых объектов) или просто context. Среда, в которой находится объект, следит не только за тем, в каком состоянии находится объект с которым вы работаете, но и за состояниями связанных объектов (объектов, которые зависимы от данного и от которых зависим он сам).
22 | Экземпляр класса `NSManagedObjectContext` предоставляет ту самую среду для объектов, объект данного типа должен быть доступен в вашем приложении всегда. Обычно экземпляр класса `NSManagedObjectContext` является свойством делегата вашего приложения. Без среды, без экземпляра класса `NSManagedObjectContext` вам просто не удастся работать с Core Data.
23 |
24 | `NSFetchedResultsController` представляет собой контроллер, предоставляемый фрэймворком Core Data для управления запросами к хранилищу.
25 |
26 | Результаты запроса могут быть отсортированы при помощи `NSSortDescriptor`. `NSSortDescriptor` определяет поле для сортировки и тип сортировки (по возрастанию или убыванию).
27 |
--------------------------------------------------------------------------------
/Answers/coredata/coredata_vs_threads.md:
--------------------------------------------------------------------------------
1 | ## Какие есть нюансы при использовании `Core Data в разных потоках`? Как `синхронизировать данные между потоками`(Как синхронизировать контекст)? Синхронизация разных типов NSManagedObjectContext (получение и изменение данных в child контекстах)?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | #### Надо перечитать и переработать
7 |
8 |
9 | `NSManagedObjectContext` не потокозащищенный:
10 |
11 | В iOS 6.0 появились типы `NSManagedObjectContext`:
12 | 1. `NSMainQueueConcurrencyType` – доступен исключительно с главного потока.
13 | 2. `NSPrivateQueueConcurrencyType` – работает на фоновом потоке.
14 | 3. `NSConfinementConcurrencyType` – работает на том потоке, на котором создали.
15 |
16 | ```Objective-C
17 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
18 | // Создание NSManagedObjectModel
19 | // Создаем NSPersistentStoreCoordinator
20 | // Добавляем к NSPersistentStoreCoordinator хранилище, именно на этой операции приложение может висеть очень долго
21 |
22 | // Создание контекстов
23 |
24 | Создаем родительский контекст, который будет иметь тип NSPrivateQueueConcurrencyType.
25 |
26 | /*
27 | _daddyManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
28 | [_daddyManagedObjectContext setPersistentStoreCoordinator:psc];
29 | // Далее в главном потоке инициализируем main-thread context, он будет доступен пользователям
30 | dispatch_async(dispatch_get_main_queue(), ^{
31 | _defaultManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
32 | // Добавляем наш приватный контекст отцом, чтобы дочка смогла пушить все изменения
33 | [_defaultManagedObjectContext setParentContext:_daddyManagedObjectContext];
34 | });
35 | */
36 | });
37 | ```
38 |
39 | Дальше создаем `defaultManagedObjectContext` и задаем ему родителя (_daddy...)
40 |
41 | При работе в других потоках задаем в качестве предка defaultManagedObjectContext.
42 |
43 | Сохранение контекстов:
44 |
45 | Осталось самое главное — сохранение. К контекстам, которые живут на бекграунд-потоках обращаться можно только через performBlock: и performBlockAndWait:. Поэтому сохранение бекграунд потока будет выглядеть следующим образом.
46 |
47 | ```Objective-C
48 | - (void)saveContextForBGTask:(NSManagedObjectContext *)bgTaskContext {
49 | if (bgTaskContext.hasChanges) {
50 | [bgTaskContext performBlockAndWait:^{
51 | NSError *error = nil;
52 | [backgroundTaskContext save:&error];
53 | }];
54 | // Save default context
55 | }
56 | }
57 | ```
58 | После сохранения дочернего контекста необходимо сохранить родительский.
59 |
60 | ```Objective-C
61 | - (void)saveDefaultContext:(BOOL)wait {
62 | if (_defaultManagedObjectContext.hasChanges) {
63 | [_defaultManagedObjectContext performBlockAndWait:^{
64 | NSError *error = nil;
65 | [_defaultManagedObjectContext save:&error];
66 | }];
67 | }
68 |
69 | // А после сохранения _defaultManagedObjectContext необходимо сохранить его родителя, то есть _daddyManagedObjectContext
70 | void (^saveDaddyContext) (void) = ^{
71 | NSError *error = nil;
72 | [_daddyManagedObjectContext save:&error];
73 | };
74 | if ([_daddyManagedObjectContext hasChanges]) {
75 | if (wait)
76 | [_daddyManagedObjectContext performBlockAndWait:saveDaddyContext];
77 | else
78 | [_daddyManagedObjectContext performBlock:saveDaddyContext];
79 | }
80 | }
81 | ```
82 |
83 | А вообще, лучше использовать фреймворк MagicalRecord, в котором реализована работа с потоками.
84 |
--------------------------------------------------------------------------------
/Answers/coredata/nsfetchresultcontroller.md:
--------------------------------------------------------------------------------
1 | ## Использовали ли `NSFetchedResultsController`? Почему?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | ** нет описания **
7 |
--------------------------------------------------------------------------------
/Answers/coredata/sqlite_vs_coredata.md:
--------------------------------------------------------------------------------
1 | ## В каких случаях лучше использовать `SQLite`, а в каких `Core Data`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | #### Недостатки и достоинства SQLite и CoreData:
6 | ##### SQLite:
7 | 1. Занимает меньше памяти
8 | 2. Написание кода более утомительно так как надо знать SQL и писать запросы.
9 |
Так же надо писать классы-материализаторы.
10 |
Что увеличивает вероятность возникновения ошибок.
11 | 3. Поддерживаетстя Android и WindowsPhone.
12 |
13 | ##### CoreData:
14 | 1. Более сложный в изучении.
15 | 2. Намного проще работать с объектами.
16 | 3. Объекты обрабатываются атомарно и существует поддержка iCloud.
17 | 4. Есть функции undo-redo.
18 |
19 | #### Скорость работы разная:
20 | На больших объемах при чтении данных iPhone 4s в разы обгоняет sqlite
21 | При хранении данных, sqlite в несколько раз превосходит coredata.
22 |
--------------------------------------------------------------------------------
/Answers/logical/bridge.md:
--------------------------------------------------------------------------------
1 | ## Задача про мост
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Есть 4 человека, каждый проходит мост за 1, 2, 5, и 10 минут соответственно. Через мост они могут переходить только парами, держась за руку и только с фонариком. Притом один должен вернуться обратно и передать фонарик. Необходимо переправить всех за 17 мин на другую сторону. Задача решаема.
6 |
7 | ### Решение
8 |
9 | |№ |Сторона А|Действие|Сторона Б|Потратили на переход|Суммарное время|
10 | |---|---|---|---|---|---|
11 | |0|1, 2, 5, 10| - | - | - | 0 мин.|
12 | |1|5, 10|1 и 2 переходят мост|1, 2| 2 мин. | 2 мин.|
13 | |2|1, 5, 10|1 возвращается|2|1 мин.|3 мин.|
14 | |3|1|5 и 10 переходят мост| 2, 5, 10| 10 мин.| 13 мин|
15 | |4|1|2 возвращается| 5, 10|2 мин.|15 мин.|
16 | |5|-|1 и 2 переходят мост| 1, 2, 5, 10|2 мин|17 мин.|
17 |
--------------------------------------------------------------------------------
/Answers/memory_managment/arc.md:
--------------------------------------------------------------------------------
1 | ## Что означает `ARC`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Automatic Reference Counting -> Автоматический подсчет ссылок.
6 | Каждый раз когда к объекту создается `сильная ссылка`, счетчик увеличивается. Когда ссылка изчезает (переменной присвоили nil для примера), то счетчик уменьшается.
7 | Как только счетчик становится равным 0, то память очищается.
8 |
--------------------------------------------------------------------------------
/Answers/memory_managment/atomic_vs_nonatomic.md:
--------------------------------------------------------------------------------
1 | ## `Atomic vs nonatomic`. Чем отличаются?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Атрибуты атомарности
6 | ### atomic
7 | Переопределить можно только оба метода (get/set). Для потокобезопасности недостаточно объявить свойство `atomic`.
8 | Методы доступа работают медленней чем `nonatomic`.
9 |
10 | ### nonatomic
11 | Нет разницы какой поток первым получить доступ к акцессору или мутатору.
12 | Поскольку большинство объектов используются в одном потоке, нет смысла нагружать их дополнительным функционалом, которые к тому же увеличит время выполнения.
13 |
14 | ---
15 | ### atomic
16 | это дефолтное значение для данного атрибута. Оно означает, что акцессор и мутатор будут сгенерированы таким образом, что при обращении к ним одновременно из разных потоков, они не будут выполняться одновременно (то есть все равно сперва один поток сделает свое дело — задаст или получит значение, и только после этого другой поток сможет заняться тем же). Из-за особенностей реализации у свойств с таким значением атрибута атомарности нельзя переопределять только один из методов доступа (уж если переопределяете, то переопределяйте оба, и сами заморочьтесь с защитой от одновременного выполнения в разных потоках). Не стоит путать атомарность свойства с потокобезопасностью объекта. К примеру, если вы в одном потоке получаете значение имени и фамилии из свойств объекта, а в другом — изменяете эти же значения, вполне может получиться так, что значение имени вы получите старое, а фамилии — уже измененное. Соответственно, применять стоит для свойств объектов, доступ к которым может осуществляться из многих потоков одновременно, и нужно спастись от получения каких-нибудь невалидных значений, но при необходимости обеспечить полноценную потокобезопасность, одного этого может оказаться недостаточно. Кроме прочего стоит помнить, что методы доступа таких свойств работают медленнее, чем nonatomic, что, конечно, мелочи в масштабах вселенной, но все же копейка рубль бережет, поэтому там, где нет необходимости, лучше использовать nonatomic.
17 |
18 |
19 | ### nonatomic
20 | Значение противоположное atomic — у свойств с таким значением атрибута атомарности методы доступа не обременены защитой от одновременного выполнения в разных потоках, поэтому выполняются быстрее. Это значение пригодно для большинства свойств, так как большинство объектов все-таки используются только в одном потоке, и нет смысла «обвешивать» их лишними фичами. В общем, для всех свойств, для которых не сможете объяснить, почему оно должно быть atomic, используйте nonatomic, и будет вам fast and easy and smart и просто праздник какой-то.
21 |
--------------------------------------------------------------------------------
/Answers/memory_managment/autorelease_pool.md:
--------------------------------------------------------------------------------
1 | ## Что такое autorelease pool?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Это специальный механизм, который позволяет посылать отложенное сообщение об освобождении объекта.
6 | Чтобы использовать эту возможность надо объект зарегистрировать в этом пуле.
7 |
8 | ```Objective-C
9 | @autoreleasepool {
10 | // Code benefitting from a local autorelease pool.
11 | }
12 | ```
13 |
--------------------------------------------------------------------------------
/Answers/memory_managment/autorelease_vs_release.md:
--------------------------------------------------------------------------------
1 | ## `autorelease vs release`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Суть в следующем: release сразу дает команду очистить память.
6 | autorelease - говорит освободить память в автоматическом режиме, когда ОС будет это необходимо.
7 | целесообразность использования:
8 |
9 | autorelease надо использовать если мы делаем convenience constructor в классах.
10 | Есть правило, согласно которому мы не должны заботиться об очистке памяти в таких конструкторах.
11 | Там это нужно делать автоматически.
12 |
--------------------------------------------------------------------------------
/Answers/memory_managment/how_use_non_arc_libs.md:
--------------------------------------------------------------------------------
1 | ## Что делать, если проект написан с использованием ARC, а нужно использовать классы сторонней библиотеки написанной без ARC?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | В настройках для модулей использующих ручное управление памятью надо добавить флаг: `-fno-objc-arc`
6 |
--------------------------------------------------------------------------------
/Answers/memory_managment/manual_allocation.md:
--------------------------------------------------------------------------------
1 | ## Ручное выделение памяти под объект без alloc.
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | Объекты можно создавать с помощью старой доброй сишной функции calloc, задав потом isa вручную. В принципе, это лишь замена alloc, а init можно отправить и потом.
7 |
8 | ```Objective-C
9 | // Выделяем память, заполненную нулями
10 | void *newObject = calloc(1, class_getInstanceSize([TestObject class]));
11 | // Задаём isa прямой записью в память
12 | Class *c = (Class *)newObject;
13 | c[0] = [TestObject class];
14 | // Здесь __bridge_transfer-каст нужен для передачи объекта в ARC - иначе утечёт
15 | obj = (__bridge_transfer TestObject *)newObject;
16 | // Посылаем init - объект готов!
17 | obj = [obj init];
18 | ```
19 |
20 | Рекомендации по использованию: рекомендуется с превеликой осторожностью. Один из вариантов использования — выделение памяти разом под большой массив объектов (о чём рассказывал некогда AlexChernyy на CocoaHeads).
21 |
22 | UPD: Благодаря пользователю Trahman было установлено, что данный подход не работает на iOS x64. С его же помощью было найдено портабельное решение:
23 |
24 | ```Objective-C
25 | object_setClass((__bridge id)newObject, [TestObject class]);
26 | ```
27 |
28 | **Дополнительно**
29 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
30 |
--------------------------------------------------------------------------------
/Answers/memory_managment/memory_warning.md:
--------------------------------------------------------------------------------
1 | ## Как происходит обработка `memory warning`(предупреждение о малом количестве памяти)?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Если на устройстве заканчивается память в центр уведомлений приходит сообщение `UIApplicationDidReceiveMemoryWarningNotification`, наш обьект может об этом узнать через уведомления и что-либо сделать, например почистить кеш или сохранить данные.
6 | Если памяти все равно не хватило, ОС смотрит на список самых прожорливых приложений и постепенно выпиливает их из системы,
7 | освобождая тем самым память.
8 |
--------------------------------------------------------------------------------
/Answers/memory_managment/mrc.md:
--------------------------------------------------------------------------------
1 | ## Как происходит `ручное управление памятью - MRC` в iOS?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | При написании программы, мы для каждого объекта выделяем память и по окончании работы очищаем.
6 | Либо при создании отправляем команду объекту "autorelease" и он очистит память самостоятельно.
7 |
8 | То есть, ваша работа по управлению памятью сводится к простому правилу. Если вы создается объект используя методы alloc, copy, mutableCopy, new или посылаете объекту команду retain, не забудьте отправить ему release или autorelease сообщение в конце функции. Если вы создаете объект другими способами, то не делайте ничего.
9 |
--------------------------------------------------------------------------------
/Answers/memory_managment/retain_delegate.md:
--------------------------------------------------------------------------------
1 | ## Нужно ли `ретейнить` (посылать сообщение retain) `делегаты`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | **Если коротко - НЕТ.**
6 |
7 | Делегат объявляется как слабая ссылка на объект (weak) и должен жить пока жив его основной класс.
8 | Делая `retain` делегату, мы можем попасть в retain-цикл. И произойдет утечка памяти.
9 |
--------------------------------------------------------------------------------
/Answers/memory_managment/weak_vs_assign__strong_vs_copy.md:
--------------------------------------------------------------------------------
1 | ## Weak vs assign, strong vs copy?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | ##### Если коротко, то:
6 | `weak` - это при `ARC`, `assign` - дефолтовое значение. в `non ARC`.
7 | `Strong` - сильная ссылка. Не позволяет обнулить свойство
8 | `Copy` - почти тоже самое что и strong, только свойство должно поддерживать протокол `NSCoping` и при присваивании свойству объекта, ему будет посылаться сообщение `copy`.
9 |
10 | ---
11 | `copy` (соответствующая переменная должна быть с атрибутом `__strong`) — при таком значении атрибута владения в сгенерированном сеттере соответствующей переменной экземпляра присваивается значение, возвращаемое сообщением `copy`, отправленным присваиваемому объекту. Использование этого значения атрибута владения накладывает некоторые ограничения на класс объекта:
12 |
13 | класс должен поддерживать протокол `NSCopying`,
14 | класс не должен быть изменяемым (mutable). У некоторых классов есть mutable-подкласс, например, NSString-NSMutableString. Если ваше свойство — экземпляр «мутабельного» класса, использование `copy` приведет к нежелательным последствиям, так как метод `copy` вернет экземпляр его «немутабельного» сородича. Например, вызов `copy` у экземпляра NSMutableString вернет экземпляр `NSString`.
15 |
16 |
17 | `weak` (соответствующая переменная должна быть с атрибутом `__weak`) — это значение аналогично `assign` и `unsafe_unretained`. Разница в том, что особая уличная магия позволяет переменным с таким значением атрибута владения менять свое значение на nil, когда объект, на который указывала переменная, уничтожается, что очень хорошо сказывается на устойчивости работы приложения (ибо, как известно, nil отвечает на любые сообщения, а значит никаких вам `EXC_BAD_ACCESS` при обращении к уже удаленному объекту). Это значение атрибута владения стоит использовать при включенном ARC для исключения retain cycle’ов для свойств, в которых хранится указатель на делегат объекта и им подобных. Это единственное значение атрибута владения, которое не поддерживается при выключенном `ARC` (как и при включенном `ARC` на iOS до версии 5.0).
18 |
19 | `unsafe_unretained` (соответствующая переменная должна быть с атрибутом __unsafe_unretained) — свойство с таким типом владения просто сохраняет адрес присвоенного ему объекта. Методы доступа к такому свойству никак не влияют на счетчик ссылок объекта. Он может удалиться, и тогда обращение к такому свойству приведет к крэшу (потому и `unsafe`). Это значение использовалось вместо weak, когда уже появился ARC, но нужно было еще поддерживать iOS 4.3. Сейчас его использование можно оправдать разве что скоростью работы (есть сведения, что магия weak свойств требует значительного времени, хотя, конечно, невооруженным глазом при нынешней производительности этого не заметишь), поэтому, особенно на первых порах, использовать его не стоит.
20 |
21 | `assign` (соответствующая переменная должна быть с атрибутом `__unsafe_unretained`, но так как атрибуты владения есть только у типов попадающих под ARC, с которыми лучше использовать strong или weak, это значение вам вряд ли понадобится) — просто присвоение адреса. Без ARC является дефолтным значением атрибута владения. Его стоит применять к свойствам типов, не попадающих под действие ARC (к ним относятся примитивные типы и так называемые необъектные типы (non-object types) вроде CFTypeRef). Без ARC он также используется вместо weak для исключения retain cycle’ов для свойств, в которых хранится указатель на делегат объекта и им подобных.
22 |
--------------------------------------------------------------------------------
/Answers/networking/difference_between_head_get_post_put.md:
--------------------------------------------------------------------------------
1 | ## Какие различия между `HEAD, GET, POST, PUT`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Метод `GET` позволяет получать любую информацию (в форме объекта), идентифицированную запрашиваемым URI (Request-URI).
6 |
7 | Метод `HEAD` идентичен GET, за исключением того, что сервер НЕ ДОЛЖЕН возвращать в ответе тело сообщения (message-body). Метаинформации, содержащейся в HTTP заголовках ответа на запрос HEAD СЛЕДУЕТ быть идентичной информации, представляемой в ответ на запрос GET. Этот метод может использоваться для получения метаинформации об объекте запроса без непосредственной пересылки тела объекта (entity-body). Этот метод часто используется для тестирования гипертекстовых связей в целях проверки правильности, достижимости, и времени модификации.
8 |
9 | Основное различие методов GET и POST состоит в способе передачи данных веб-формы обрабатывающему скрипту, а именно:
10 | 1. Метод GET отправляет скрипту всю собранную информацию формы как часть URL:
11 |
12 | ```
13 | http://www.MySite.ru/script.php?login=admin&name=komtet
14 | ```
15 | 2. Метод POST передает данные таким образом, что пользователь сайта уже не видит передаваемые скрипту данные:
16 |
17 | ```
18 | http://ww.komtet.ru/script.php
19 | ```
20 |
21 | Оба метода успешно передают необходимую информацию из веб-формы скрипту, поэтому при выборе того или иного метода, который будет наиболее подходить сайту, нужно учитывать следующие факторы:
22 | 1. Принцип работы метода GET ограничивает объём передаваемой скрипту информации;
23 | Так как метод GET отправляет скрипту всю собранную информацию формы как часть URL (то есть в открытом виде), то это может пагубно повлиять на безопасность сайта;
24 | 2. Страницу, сгенерированную методом GET, можно пометить закладкой (адрес страницы будет всегда уникальный), а страницу, сгенерированную метод POST нельзя (адрес страницы остается неизменным, так как данные в URL не подставляются);
25 | 3. Используя метод GET можно передавать данные не через веб-форму, а через URL страницы, введя необходимые значения через знак &:
26 | http://www.komtet.ru/script.php?login=admin&name=komtet
27 | 4. Метод POST в отличие от метода GET позволяет передавать запросу файлы;
28 | 5. При использовании метода GET существует риск того, что поисковый робот может выполнить тот или иной открытый запрос.
29 |
--------------------------------------------------------------------------------
/Answers/networking/http_tcp.md:
--------------------------------------------------------------------------------
1 | ## Что означает `http, tcp`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | * `hyper text transfer protocol` - протокол передачи гипертекста
6 | * `transmission control protocol` — протокол управления передачей. Устанавливает устойчивое соединение. Повторно запрашивает данные.
7 | в случае потери пакетов. Гарантируя целостность переданных данных в отличии от UDP.Транспортный уровень модели OSI.
8 |
--------------------------------------------------------------------------------
/Answers/networking/rest.md:
--------------------------------------------------------------------------------
1 | ## Что такое архитектура `REST`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | `REST` (Representational state transfer) – это стиль архитектуры программного обеспечения для распределенных систем, таких как World Wide Web, который, как правило, используется для построения веб-служб. Термин REST был введен в 2000 году Роем Филдингом, одним из авторов HTTP-протокола. Системы, поддерживающие REST, называются RESTful-системами.
6 |
7 | Как происходит управление информацией сервиса – это целиком и полностью основывается на протоколе передачи данных. Наиболее распространенный протокол конечно же HTTP. Так вот, для HTTP действие над данными задается с помощью методов: GET (получить), PUT (добавить, заменить), POST (добавить, изменить, удалить), DELETE (удалить). Таким образом, действия CRUD (Create-Read-Updtae-Delete) могут выполняться как со всеми 4-мя методами, так и только с помощью GET и POST.
8 |
9 | Вот как это будет выглядеть на примере:
10 | * GET /book/ — получить список всех книг
11 | * GET /book/3/ — получить книгу номер 3
12 | * PUT /book/ — добавить книгу (данные в теле запроса)
13 | * POST /book/3 – изменить книгу (данные в теле запроса)
14 | * DELETE /book/3 – удалить книгу
15 |
--------------------------------------------------------------------------------
/Answers/objective_c/NSSet_NSArray.md:
--------------------------------------------------------------------------------
1 | ## Чем отличается `NSSet от NSArray`? Какие `операции` происходят быстро в `NSSet` и какие в `NSArray`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | * `NSSet` хранит уникальные объекты
6 | * `NSArray` - может хранить много одинаковых объектов.
7 | * В `NSSet` быстрей отрабатывает выборка
8 | * В `NSArray` быстрей работает вставка и удаление
9 |
--------------------------------------------------------------------------------
/Answers/objective_c/add_property_in_runtime.md:
--------------------------------------------------------------------------------
1 | ## Как добавить свойство в существующий объект с закрытой реализацией через runtime?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Добавляем свойство в GMSPlace. Добавляем shortAddress через runtime.
6 | ```Objective_c
7 | #import
8 | @interface GMSPlaceategory)
9 | @property (strong, nonatomic) NSString *shortAddress;
10 | @end
11 | #import "GMSPlace+Category.h"
12 | #import
13 |
14 | @implementation GMSPlace (Category)
15 | - (NSString*) shortAddress {
16 | return objc_getAssociatedObject(self, @selector(shortAddress));
17 | }
18 | - (void)setShortAddress:(NSString *)shortAddress {
19 | objc_setAssociatedObject(self, @selector(shortAddress), shortAddress, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
20 | }
21 | @end
22 | ```
23 |
--------------------------------------------------------------------------------
/Answers/objective_c/autorelease.md:
--------------------------------------------------------------------------------
1 | ## Что такое autorelease?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | [Доступно расписано тут](http://stackoverflow.com/questions/6578/understanding-reference-counting-with-cocoa-and-objective-c)
6 |
--------------------------------------------------------------------------------
/Answers/objective_c/base_oop_term_per_objc.md:
--------------------------------------------------------------------------------
1 | ## Опишите `основные понятия ОО парадигмы` в терминах Objective-C (`интерфейс, реализация, свойства, протоколы,` иa т.д)
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | ## Основные понятия ООП:
6 | ### Абстракция
7 |
8 | **Коротко:** Реализации в Objective-C нет.
9 |
10 | **Подробней:** `Абстрагирование` - это способ выделить существенные свойства и игнориро- вать несущественные. Соответственно, абстракция - это набор выделенных су- щественных свойств.
11 | Существенные свойства - это свойства, которыми сущность обязана обладать, чтобы быть именно этой сущностью. Несущественные свойства - свойства, обла- дание которыми необязательно.
12 | С точки зрения сложности, главное достоинство абстракции в том, что она позволяет игнорировать несущественные детали (не имеющие значения для про- граммы). Абстракция - это один из главных способов борьбы со сложностью ре- ального мира.
13 |
14 | ### Класс
15 |
16 | `Класс` - это абстрактная (виртуальная) модель (абстрактный тип данных), еще несуществующей сущности. Фактически класс является образцом для создания новых объектов или сущностей (формулой или руководством по эксплуатации). Обычно классы относятся к статичным сущностям, существующим в коде и неиз- менным в процессе выполнения.
17 | В отличии от объектов, классы обычно не содержат данных. Передача данных классу позволяет создавать объекты, описанного в классе типа (в ООП понятия тип данных и класс - синонимы).
18 | Объект, созданный по образцу класса называют экземпляром этого класса. Основное предназначение классов - определять поведение своих экземпляров. Обычно классы создают таким образом, чтобы они описывали объекты предмет- ной области (объекты реального мира).
19 | Классы позволяют описывать одинаковые сущности только один раз, умень- шая этим размеры и сложность программы.
20 |
21 |
22 | Пример простого класса:
23 |
24 | ```Objective-C
25 | //Файл с заголовками (интерфейсная часть)
26 | #import
27 | @interface LovecraftsDeity : NSObject
28 |
29 | @end
30 | ```
31 |
32 | ```Objective-C
33 | //Файл с имплементацией
34 | #import "LovecraftsDeity.h"
35 | @implementation LovecraftsDeity
36 |
37 | @end
38 | ```
39 |
40 | ### Объект
41 |
42 | В основе ООП находится понятие объекта. `Объект` - это абстракция изменяемого состояния памяти компьютера. Обычно объекты относятся к динамичным сущностям, создаваемым и изменяемым в процессе выполнения программы. Объекты обладают состоянием и поведением.
43 | Состояние объекта зависит от значения его свойств (хранимых объектом данных). Поведение объекта зависит от набора доступных ему методов. `Методы` - это сообщения, которыми обмениваются объекты. Это абстрактные сущности, определяющие действия, которые можно выполнить над объектом и действия, которые сам объект может выполнять. Пользуясь методами объекта мы можем влиять на его состояние, а посылая сообщения классу мы можем изменять состояние всех его экземпляров.
44 |
45 | Таким образом ООП оперирует состоянием, заключенным внутри объекта, и позволяет влиять на него с помощью предоставленных методов.
46 | Создание объектов позволяет уменьшить сложность программы, акцентируя внимание только на использующихся сущностях и их взаимодействии.
47 |
48 | Пример объекта на основе ранее описанного класса:
49 |
50 | ```Objective-C
51 | LovecraftsDeity *cthulhu = [LovecraftsDeity new];
52 | ```
53 |
54 | ### Свойство
55 |
56 | ...
57 |
58 | ### Метод
59 |
60 | ...
61 |
62 |
63 | ### Инкапсуляция
64 |
65 | `Инкапсуляция` - это механизм языка, позволяющий сущности объединять в себе данные и методы для работы с этими данными. Данные при этом скрыты от остальной программы, а методы доступны для взаимодействия объектов. Объект не считается отдельной сущностью, если его состояние может быть изменено без явного использования ссылки на объект.
66 | * Инкапсуляция позволяет распараллелить процессы создания программы, ускоряя разработку ПО
67 | * Инкапсуляция снижает сложность разработки, позволяя сосредоточиться
68 | на небольших фрагментах программы
69 | * Инкапсуляция помогает сокрытию деталей реализации, необходимых про- грамме, но выходящих за рамки абстракции. Инкапсуляция помогает управлять сложностью, скрывая доступ к ней.
70 |
71 | ```Objective-C
72 | //Файл с заголовками (интерфейсная часть)
73 | #import
74 | @interface LovecraftsDeity : NSObject
75 | -(void)call;
76 | @end
77 | ```
78 |
79 | ```Objective-C
80 | //Файл с имплементацией
81 | #import "LovecraftsDeity.h"
82 | @implementation LovecraftsDeity
83 | -(void)call {
84 | NSLog(@"The Call of LovecraftsDeity");
85 | NSLog(@"Some complicated methods...");
86 | }
87 | @end
88 | ```
89 |
90 |
91 | ### Наследование
92 | `Наследование` - это механизм языка, позволяющий сущности использовать структуру другой сущности, заимствуя и расширяя уже имеющуюся функциональность (например классы расширяют возможности модулей). Класс, который заимствуется (наследуется) называется базовым или суперклассом, а класс, который заимствует (наследует) - производным или подклассом. Все базовые и производные классы в общем создают иерархию классов программы.
93 | * Наследованиеснижаетвремянаразработкузасчетповторногоиспользования кода;
94 | * Наследование снижает сложность, позволяя использовать уже известные фрагменты программы. Однако при сложной иерархии повышается объем кода, с которым работает программист в отдельный момент времени;
95 | * Наследование дополняет абстракцию,выделяя сущности с незначительным уровнем различий. Наследование позволяет создавать абстракции с различным уровнем реализации (дополнительными группами существенных свойств).
96 |
97 | Наследник класса №1:
98 | ```Objective-C
99 | #import "LovecraftsDeity.h"
100 | @interface Cthulhu : LovecraftsDeity
101 | @property (nonatomic, strong) NSNumber *tentacles;
102 | @end
103 | ```
104 |
105 | ```Objective-C
106 | #import "Cthulhu.h"
107 | @implementation Cthulhu
108 | @end
109 | ```
110 |
111 | Наследник класса №2:
112 | ```Objective-C
113 | #import "LovecraftsDeity.h"
114 | @interface Shub_Niggurath : LovecraftsDeity
115 | -(void)generateMonsters;
116 | @end
117 | ```
118 |
119 | ```Objective-C
120 | #import "Shub-Niggurath.h"
121 | @implementation Shub_Niggurath
122 | -(void)generateMonsters {
123 | NSLog(@"Generate legion of monsters...");
124 | }
125 | @end
126 | ```
127 |
128 | ### Полиморфизм
129 |
130 | ...
131 |
--------------------------------------------------------------------------------
/Answers/objective_c/category_vs_extention.md:
--------------------------------------------------------------------------------
1 | ## Чем `категория` отличается от `расширения` (extension, наименованная категория)? `категория vs extension`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | * `Категория` - это добавления методов в часто закрытые от разработчика классы. Например `NSObject`.
6 | * `Категория` - это дополнительные методы к классу которые мы и прописываем. Категория имеет *.h и *.m файлы.
7 | * `Расширение` - это аналог приватных функций в *.m файле
8 |
--------------------------------------------------------------------------------
/Answers/objective_c/category_vs_inheritance.md:
--------------------------------------------------------------------------------
1 | ## Когда лучше использовать `категорию`, а когда `наследование`? `категория vs наследование`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
Наследование устанавливает ментальную связь между объектами предметной области.
6 |
Наследуясь мы расширяем свойства объекта и его поведение.
7 |
Категории используются только для расширения его функционала (методов).
8 |
--------------------------------------------------------------------------------
/Answers/objective_c/delegate.md:
--------------------------------------------------------------------------------
1 | ## Что такое `делегат (delegate)`? как его создать и использовать?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | `Делегат` - это шаблон проектирования. Класс позволяет хранить в себе ссылку на методы с определенной сигнатурой.
6 |
7 | Говоря простым языком, делегат - это такой класс, который реализует какой-то функционал. Передавая его в качестве ссылки,
8 | принимающий класс может вызывать его методы.
9 |
10 | В `Objective-C` при создании делегата его необходимо передавать как **слабую ссылку**. В ином случае возникнет `retain цикл` с последующей утечкой памяти.
11 |
--------------------------------------------------------------------------------
/Answers/objective_c/delegate_vs_notification.md:
--------------------------------------------------------------------------------
1 | ## Какая разница между использование `делегатов (delegation)` и `нотификейшенов (notification)`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | `Делегат` это конкретный объект, который принимает на себя управление.
6 | `Нотификация` - это отправка уведомления с конкретным ключем. Зная ключ, любой объект
7 | приложения сможет получить нотификацию (если реализован наблюдатель).
8 |
--------------------------------------------------------------------------------
/Answers/objective_c/designated_initializer.md:
--------------------------------------------------------------------------------
1 | ## Что такое назначеный `инициализатор (designated initializer`), напишите любой элементарный инициализатор, почему он так выглядит? (имеется ввиду `if (self = [super ...])`)?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | * Назначенный метод гарантирует полную инициализацию объекта, вызывая унаследованный init.
6 | * В данном конструкторе инициализируются все свойства объекта.
7 |
--------------------------------------------------------------------------------
/Answers/objective_c/fast_enumeration.md:
--------------------------------------------------------------------------------
1 | ## Что такое `быстрое перечисление (fast enumeration)`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Итерация (цикл) по коллекциям (`NSArray`, `NSDictionary`):
6 | ```Objective-C
7 | for Type *item in Collection {}
8 | ```
9 |
--------------------------------------------------------------------------------
/Answers/objective_c/formal_vs_informal_protocol.md:
--------------------------------------------------------------------------------
1 | ## `Формальный и неформальный (informal)` протокол?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | * `Формальный протокол` - это обычный протокол, который иммет обязательные и необязательные методы к реализации.
6 | * `Неформальный протокол` - это категории.
7 |
--------------------------------------------------------------------------------
/Answers/objective_c/how_get_current_coordinate.md:
--------------------------------------------------------------------------------
1 | ## Как получить текущую координату?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Получить текущую координату.
6 |
7 | ```Objective-C
8 | - (void)getNearbyPlaces
9 | {
10 | [self.placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList * _Nullable likelihoodList, NSError * _Nullable error) {
11 |
12 | if (error != nil) {
13 | NSLog(@"Current Place error %@", [error localizedDescription]);
14 | return;
15 | }
16 |
17 | for (GMSPlaceLikelihood *likelihood in likelihoodList.likelihoods) {
18 | GMSPlace* place = likelihood.place;
19 | NSLog(@"Current Place name %@ at likelihood %g", place.name, likelihood.likelihood);
20 | NSLog(@"Current Place address %@", place.formattedAddress);
21 | NSLog(@"Current Place attributions %@", place.attributions);
22 | NSLog(@"Current PlaceID %@", place.placeID);
23 | }
24 |
25 | NSLog(@"likelihoodList = %@", likelihoodList);
26 | }];
27 | }
28 |
29 | self.placesClient = [GMSPlacesClient sharedClient];
30 | ```
31 |
32 | [Ccылка на Google Places](https://developers.google.com/places/ios-api/start#add-a-place-picker)
33 |
--------------------------------------------------------------------------------
/Answers/objective_c/implicit_property.md:
--------------------------------------------------------------------------------
1 | ## Неявные property.
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Объявление @property в хедере на самом деле объявляет лишь геттер и мутатор для некоторого поля. Если их объявить напрямую, ничего не изменится:
6 | ```Objective-C
7 | - (int)value;
8 | - (void)setValue:(int)newValue;
9 |
10 | obj.value = 2;
11 | int i = obj.value;
12 | ```
13 |
14 | Так же неявные свойства — это любые функции, не принимающие аргументов, но возвращающие значение:
15 | ```Objective-C
16 | NSArray *a = @[@1, @2, @3];
17 | NSInteger c = a.count;
18 | ```
19 |
20 | А ещё — функции, имя которых начинается на «set», ничего не возвращающие, но принимающие один аргумент:
21 | ```Objective-C
22 | @interface TestObject : NSObject
23 | - (void)setTitle:(NSString *)title;
24 | @end;
25 |
26 | //...
27 |
28 | TestObject *obj = [TestObject new];
29 | obj.title = @"simple object";
30 | ```
31 |
32 | Рекомендации по использованию: объявление @property выглядит гораздо лучше, для этого и было введено. К свойствам лучше обращаться через ".", а вот обычные методы лучше вызывать через "[]". Иначе начинает сильно страдать читаемость кода.
33 |
34 | **Дополнительно**
35 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
36 |
--------------------------------------------------------------------------------
/Answers/objective_c/instancetype.md:
--------------------------------------------------------------------------------
1 | ## Использование instancetype.
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | В `ObjC` имеется замечательный тип `id`, который по сути является `NSObject *`, то есть, самым базовым типом для объектов, к которому можно привести любой другой объект. Удобно, но в некоторых случаях могут возникнуть проблемы. К примеру:
6 |
7 | ```Objective-C
8 | [[MyClass sharedInstance] count];
9 | ```
10 |
11 | Если sharedInstance возвращает id, то код соберётся без предупреждений даже если в `MyClass` нет метода `count`. Если же sharedInstance будет возвращать `instancetype`, то ворнинг всё же появится, ведь компилятор явно понимает, что возвращается объект того класса, у которого вызван `sharedInstance`.
12 |
13 | Рекомендации по использованию: уместно в методах типа `init/new/copy` и т.п.
14 |
15 | **Дополнительно**
16 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
17 |
--------------------------------------------------------------------------------
/Answers/objective_c/isa.md:
--------------------------------------------------------------------------------
1 | ## Что такое `указатель isa`? Для чего он нужен?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Указатель на Class для данного объекта. Каждый объект имеет ссылку на свой класс через isa.
6 |
7 | Определение NSObject
8 |
9 | ```Objective-C
10 | @interface NSObject {
11 | Class isa;
12 | }
13 | ```
14 |
15 | Как видим, вновь какая-то пременная. Но что это за Class такой? Переходим по определению, которое нам предлагает Xcode и попадаем в `usr/include/objc/objc.h`, в котором находим следущее:
16 |
17 | ```Objective-C
18 | typedef struct objc_class *Class;
19 | ```
20 |
21 | Идём дальше в `/usr/include/objc/runtime.h` и видим:
22 | ```Objective-C
23 | struct objc_class {
24 | Class isa;
25 |
26 | #if !__OBJC2__
27 | Class super_class OBJC2_UNAVAILABLE;
28 | const char *name OBJC2_UNAVAILABLE;
29 | long version OBJC2_UNAVAILABLE;
30 | long info OBJC2_UNAVAILABLE;
31 | long instance_size OBJC2_UNAVAILABLE;
32 | struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
33 | struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
34 | struct objc_cache *cache OBJC2_UNAVAILABLE;
35 | struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
36 | #endif
37 |
38 | } OBJC2_UNAVAILABLE;
39 | ```
40 |
41 | Таким образом, `Class` это указатель на структуру, которая… Начинается с ещё одного `Class`
42 | Посмотрим ещё один класс, `NSProxy`
43 |
44 | ```Objective-C
45 | @interface NSProxy {
46 | Class isa;
47 | }
48 | ```
49 | И тут он есть. Ещё один, `id`, за которым может скрываться любой объект в Objective-C
50 | ```Objective-C
51 | typedef struct objc_object {
52 | Class isa;
53 | } *id;
54 | ```
55 |
56 | И снова он. Очевидно, что каждый объект в Objective-C должен начинаться с Class isa, даже объекты классов. Так что же это такое?
57 | Как следует из названия и типа, переменная isa указывает, какому классу принадлежит тот или иной объект. Каждый объект в Objective-C должен начинаться с isa, иначе runtime не будет знать, что же с ним делать. Вся информация о типе каждого конкретного объекта скрывается за этим крохотным указателем. Оставшийся кусок объекта, с точки зрения runtime, представляет из себя просто огромный BLOB, не дающий никакой информации. Только лишь классы могут придать этому куску какой-то смысл.
58 |
59 |
60 | #### Классы
61 |
62 | Что же тогда на самом деле содержится в классах? Ответ на этот вопрос нам поможет найти «недоступные » поля структуры (те, что после #if !__OBJC2__, они оставлены здесь для совместимости с пре-Леопардом, и вы не должны пользоваться ими, если занимаеться разработкой пол Леопард и выше, однако, они помогут понять нам, что же за информация там скрывается). Сначала идет isa, позволяющий работать с классом, как с объектом. Потом идет ссылка на Class — предок, дабы не нарушалась иерархия классов. Далее идет некоторая базовая информация о классе. Но самое интересное — в конце. Это список переменных, список методов и список протоколов. Все это доступно во время исполнения, и может быть изменено там же!
63 |
64 | Я пропустил кэш, так как он не слишком интересен с точки зрения манипуляции во время исполнения, но стоит рассказать о том, какую роль он играет в принципе. Каждый раз, когда вы посылаете сообщение ([foo bar]), Runtime ищет его в списке методов класса объекта. Но так как это просто линейный список, этот процесс достаточно продолжительный. Кэш же — это хэш таблица, в которой содержатся уже вызывавшиеся до этого методы. Именно поэтому первый вызов метода может быть значительно дольше, чем все последующие.
65 |
66 | Исследуя runtime.h, вы можете обнаружить множество функций для доступа и изменению этих элементов. Каждая функция начинается с префикса, который показывает, с чем она имеет дело. Базовые начинаются на objc_, функции для работы с классами на class_, и так далее. Например, вы можете вызвать class_getInstanceMethod, чтобы узнать информацию о конкретном методе, такую как список аргументов/тип возвращаемого значения. Или же можете добавить новый метод с помощью class_addMethod. Вы даже можете создавать целые классы с помощью objc_allocateClassPair прямо во время исполнения!
67 |
68 | #### Практическое применеие
69 |
70 | Есть множество вариантов применеия этой Runtime мета-информации, вот только некоторые из них
71 | 1. **Автоматический поиск переменных/методов**. Apple уже реализовало это в виде `Key-Value Coding`: вы задаете имя, в соответсвии с этим именем получаете переменную или метод. Вы можете делать это и сами, если вас чем-то не устраивает реализация Apple.(прим. переводчика — например, вот так Better key-value observing for Cocoa)
72 | 2. **Автоматическая регистрация/вызов подклассов**. Используя `objc_getClassList` вы можете получить список классов, уже известных Runtime и, проследив иерархию классов, выяснить, какие подклассы наследуются из данного класса. Это дает вам возможность писать подклассы, которые будут отвечать за специфичиские форматы данных, или что-то в этом роде, и потом дать суперклассу возможность находить их самому, избавив себя от утомительной необходимости регистрировать их все руками.
73 | 3. **Автоматически вызвывать метод для каждого класса**. Это может быть полезно для `unit-testing` фреймворков и подобного рода вещей. Очень похоже на п. 2, но с акцентом на поиск возможных методов, а не на иерархию классов
74 | 4. **Перегрузка методов во время исполнения**. `Runtime` предоставляет вам полный набор инструментов для изменения реализации методов классов, без необходимости изменять что-либо в их исходном коде
75 | 5. **Bridging**. Имеея возможность динамически создавать классы и просматривать необходимые поля, вы можете создать мост между Objective-C и другим (достаточно динамичным) языком.
76 | 6.**И многое, многое другое! Не ограничивайте себя списком, представленным выше.
77 |
78 | #### Заключение
79 |
80 | Objective-C — это мощный язык, ключевую роль в динамичности которого играет всеохватывающий Runtime API. Быть может, не так уж и приятно возиться со всем этим C кодом, но возможности, которые он открывает, поистине огромны.
81 |
82 | (прим. переводчика — для тех, кому уже не терпится поиграться со всей этой бесконечной динамичностью Objective-C, но не хочется разбираться с runtime.h, Mike Ash выложил на GitHub проект — обертку над runtime.h, предоставляющую полный доступ ко всем вкусностям, описаным выше, но в привычном Objective-C синтаксисе.)
83 |
84 |
85 | #### URLs
86 | [Разработка → Objective-C Runtime изнутри](https://habrahabr.ru/post/148922/)
87 |
--------------------------------------------------------------------------------
/Answers/objective_c/ivar_access.md:
--------------------------------------------------------------------------------
1 | ## Доступ к публичным ivar-ам как в структурах.
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | Несмотря на очевидность данной фичи, многие разработчики о ней почему-то не знают. Знание это может быть полезно для разрешения конфликта имён.
7 | ```Objective-C
8 | @interface TestObject : NSObject
9 | {
10 | @public
11 | int field;
12 | }
13 |
14 | @implementation TestObject
15 |
16 | - (void)updateWithField:(int)field
17 | {
18 | self->field = field;
19 | }
20 |
21 | @end
22 |
23 | // ...
24 |
25 | TestObject *obj = [TestObject new];
26 | obj->field = 200;
27 | ```
28 |
29 | Рекомендации по использованию: в `ObjC` лучше для таких целей использовать `@property`.
30 |
31 | **Дополнительно**
32 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
33 |
--------------------------------------------------------------------------------
/Answers/objective_c/ivar_in_category.md:
--------------------------------------------------------------------------------
1 | ## Можно ли добавить `ivar` в категорию?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | ### НЕТ.
6 |
--------------------------------------------------------------------------------
/Answers/objective_c/kvo.md:
--------------------------------------------------------------------------------
1 | ## Что такое `KVO`? Когда его нужно использовать? Методы для обозревания объектов? Работает ли `KVO с instance переменными (полями)` объекта?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | ### Что такое `KVO`?
6 | `KVO` предоставляет механизм, который позволяет объектам получать оповещение во время изменения каких-либо из их свойств.
7 |
8 | ### Когда его нужно использовать?
9 |
10 | Если мы хотим, чтобы один объект выполнял какие-либо действия, во время изменения свойств другого объекта.
11 | Например, мы имеем `PersonObject` и `BankObject`. В случае, если меняется свойство `accountBalance` в объекте `BankObject`.
12 | Мы хотим вызывать определенный метод в `PersonObject`.
13 |
14 | ### Методы для обозревания объектов?
15 |
16 | В нашем примере:
17 | ```Objective-C
18 | [bankInstance addObserver: personInstance
19 | froKeyPath: @"accountBalance"
20 | options: NSKeyValueObservingOptionNew
21 | context: NULL];
22 | ```
23 |
24 | в `PersonObject` реализуем метод:
25 |
26 | ```Objective-C
27 | - (void) observeValueForKeyPath: (NSString *)keyPath
28 | ofObject: (id)object
29 | change: (NSDictionary *)change
30 | context: (void *)context {
31 | // code
32 | }
33 | ```
34 |
35 | ### Работает ли `KVO с instance переменными (полями)` объекта?
36 |
37 | Да.
38 |
--------------------------------------------------------------------------------
/Answers/objective_c/new_methods.md:
--------------------------------------------------------------------------------
1 | ## Квадратные скобки для доступа к элементам массива или словаря можно использовать и со своими объектами.
2 | (Новый синтаксис применим к любым объектам)
3 |
4 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
5 |
6 |
7 | Квадратные скобки для доступа к элементам массива или словаря можно использовать и со своими объектами. Для этого надо объявить следующие методы.
8 |
9 | Для доступа по индексу:
10 | ```Objective-C
11 | - (id)objectAtIndexedSubscript:(NSUInteger)index;
12 | - (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)index;
13 | ```
14 |
15 | Для доступа по ключу:
16 | ```Objective-C
17 | - (id)objectForKeyedSubscript:(id)key;
18 | - (void)setObject:(id)obj forKeyedSubscript:(id)key;
19 | ```
20 |
21 | Используем:
22 | ```Objective-C
23 | id a = obj[1];
24 | obj[@"key"] = a;
25 | ```
26 |
27 | Рекомендации по использованию: иногда можно, но только если Ваш класс не является коллекцией. Если является, лучше наследоваться от имеющихся.
28 |
29 | **Дополнительно**
30 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
31 |
--------------------------------------------------------------------------------
/Answers/objective_c/nil_Nil_NSNull.md:
--------------------------------------------------------------------------------
1 | ## Разница между nil и Nil?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | #### [Вот тут написано понятно](https://habrahabr.ru/post/165021/)
6 |
7 |
8 |
9 | |Обозначение|Легкимдвижением руки…|Поснение|
10 | |-|-|-|
11 | |0|0|Ноль — он везде ноль|
12 | |NULL|(void *)0|Нулевой указатель в языке Си|
13 | |nil|(id)0|Нулевой указатель на объект Objective-C|
14 | |Nil|(Class)0|Нулевой указатель типа Class в Objective-C|
15 | |NSNull|[NSNull null]|Синглтон класса NSNull — обёртки над nil и Null|
16 |
--------------------------------------------------------------------------------
/Answers/objective_c/noname_methods.md:
--------------------------------------------------------------------------------
1 | ## Безымянные методы.
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | Имя метода задавать не обязательно, если у него имеются аргументы. Нередко встречаются методы типа - (void)setSize:(CGFloat)x :(CGFloat)y, но это можно довести и до абсолюта:
7 | ```Objective-C
8 | @interface TestObject : NSObject
9 |
10 | + (id):(int)value;
11 | - (void):(int)a;
12 | - (void):(int)a :(int)b;
13 |
14 | @end
15 |
16 | // ...
17 |
18 | TestObject *obj = [TestObject :2];
19 | [obj :4];
20 | [obj :5 :7];
21 | ```
22 |
23 | Забавно выгладят и селекторы для таких методов: @selector(:) и @selector(::).
24 | Рекомендации по использованию: только в исследовательских целях.
25 |
26 |
27 | **Дополнительно**
28 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
29 |
--------------------------------------------------------------------------------
/Answers/objective_c/not_find_method_in_object.md:
--------------------------------------------------------------------------------
1 | ## Что происходит с методом после того, как он не нашелся в объекте класса, которому его вызвали?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Будет вызван поиск метода в предке класса. И так до NSObject. Если и там метод не будет найден - произойдет crash приложения.
6 |
--------------------------------------------------------------------------------
/Answers/objective_c/nsarray_nsmutablearray.md:
--------------------------------------------------------------------------------
1 | ## В чем разница между `NSArray и NSMutableArray`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | * NSMutableArray позволяет изменять состав коллекции.
6 | * NSArray - не меняется после создания.
7 |
--------------------------------------------------------------------------------
/Answers/objective_c/nsfastenumaration.md:
--------------------------------------------------------------------------------
1 | ## Что не так с этим кодом? Зачем нужны `инициализаторы`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Что ж, в заключение ещё одна интересная фича `ObjC`: циклы `for..in`. Их поддерживают все дефолтные коллекции, но можем поддержать и мы. Для этого надо поддержать протокол `NSFastEnumeration`, а точнее — определить метод `countByEnumeratingWithState:objects:count:`, но не всё так просто! Вот сигнатура этого метода:
6 |
7 | ```Objective-C
8 | - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len
9 | ```
10 |
11 | Этот метод будет вызван каждый раз, когда runtime захочет получить от нас новую порцию объектов. Их мы должны записать либо в предоставленный буфер (размер его len), либо выделить свой. Указатель на этот буфер надо поместить в поле `state->itemsPtr`, а количество объектов в нём вернуть из функции. Так же не забываем, что (в документации этого нет) поле `state->mutationsPtr` не должно быть пустым. Если этого не сделать, то мы получим неожиданный `SEGFAULT`. А вот в поле `state->state` можно записать что угодно, но лучше всего — записать количество уже отданных элементов. Если отдавать больше нечего, нужно вернуть ноль.
12 |
13 | Вот мой пример реализации этой функции:
14 | ```Objective-C
15 | - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len
16 | {
17 | if (state->state >= _value)
18 | {
19 | return 0;
20 | }
21 | NSUInteger itemsToGive = MIN(len, _value - state->state);
22 | for (NSUInteger i = 0; i < itemsToGive; ++i)
23 | {
24 | buffer[i] = @(_values[i + state->state]);
25 | }
26 | state->itemsPtr = buffer;
27 | state->mutationsPtr = &state->extra[0];
28 | state->state += itemsToGive;
29 | return itemsToGive;
30 | }
31 | ```
32 |
33 | Теперь можно использовать:
34 | ```Objective-C
35 | for (NSNumber *n in obj)
36 | {
37 | NSLog(@"n = %@", n);
38 | }
39 | ```
40 |
41 | Рекомендации по использованию: может быть полезно для упрощения работы с кастомными структурами данных, к примеру, с деревьями и связанными списками.
42 |
43 | **Дополнительно**
44 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
45 |
--------------------------------------------------------------------------------
/Answers/objective_c/nsobject_vs_id.md:
--------------------------------------------------------------------------------
1 | ## Разница между NSObject и id?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
Все непримитивные объекты являются типом id.
6 |
Типу id можно посылать какие угодно сообщения.
7 |
Объекту NSObject можно посылать только декларированые у него сообщения.
8 |
Явное указание типа объекта помогает компилятору искать нужные методы и разрешать неоднозначности.
9 |
--------------------------------------------------------------------------------
/Answers/objective_c/print_autoreleasepool.md:
--------------------------------------------------------------------------------
1 | ## Распечатать текущий autorelease pool
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | У ObjC имеются «скрытые» функции, доступ к которым можно получить с помощью `extern`:
6 |
7 | ```Objective-C
8 | extern void _objc_autoreleasePoolPrint(void);
9 | ```
10 |
11 | После вызова этой функции в консоль будет выведено содержимое текущего авторелиз-пула, примерно в таком виде:
12 | ```Objective-C
13 | objc[26573]: ##############
14 | objc[26573]: AUTORELEASE POOLS for thread 0x7fff72fb0310
15 | objc[26573]: 9 releases pending.
16 | objc[26573]: [0x100804000] ................ PAGE (hot) (cold)
17 | objc[26573]: [0x100804038] ################ POOL 0x100804038
18 | objc[26573]: [0x100804040] 0x100204500 TestObject
19 | objc[26573]: [0x100804048] 0x100102fc0 __NSDictionaryM
20 | objc[26573]: [0x100804050] 0x1007000b0 __NSArrayI
21 | objc[26573]: [0x100804058] 0x1006000a0 __NSCFString
22 | objc[26573]: [0x100804060] 0x100600250 NSMethodSignature
23 | objc[26573]: [0x100804068] 0x100600290 NSInvocation
24 | objc[26573]: [0x100804070] 0x100600530 __NSCFString
25 | objc[26573]: [0x100804078] 0x100600650 __NSArrayI
26 | objc[26573]: ##############
27 | ```
28 |
29 | Это бывает очень полезно для дебага. Можно поискать и другие полезные штуки [здесь](www.opensource.apple.com/source/objc4/objc4-551.1)
30 |
Рекомендации по использованию: в дебаге — пожалуйста.
31 |
32 |
33 | **Дополнительно**
34 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
35 |
--------------------------------------------------------------------------------
/Answers/objective_c/private_and_protected_methods.md:
--------------------------------------------------------------------------------
1 | ## Есть ли `приватные и защищенные` методы в Objective-C?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | Нет, таких методов нет. Но можно реализовать их иммитацию.
6 |
7 | ```Objective-C
8 | /////// SuperClass.h
9 | @interface SuperClass @end
10 |
11 | /////// SuperClass.m
12 | @implementation SuperClass
13 | - (void) protectedMethod
14 | {}
15 | @end
16 |
17 | /////// SubClass.h
18 | @interface SubClass : SuperClass
19 | @end
20 |
21 | /////// SubClass.m
22 | @interface SubClass (Protected)
23 | - (void) protectedMethod ;
24 | @end
25 |
26 | @implementation SubClass
27 | - (void) callerOfProtectedMethod
28 | {
29 | [self protectedMethod] ; // this will not generate warning
30 | }
31 | @end
32 | ```
33 |
--------------------------------------------------------------------------------
/Answers/objective_c/proxing.md:
--------------------------------------------------------------------------------
1 | ## Проксирование: forwardingTargetForSelector: и forwardInvocation:
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | Для ООП свойственно введение дополнительных уровней абстракции при некоторых проблемах. К примеру, иногда нужно из объекта сделать прокси для другого объекта. В этом нам всегда помогут следующие методы.
7 |
8 | Если в нашем объекте не найдена имплементация для некоторого селектора, то ему будет послано следующее сообщение:
9 |
10 | ```Objective-C
11 | - (id)forwardingTargetForSelector:(SEL)aSelector
12 | {
13 | if ([_dict respondsToSelector:aSelector])
14 | {
15 | return _dict;
16 | }
17 | return [super forwardingTargetForSelector:aSelector];
18 | }
19 | ```
20 |
21 | Если объект, который мы проксируем, отвечает на селектор, то пусть он и реагирует на него. Иначе всё таки придётся кинуть эксепшн.
22 |
23 | Если мы хотим не просто передать селектор другому объекту, но при этом и изменить сам селектор, мы можем воспользоваться следующей парой функций.
24 |
25 | Сначала на запрос сигнатуры неизвестного нам метода мы должны вернуть сигнатуру существующего метода проксируемого объекта:
26 | ```Objective-C
27 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
28 | {
29 | NSMethodSignature *sig = [super methodSignatureForSelector:aSelector];
30 | if ([NSStringFromSelector(aSelector) isEqualToString:@"allDamnKeys"])
31 | {
32 | sig = [_dict methodSignatureForSelector:@selector(allKeys)];
33 | }
34 | return sig;
35 | }
36 | ```
37 |
38 | Затем перенаправляем вызов и меняем имя селектора:
39 | ```Objective-C
40 | - (void)forwardInvocation:(NSInvocation *)anInvocation
41 | {
42 | if ([NSStringFromSelector(anInvocation.selector) isEqualToString:@"allDamnKeys"])
43 | {
44 | anInvocation.selector = @selector(allKeys);
45 | [anInvocation invokeWithTarget:_dict];
46 | }
47 | }
48 | ```
49 |
50 | Рекомендации по использованию: очень удобный механизм для реализации прокси-объектов. Возможно, кто-то найдёт и другие варианты использования. Главное — не переусердствовать: код должен быть читаем и легко понимаем.
51 |
52 |
53 | **Дополнительно**
54 | * [Источник + доп материал.](https://habrahabr.ru/company/mailru/blog/210672/)
55 |
--------------------------------------------------------------------------------
/Answers/objective_c/root_classes.md:
--------------------------------------------------------------------------------
1 | ## Какие существуют `root классы` в iOS? Для чего нужны `root классы`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | `NSObject`, `NSProxy`, `Protocol`, `Class`.
6 |
7 | `NSObject` - корневой класс для всех классов, реализует базовую функциональность.
8 | `NSProxy` - позволяет предварительно конфигурировать группы объектов по определенным
9 | шаблонам.
10 |
--------------------------------------------------------------------------------
/Answers/objective_c/run_loop.md:
--------------------------------------------------------------------------------
1 | ## Что такое `Run Loop`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | Циклы выполнения (Run-Loops)
7 | Циклы выполнения - часть инфраструктуры, используемой для управления событиями прибывающими асинхронно в потоке. Циклы выполнения работают по мониторингу одного или нескольких источников событий для потока. Как только события прибыли, система пробуждает поток и отправляет события на цикл выполнения, который затем передает их указанным обработчикам. Если нет событий готовых быть обработанными, цикл выполнения ставит поток в режим сна.
8 |
9 | Вы не обязаны использовать циклы выполнения с любым созданным потоком, но это может обеспечить лучший опыт для пользователей. Циклы выполнения позволяют создавать долгоживущие потоки, использующие минимальное количество ресурсов. Поскольку цикл выполнения ставит свой поток в режим сна тогда, когда нечего делать, он устраняет необходимость опроса, который тратит ресурсы процессора и позволяет процессору уснуть для экономии энергии.
10 |
11 | Для настройки цикла выполнения, все, что необходимо сделать, это запустить ваш поток, получить ссылку на объект цикла выполнения, установить обработчики событий, и запустить цикл выполнения. Инфраструктура, предоставляемая как Cocoa, так и Carbon обрабатывает конфигурации запуска цикла основного потока автоматически. Если вы планируете создать долгоживущий вторичный поток, необходимо настроить цикл выполнения для этих потоков самому.
12 |
--------------------------------------------------------------------------------
/Answers/objective_c/runtime.md:
--------------------------------------------------------------------------------
1 | ## Суть `рантайма (Runtime), отправление сообщения`.
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
6 | [Вот тут подробно расписиано](https://habrahabr.ru/post/177421/)
7 |
8 | Метды рантайма описаны в заголовочных файлах: objc.h, runtime.h и message.h
9 |
10 | `Runtime`, библиотека времени выполнения, предоставляет тот набор функций, которые "вдыхают" в язык жизнь, реализуя его динамические возможности и обеспечивая функционирование ООП.
11 |
12 | Класс в Objective-C — это полноценный объект и у него тоже присутствует isa-указатель на «класс класса», так называемый метакласс в терминах Objective-C. Аналогично, С-структуры определены и для других сущностей языка:
13 |
14 | #### Функции Runtime-библиотеки
15 |
16 | Помимо определения основных структур языка, библиотека включает в себя набор функций, работающих с этими структурами. Их можно условно разделить на несколько групп (назначение функций, как правило, очевидно из их названия):
17 | * Манипулирование классами: class_addMethod, class_addIvar, class_replaceMethod
18 | * Создание новых классов: class_allocateClassPair, class_registerClassPair
19 | * Интроспекция: class_getName, class_getSuperclass, class_getInstanceVariable, class_getProperty, class_copyMethodList, class_copyIvarList, class_copyPropertyList
20 | * Манипулирование объектами: objc_msgSend, objc_getClass, object_copy
21 | * Работа с ассоциативными ссылками
22 |
--------------------------------------------------------------------------------
/Answers/objective_c/selector.md:
--------------------------------------------------------------------------------
1 | ## `Селектор (selector).`
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | ### Что такое `селектор (selector)`?
6 |
7 | Селектор - это имя метода закодированное специальным образом, используемым objective-c для быстрого поиска. Указание компилятору на селектор происходит при помощи директивы @selector(метод)
8 |
9 | ```objective-c
10 | First* f = [[First alloc] init];
11 | if([f respondsToSelector:@selector(setName:)]){
12 | NSLog (@"Метод поддерживается");
13 | }
14 | ```
15 | В этом примере создается экземпляр класса `First *f` (наследник `NSObject`), после с помощью метода respondsToSelector проверяем может ли класс ответить на метод `setName`.
16 |
17 |
18 | ### Как его вызвать?
19 | ```Objective-C
20 | [self performSelector:@selector(method)];
21 | ```
22 |
23 | ### Как отложить вызов селектора?
24 | ```Objective-C
25 | [self performSelector:@selector(method) withObject:obj afterDelay:delay];
26 | ```
27 |
28 | ### Что делать если селектор имеет много параметров?
29 |
30 | ```Objective-C
31 | @selector(method:::) - двоиточий столько сколько параметров.
32 | ```
33 |
34 | ### (NSInvocation)
35 |
36 | Вызывает метод у объекта, можно менять параметры и цель.
37 | Как запустить селектор во фоновом потоке?
38 | ```Objective-c
39 | [self performSelectorInBackground:selector withObject:obj];
40 | ```
41 |
--------------------------------------------------------------------------------
/Answers/objective_c/send_message_to_id.md:
--------------------------------------------------------------------------------
1 | ## Какая разница между использование `делегатов (delegation)` и `нотификейшенов (notification)`?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 |
`id` - это указатель на любой **не примитивный** объект. В `ARC` нельзя сконвертировать примитив в `id`.
6 |
Выполнит соответствуюший метод, если найдёт, иначе выбросит исключение.
7 |
--------------------------------------------------------------------------------
/Answers/objective_c/uinavigationcontroller.md:
--------------------------------------------------------------------------------
1 | ## Что такое UINavigationController?
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | * [Apple dev docs](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/)
6 | * [HARB](https://habrahabr.ru/post/263069/)
7 | * [macbug](http://macbug.ru/ios/cnavigation)
8 |
--------------------------------------------------------------------------------
/Answers/swift/weak_vs_unowned.md:
--------------------------------------------------------------------------------
1 | ## Weak vs unowned
2 |
3 | [**Вернутся к списку вопросов**](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/readme.md)
4 |
5 | [Подробное описание с примерами по ссылке](http://krakendev.io/blog/weak-and-unowned-references-in-swift)
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Вопросы и ответы для собеседования на позицию iOS разработчика:
2 |
3 | =======
4 | General:
5 | --------
6 | - [Что такое `полиморфизм`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/General/OOP/Polymorphism.md)
7 | - [Что такое `инкапсуляция`? Что такое нарушение инкапсуляции?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/General/OOP/Encapsulation.md)
8 | - [Чем `абстрактный класс` отличается от `интерфейса`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/General/OOP/Abstract_class_vs_interface.md)
9 | - [Что такое `SOLID` принципы?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/General/SOLID.md)
10 | - [Расскажите о паттерне `MVC`. Чем отличается `пассивная` модель от `активной`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/General/Pattern/MVC_active_vs_passive.md)
11 | - [Какие еще `паттерны` знаете?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/General/Pattern/Little_bit_about_patterns.md)
12 |
13 | UIKit:
14 | ------
15 | - [Цикл жизни ios-приложения. Какие бывают `состояния` у приложения?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/App_lifecycle.md)
16 | - [Разница между свойствами `bounds и frame` объекта UIView? Понимание системы координат?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/Frame_vs_Bounds.md)
17 | - [Цикл жизни `UIViewController`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/UIViewController_lifecycle.md)
18 | - Что такое `View` (представление) и что такое `window`?
19 | - [Какого разрешение экранов iphon'ов, и в чем разница между `points (точками)` и `пикселями (pixels)`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/Size_of_iPhone_and_different_between_points_and_pixels.md)
20 | - [Что означают `IBOutlet` и `IBAction`, для чего они нужны, и что значат для препроцессора?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/IBOutlet_vs_IBAction.md)
21 | - [Как работает `UITableView`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/Use_UITableView.md)
22 | - [Как многопоточность работает с `UIKit`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/Multithreading_with_UI/Multithreading_with_UI.md)
23 | - Что можно сделать если клавиатура при появлении скрывает важную часть интерфейса?
24 | - Почему мы должны `релизить IBOutlet'ты` во viewDidUnload?
25 | - Что такое `awakeFromNeeb`, в чем разница между `xib и nib` файлами?
26 | - Иерархия наследования UIButton.
27 | - [Что такое `responder chain`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/Responder_chain.md)
28 | - [Как работают `push нотификации`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/UIKit/How_to_work_with_push_notification.md)
29 |
30 |
31 | Multithreading:
32 | ---------------
33 | - [Что такое `состояние гонки`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/Multithreading/Race_condition.md)
34 | - [Что такое `deadlock`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/Multithreading/Deadlock.md)
35 | - [Что такое `livelock`?](https://github.com/CoBug92/Interview_iOS/blob/master/Answers/Multithreading/Livelock.md)
36 | - [Что такое `семафор (semafor)`?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/multithreading/semaphore.md)
37 | - [Что такое `мьютекс (mutex)`?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/multithreading/mutex.md)
38 | - `Асинхронность` vs `многопоточность`. Чем отличаются?
39 | - [Какие технологии в iOS возможно использовать для работы с потоками. Преимущества и недостатки.](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/multithreading/another_thread_technology.md)
40 | - Как запустить поток? Что первым нужно сделать при запуске потока? (NSAutoreleasePool - пул автоосвобождения) Что такое runLoop, кодга он используется? (timers, nsurlconnection …)
41 | - [Чем отличается `dispatch_async от dispatch_sync`?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/multithreading/dispatch_sync_vs_async.md)
42 | - Для чего при разработке под iOS использовать `POSIX-потоки`? `pthread_create(&thread, NULL, startTimer, (void *)t);`
43 | - А чем реально `POSIX-потоки` лучше чем `GCD или NSOperationQueue вместе с NSOperation`? Приходилось ри реально использовать POSIX и как в этом были прюсы? Реально, просто интересно…
44 | `Use POSIX calls if cross-platform portability is required. If you are writing networking code that runs exclusively in OS X and iOS, you should generally avoid POSIX networking calls, because they are harder to work with than higher-level APIs. However, if you are writing networking code that must be shared with other platforms, you can use the POSIX networking APIs so that you can use the same code everywhere. `
45 |
46 |
47 | Networking:
48 | ----------
49 | - Преимущества и недостатки `синхронного и асинхронного` соединения?
50 | - [Что означает `http, tcp`?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/networking/http_tcp.md)
51 | - [Какие различия между `HEAD, GET, POST, PUT`?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/networking/difference_between_head_get_post_put.md)
52 | - Как загрузить что-то из интернета? В чем разница между `синхронными и асинхронными запросами`?
53 | - [Небольшое задание. Опишите как загрузить изображение из интернета и отобразить его в ImageView — все это должно происходить после нажатия кнопки.]()
54 | - [Архитектура REST](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/networking/rest.md)
55 |
56 |
57 | Базы данных, CoreData:
58 | ----------------------
59 | - Составить SQL запрос на выборку всех проектов на которых сидит девелопер с
60 | id ==3. (`Developers:id,name; Projects:id,name; Developers&Projects:project_id,developer_id`)?
61 | - Зачем нужно делать `двустороннии связи` в таблицах?
62 |
63 | - [Что такое `Core Data`?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/coredata/coredata.md)
64 | - [В каких случаях лучше использовать `SQLite`, а в каких `Core Data`?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/coredata/sqlite_vs_coredata.md)
65 | - ~~Что такое `контекст (Managed object context)`? Как происходят `изменения в NSManagedObjectContext`?~~
66 | - ~~Что такое `Persistent store coordinator`? Зачем нужен `NSPersistentStoreCoordinator`?~~
67 | - [Какие есть нюансы при использовании `Core Data в разных потоках`? Как `синхронизировать данные между потоками`(Как синхронизировать контекст)? Синхронизация разных типов NSManagedObjectContext (получение и изменение данных в child контекстах)?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/coredata/coredata_vs_threads.md)
68 |
69 | - [Использовали ли `NSFetchedResultsController`? Почему?](https://github.com/Torlopov-Andrey/hh_interview_ios/blob/master/answers/coredata/nsfetchresultcontroller.md)
70 | - Что такое `Fault` и зачем он нужен?
71 | - Что таке `Fetched Property` и особенности работы с ним по сравнению с обычной связью?
72 | - Как использовать `СoreData` совместно с `многопоточностью`?
73 | - Что такое `NSManagedObjectId`? Можем ли мы сохранить его на потом если приложение закроется?
74 | - Какие `типы хранилищ` поддерживает CoreData?
75 | - Что такое `ленивая загрузка (lazy loading)`? Что ее связывает с CoreData? Опишите ситуация когда она может быть полезной?
76 |
77 | CoreAnimation, CoreGraphics:
78 | ----------------------------
79 | - Чем отличается `UIView от CALayer`?
80 | - Какие типы `CALayer` есть?
81 | - Чем отличается `UIView based Animation от Core Animation`?
82 | - Тайминги в `CoreAnimation`?
83 | - Что такое `backing store`?
84 | - Чем отличаются `аффинные преобразования от трехмерных`?
85 | - Нужно ли `ретейнить (посылать сообщение retain)` делегат для `CAAnimation`?
86 |
87 |
88 |
89 |
90 |
91 |
92 | ----------------------------
93 | За список вопросов и часть ответов спасибо:
94 | * [Torlopov-Andrey](https://github.com/Torlopov-Andrey)
95 |
--------------------------------------------------------------------------------