iOS.

iOS.

Andrey Maliayev

Career.

E-mail: andreymaliayevcareer@gmail.com

Telegram: @AndreyMaliayev



Interview.

ООП.

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


Классы и объекты.

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

Переменная-объект, относящаяся к заданному классом типу, называется экземпляром этого класса.

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


Объект - сущность, обладающая определенным состоянием и поведением, имеющая определенные свойства (поля, properties) и методы (функции, func). Методы объекта отвечают за операции над свойствами объекта.

Объект и экземпляр класса - взаимозаменяемые термины.


Другими словами класс - является описанием объекта, методов и свойств. Объект - это реализация класса.


Свойства и методы.

Свойство - это способ доступа к внутреннему состоянию объекта. Свойства представляют собой переменную или константу определенного типа. Обращение к свойствам реализуется через функции:

  • при установке значения вызывается метод, называемый сеттером (setter);
  • при получении значения вызывается метод, называемый геттером (getter).

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


Метод - это функция, принадлежащая какому-либо классу или объекту.

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

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

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


Интерфейсы.

Интерфейсы (протоколы в Swift) - определяют список свойств и методов, которые удовлетворяют требованиям конкретной задачи. Интерфейсы (протоколы) не предоставляют реализацию для любого из этого требований, они только описывают, как реализация должна выглядеть.

В Swift интерфейсы (протоколы) могут быть приняты классами, структурами и перечислениями, которые обязаны реализовать все обязательные требования интерфейса (протокола).

Любой тип, который удовлетворяет требованиям интерфейса (протокола), реализует или соответствует ему. Эти понятия равнозначны.


Абстракция.

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


Инкапсуляция.

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


Наследование.

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


Полиморфизм.

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

Полиморфизм - способность функции обрабатывать данные разных типов. Пример с разными животными в мешке.



SOLID.


  • Single responsibility;
  • Open-closed;
  • Liskov substitution;
  • Interface segregation;
  • Dependency inversion.

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


Single responsibility principle.

Принцип единой ответственности.

У класса должен быть только один мотив для изменения.


Каждый объект должен иметь одну ответственность и эта ответственность должна быть полностью инкапсулирована (скрыта внутри класса).


Open-closed principle.

Принцип открытости / закрытости.

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


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

Программные сущности должны быть:

  • открыты для расширения: поведение сущности может быть расширено, путём создания новых типов сущности;
  • закрыты для изменения: в результате расширения поведения сущности, не должны вносится изменения в код, которые эти сущности использует.

Согласно принципу открытости / закрытости, классы подразделяются на:

  • открытые;
  • закрытые.

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

Закрытым (или законченным) считается класс, который готов для использования другими классами, то есть интерфейс класса окончательно определен и не будет изменен в будущем.


Liskov substitution.

Принцип подстановки Барбары-Лисков.

Подклассы должны дополнять, а не замещать поведение базового класса.


Принцип определяет понятие замещения. Это означает, что если тип S является подтипом Т, тогда объекты типа T в программе могут быть замещены объектами типа S без каких-либо изменений желательных свойств этой программы. Более простыми словами можно сказать, что поведение наследуемых классов не должно противоречить поведению, заданному базовым классом, то есть поведение наследуемых классов должно быть ожидаемым для кода, использующего переменную базового типа.


Interface segregation.

Принцип разделения интерфейса.

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


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


Dependency inversion.

Принцип инверсии зависимостей.

Классы верхних уровней не должны зависеть от классов нижних уровней. Оба уровня должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.


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



Dependency injection.

Внедрение зависимостей.

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

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

class Car {

  private let wheel: Wheel()
  private let battery: Batter()

}

Константы wheel и battery в данном случае являются зависимостями класса Car.

Способы внедрения зависимостей:

  • через инициализатор (constructor injection);
  • через свойство (setter injection);
  • через метод (interface injection).



Value types vs Reference types.


Value type.

Тип значения.

Экземпляр типа значения является независимым экземпляром и хранит свои данные в своем собственном распределении памяти.

Существует несколько различных типов значений: struct, enum, tuple.

Example: Array, String, Dictionary.


Reference type.

Ссылочный тип.

Экземпляры ссылочного типа совместно используют одну копию своих данных, так что каждый новый экземпляр будет указывать на один и тот же адрес в памяти. Ссылочные типы: class, func, clousure.


Optional.

Опциональные (необязательные) значения позволяют безопасно обрабатывать ситуации, когда значение переменной может отсутствовать. То есть опциональное значения может как присутствовать в переменной, так и отсутствовать, в таком случае будет возвращен nil. Опциональными могут быть как ссылочные типы, так и типы значения.

Опциональные значения позволяют переменной любого типа представить ситуацию "отсутствие значения". В Objective-C «отсутствие значения» было доступно только в ссылочных типах с использованием специального значения nil. У типов-значений (Value types), вроде int или float, такой возможности не было. Swift расширил концепцию «отсутствия значения» на типы-значения. Переменная optional может содержать либо значение, либо nil, сигнализирующее об отсутствии значения.


Опциональное значение - это enum.

enum Optional<Wrapped> {
    
    // отсутствие значения
    case none

    // наличие значения, хранящегося как `Wrapped`
    case some(Wrapped)
}

Работа с опциональными значениями.

Безопасные варианты:

  • Optional binding:
