Академический Документы
Профессиональный Документы
Культура Документы
Циклы ссылок:
Бывают ситуации, когда два объекта больше не используются, но каждый из них
ссылается на другой. Так как у каждого счетчик ссылок не равен 0, ни один из них
не будет освобождён.
Это цикл сильных ссылок (strong reference cycle). Такая ситуация сбивает с толку
ARC и не позволяет ему очистить память.
Ссылки Weak:
Чтобы разорвать цикл сильных ссылок, вы можете обозначить отношение между
объектами как слабое (weak).
По умолчанию все ссылки являются сильными и присваивание приводит к
увеличению счётчика ссылок. При использовании слабых ссылок (weak references)
счётчик ссылок не увеличивается.
Ссылки Unowned:
Существует также другой модификатор ссылки, который не приводит к
увеличению счётчика ссылок: unowned.
Ссылка weak всегда optional и автоматически становится nil, когда ссылаемый
объект высвобождается.
Вот почему мы должны объявлять weak свойства как переменную optional типа:
это свойство должно измениться.
Ссылки Unowned, напротив, никогда не optional. Если вы попробуете получить
доступ к unowned свойству, которое ссылается на освобождённый объект, вы
получите ошибку, похожую на принудительное разворачивание содержащую nil
переменной (force unwrapping).
Списки захвата:
В Swift предусмотрен простой и элегантный способ разорвать цикл сильных
ссылок в замыканиях. Вы объявляете список захвата, в котором определяете
отношения между замыканием и объектами, которое оно захватывает.
Захвати себя:
lazy var completePhoneNumber: () -> String = { [unowned self] in return self.countryCode + " " + self.number
}
Мы добавляем [unowned self] в список захвата замыкания. Это означает, что мы
захватили self как unowned ссылку вместо сильной.
for _ in 0 ..< 5 {
autoreleasepool {
for _ in 0 ..< 1000 {
let image = NSImage(contentsOfFile: filename)
}
}
}
}
Сильные указатели похожи на поводка на собаке. Пока у вас есть привязь к собаке, собака не
убежит. Если пять человек прикрепите их привязь к одной собаке (пять сильных указателей на
один объект), то собака не убежит, пока все пять поводков не будут отсоединены.
Как только последний сильный указатель (поводок) больше не указывает на объект, объект
будет освобожден, и все слабые указатели будут обнулено.
strong(сохранить) -
@synthesize viewController;
weak -
@synthesize myButton;
Assign -
@synthesize address;
Указывает на то, что для объекта, используемого в качестве нового значения instance-
переменной, управление памятью происходит вручную (не забываем потом освободить память).
Без ARC при присваивании увеличивает счетчик ссылок объекта, т.е. ты становишься
владельцем.
retain, в отличие от copy не копирует объект при обращении к свойству, а увеличивает
счетчик использований и возвращает тот же самый объект (как бы ссылку на объект). Это нужно,
если объект большой или его не имеет смысла копировать. Например, объекты типа UIView,
UIViewController, UIWindow.
retain - передача по ссылке, copy - по значению.
Атрибут retain обеспечивает присвоение значения экземплярной переменной в порядке
retain-release.
weak
strong
Retain cycle
Цикл сохранения - это ситуация в управлении памятью с подсчетом отсчетов, когда два (или иногда более)
объекта имеют сильные ссылки друг на друга. Обычно объекты уничтожаются, когда их счетчик ссылок
достигает нуля, а ссылки, которые они удерживают, освобождаются в это время. В цикле каждый объект
удерживает другого живым, и ни один из них не будет уничтожен, если цикл не будет преднамеренно
нарушен.
class
Krake
n {
let tentacle = Tentacle() //strong reference to
child.
}
class Tentacle {
let sucker = Sucker() //strong reference to child
}
class Sucker {}
}
Здесь мы видим линейную иерархию на примере. У Kraken есть
сильная ссылка к объекту класса Tentacle, а у него самого есть
сильная ссылка к классу Sucker. Вся иерархия идет от родителя
(Kraken) вниз до дочернего объекта (Sucker).
WEAK
Слабая ссылка (weak reference) — это просто указатель на
объект, который не защищает нас от уничтожения объекта
путем ARC. Если сильные сслыки увеличивают количество
ссылок на 1, то слабые — нет. К тому же слабые ссылки
обнуляют указатель на ваш объект, когда он был успешно
удален. Это гарантирует вам, что когда вы будете обращаться
к слабой ссылки, вы получите либо правильный объект,
либо nil.
deinit {
NotificationCenter.default.removeObserver(notificationObserver)
}
}
func limbHasBeenLost() {
startCrying()
}
}
protocol LossOfLimbDelegate {
func limbHasBeenLost()
}
class Tentacle {
var delegate: LossOfLimbDelegate?
func cutOffTentacle() {
delegate?.limbHasBeenLost()
}
}
Вот почему:
И в тоже время:
UNOWNED
Поведение weak и unowned ссылок похоже, но не
одинаково. Unowned ссылки, как и weak, не увеличивают
количество retain ссылок на объект. Тем не менее в
Swift unowned ссылка имеет преимущество — она не
опциональна.
«Используйте weak ссылку, если вы знаете, что в какой-
то момент времени эта ссылка станет нулевой. И
наоборот, используйте unowned ссылку, если вы знаете,
что ссылка никогда не будет равна нулю.
Здесь хороший пример того, как класс создает retain цикл,
используя closure, который не будет nil, потому что он
получает значение в init():
class
RetainCycle
{
var closure: (() -> Void)!
var string = "Hello"
init() {
closure = {
self.string = "Hello, World!"
}
}
}
Вопрос 1
Что такое optional и какие проблемы они решают?
ответ
optional позволяет переменной любого типа представить ситуацию "отсутствие
значения". В Objective-C «отсутствие значения» было доступно только в
ссылочных типах с использованием специального значения nil. У типов-значений
(value types), вроде int или float, такой возможности не было.
Swift расширил концепцию «отсутствия значения» на типы-значения.
Переменная optionalможет содержать либо значение, либо nil, сигнализирующее
об отсутствии значения.
Вопрос 2
Коротко перечислите основные отличия между structure и class.
ответ
Классы поддерживают наследование, а структуры — нет.
Классы — ссылочный тип, структуры — тип-значение.
Вопрос 3
Что такое generics и для чего они нужны?
ответ
В Swift вы можете использовать generics в классах, структурах и перечислениях.
return x == y
areIntEqual( 1, 1) // true
return x == y
areTheyEqual( 1, 1)
Вопрос 4
В некоторых случаях не получится избежать неявного разворачивания (implicitly
unwrapped) optionals. Когда и почему?
ответ
Наиболее частые причины для использования implicitly unwrapped optionals:
Вопрос 5
Какими способами можно развернуть optional? Оцените их в смысле
безопасности.
ответ
Принудительное развёртывание (forced unwrapping) — небезопасно.
let a: String = x!
var a = x!
if let a = x {
let a = x?.count
let a = x ?? ""
Оператор Guard — безопасно.
return
if case let a? = x {
print(a)
Общие проблемы.
UI
Создать свой интерфейс можно 3-мя способами: программно, на основе маски,
которая автоматически подстраивается под изменения или использовать Auto
Layout.
Отличие Auto Layout от других способов в том, что вам больше не нужно писать
код, который изменяет интерфейс в зависимости от размера окна и других
элементов, вместо этого Auto Layout самостоятельно вычисляет расположение
элемента интерфейса в приложении и изменяет его относительно окружения.
Auto Layout занимается динамическим вычислением позиции и размера
всех view в view иерархии, на основе constraints — правил заданных для того или
иного view. Самый большой и очевидный плюс для разработчика в использовании
Auto Layout в том, что исчезает необходимость в подгонке размеров приложения
под определенные устройства — Auto Layout делает это за вас, динамически
изменяя интерфейс в зависимости от внешних или внутренних изменений.
Анатомия Constraint
Вся суть правил сводится к созданию вычисления у которого может быть только
один ответ — расположение элемента интерфейса.
Среди данных пунктов самый важный именно 2-й, так как использование этой
панели является основным инструментом при создании разметки.
Core Data
Core Data – это фреймворк, который управляет и хранит данные в приложении.
Можно рассматривать Core Data, как оболочку над физическим реляционным
хранилищем, представляющую данные в виде объектов, при этом сама Core Data
не является базой данных.
Для создания хранилища в приложении используются
классы NSPersistentStoreCoordinator или NSPersistentContainer.
NSPersistentStoreCoordinator создает хранилище указанного типа на основе
модели, можно указать размещение и дополнительные опции.
Работает это следующим образом: если по указанному пути существует база
данных, то координатор проверяет ее версию и, при необходимости, делает
миграцию. Если база не существует, то она создается на основании модели
NSManagedObjectModel.
Пример с NSPersistentStoreCoordinator
Пример с NSPersistentContainer
Core Data использует 4 типа хранилища:
— SQLite
— Binary
— In-Memory
— XML (только для Mac OS)