if let a = x {
  print("x was successfully unwrapped and is = \(a)")
}
  • Оператор Guard — безопасно:
guard let a = x else {
  return
}
  • Optional chaining — безопасно:
let a = x?.count
  • Nil coalescing operator — безопасно:
let a = x ?? ""
  • Optional pattern — безопасно.
if case let a? = x {
  print(a)
}

Небезопасные варианты:

  • Forced unwrapping (принудительное развёртывание) - небезопасно:
let a: String = x!
  • Неявное развертывание при объявлении переменной - небезопасно.
var a = x!



Class and Struct.

Отличия:

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

Классы хранятся в куче, а структуры в стеке.

Классы:

  • ссылочный тип (reference type), то есть передаются по ссылке (все ссылки указывают на один объект в памяти);
  • имеют счетчик ссылок;
  • поддерживают наследование;
  • обязательный инициализатор (конструктор);
  • имеется метод деинициализации (deinit);
  • методы класса могут менять его значения.

Структуры:

  • тип-значение (value type), то есть передаются по значению (с помощью копирования);
  • не поддерживают наследование;
  • не имеют счетчика ссылок, из-за чего невозможна утечка памяти;
  • безопасны в многопоточной среде, поскольку несколько потоков могут изменять экземпляр, не беспокоясь о состоянии гонки или взаимоблокировках;
  • быстрее, чем ссылочные типы;
  • нет метода деинициализации (deinit);
  • инициализатор (конструктор) не обязательный, инициализация осуществляется автоматически;
  • если метод меняет значение самой структуры, его необходимо пометить как mutating.

Общие характеристики:

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

Дополнительные возможности классов:

  • Наследование, что позволяет одному классу наследовать характеристики другого;
  • Приведение типов позволяет проверить и интерпретировать тип экземпляра класса в процессе выполнения;
  • Деинициализаторы позволяют экземпляру класса освободить любые ресурсы, которые он использовал;
  • Подсчет ссылок допускает более чем одну ссылку на экземпляр класса.



MVC.

Концепция MVC позволяет разделить данные, представление и обработку действий пользователя на три отдельных компонента:

  • Модель (англ. Model). Модель предоставляет знания: данные и методы работы с этими данными, реагирует на запросы, изменяя своё состояние. Не содержит информации, как эти знания можно визуализировать;
  • Представление, вид (англ. View). Отвечает за отображение информации (визуализацию). Часто в качестве представления выступает форма (окно) с графическими элементами;
  • Контроллер (англ. Controller). Обеспечивает связь между пользователем и системой: контролирует ввод данных пользователем и использует модель и представление для реализации необходимой реакции.

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

Активная модель оповещает представление о том, что в ней произошли изменения, а представления, которые заинтересованы в оповещении, подписываются на эти сообщения. Это позволяет сохранить независимость модели как от контроллера, так и от представления.


MVC.



MVVM.

View (ViewController) и Model имеют «посредника» — View Model. View Model — это независимое от UIKit представление View. View Model вызывает изменения в Model и самостоятельно обновляется с уже обновленным Model, и, так как связывание происходит через View, то View обновляется тоже.


MVVM.





implicitly unwrapped

Это когда var a: Int!


frame vs bounds

frame – это прямоугольник описываемый положением location(x, y) и размерами size (width, height) вьюхи относительно ее superview в которой она содержится.

bounds – это прямоугольник описываемый положением location(x, y) и размерами size (width, height) вьюхи относительно ее собственной системы координат (0, 0).


class vs static

Такие методы зовутся методами типа. Индикатор такого метода - ключевое слово static, которое ставится до ключевого слова метода func. Классы так же могут использовать ключевое слово class, чтобы разрешать подклассам переопределение инструкций суперкласса этого метода.


Сбегающие замыкания

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



Жизненный цикл приложения

Not running (не запущенное) — приложение не было запущено или его работа была прекращена.

Inactive (неактивное) — приложение работает, но не принимает события (например, когда пользователь заблокировал телефон при запущенном приложении).

Active (активное) — нормальное состояние приложения при его работе.

Background (фоновое) — приложение больше не на дисплее, но оно все еще выполняет код.

Suspended (приостановленное) — приложение занимает память, но не выполняет код.

Scene.



UIApplicationDelegate



Жизненный цикл ViewController

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

viewDidLoad — вью создано и загружено в память, но нет bounds. Хорошее место для инициализации и настройки объектов, используемых во вью контроллере.

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

viewWillLayoutSubviews — вызывается каждый раз, когда frame изменился, например, при смене ориентации. Если вы не используете autoresizing masks или constaints, вы, вероятно, хотите обновить сабвью здесь.

viewDidLayoutSubviews — вызывается уведомить контроллер, что его вью только что залэйаутил сабвью.

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

viewWillDissapear — вью уходит с экрана. Вызывается как при закрытии вью контроллера, так и при переходе дальше по иерархии, например, при пуше нового контроллера в NavigationController

viewDidDissapear — вью ушло с экрана. Вызывается как при закрытии вью контроллера, так и при переходе дальше по иерархии.


UIViewController lifecycle



Stack Overflow.

  • Coping repository without commit history:

https://stackoverflow.com/a/37499365



GitHub.

  • Scrollview Parallax / Zoom / Stretch:

https://github.com/BillCarsonFr/ScrollviewParallax

Report Page