Swift как работает память

Обновлено: 04.07.2024

в частности, как Swift управление памятью работает с optionals с использованием шаблона делегата?

привыкнув писать шаблон делегата в Objective-C, мой инстинкт-сделать делегата weak . Например, в Objective-C:

однако, делать это в Swift не так прямолинейно.

если мы имеем как раз нормальный смотря протокол:

мы не можем объявить переменные этого типа как слабый:

"слабый" не может быть применен к неклассовому типу "FooDelegate"

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

что позволяет нам использовать weak , но не позволяет нам использовать structs или enums .

если я не сделаю свой протокол протоколом класса, и поэтому не используйте weak для моей переменной я создаю цикл сохранения, правильно?

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

я в первую очередь спрашиваю, потому что в разделе делегации официальная документация Apple по протоколам Swift, они предоставляют пример неклассового протокола и не слабой переменной, используемой как делегат их класса:

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

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

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

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

Да, этот пример немного странный.

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

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

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

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

если вы должны иметь structs и emums в вашем протоколе, тогда, если вы сделаете свой делегат nil перед тем, как закрыть контроллер вида, это прерывает цикл сохранения. Я проверил это в документах.

Swift — это надёжный и интуитивно понятный язык программирования от Apple, при помощи которого можно создавать приложения для iOS, Mac, Apple TV и Apple Watch. Он предоставляет разработчикам небывалую свободу творчества. Благодаря этому простому и удобному языку с открытым кодом вам достаточно просто интересной идеи, чтобы создать нечто невероятное.

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

Swift — это быстрый и эффективный язык программирования с откликом в реальном времени, который легко можно вставить в готовый код Objective-C. Теперь разработчики могут не только писать более надёжные и безопасные коды, но также экономить время и создавать приложения с расширенными возможностями.

Прекрасное приложение в Swift. Простота использования и отклик в реальном времени — вот почему VSCO выбрали Swift, чтобы создать новую версию своего фотоприложения для iOS.

Превосходные приложения,
разработанные на языке Swift.

Всё больше разработчиков встраивают код Swift в свои приложения. А некоторые даже создают в Swift совершенно новые приложения.

Производительность выше. Приложения лучше.

Приложения Swift превосходят ожидания. Например, обычный алгоритм поиска выполняется в Swift гораздо быстрее.

В графе с использованием алгоритма поиска в глубину найдено 10 000 целых чисел*

Язык Swift добавлен
в учебную программу.

Потенциал Swift оценили учебные заведения по всему миру. Они используют Swift и Xcode на Mac для обучения, обеспечивая своих студентов лучшими инструментами для создания приложений. А с бесплатной учебной программой от Apple «Разработка на языке Swift» даже новички легко переходят от основ программирования к профессиональной разработке.

Университеты, включившие язык Swift в учебную программу

  • Калифорнийский университет в Санта-Круз
  • Колледж Футхилл
  • Мельбурнский королевский технологический университет
  • Мюнхенский технический университет
  • Общественный колледж Лосон
  • Общественный колледж Манхэттена
  • Общественный колледж Месы
  • Общественный колледж Хьюстона
  • Общественный колледж Централ Пьемонт
  • Плимутский университет
  • Политехнический университет штата Калифорния
  • Стэнфордский университет
  • Технический колледж северо-западного Канзаса
  • Технологический институт Монтеррея
  • Университет Аберистуита
  • Университет Фулл Сейл
  • Школа Ingésup
  • Южный методистский университет

Swift повсюду.
И теперь открыт для всех.

Swift бесплатно доступен для использования разработчиками, преподавателями и студентами по лицензии на распространение ПО с открытым исходным кодом Apache 2.0. Мы предоставляем двоичные файлы для OS X и Linux, которые позволяют компилировать код для iOS, OS X, watchOS, tvOS и Linux. А чтобы ускорить развитие и превращение Swift в ещё более мощный язык, мы создали новое сообщество, где пользователи могут напрямую вносить свой вклад в исходный код Swift.

Познакомьтесь со Swift.

Главная книга

Загрузите учебник Язык программирования Swift из Apple Books Store бесплатно. Узнайте, как благодаря Swift процесс программирования становится более удобным, гибким и увлекательным.

Xcode

Xcode — это приложение для Mac, предназначенное для разработки других приложений для Mac и iOS. В Xcode есть все инструменты, необходимые для создания потрясающих приложений. Его можно загрузить бесплатно из Mac App Store.

Веб-сайт для разработчиков

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

Оператор является специальным символом или фразы , которую вы используете , чтобы проверить, изменить или скомбинировать значение. Например, оператор сложения ( + ) добавляет два числа, как в , а логический оператор И ( ) объединяет два логических значения, как в . let i = 1 + 2 && if enteredDoorCode && passedRetinaScan

Swift поддерживает большинство стандартных операторов C и улучшает некоторые возможности для устранения распространенных ошибок кодирования. Оператор присваивания ( = ) не возвращает значение, чтобы предотвратить его ошибочное использование, когда == предполагается, что равно operator ( ). Арифметические операторы ( + , - , * , / , % и т.д.) обнаружить и запретить переполнение значения, чтобы избежать неожиданных результатов при работе с числами , которые становятся больше или меньше , чем диапазон допустимого значения типа , который хранит их. Вы можете выбрать поведение переполнения, используя операторы переполнения Swift, как описано в разделе «Операторы переполнения» .

Swift также предоставляет операторы диапазона, которых нет в C, такие как a..<b и a. b , в качестве ярлыка для выражения диапазона значений.

В этой главе описываются общие операторы в Swift. Расширенные операторыохватывают расширенные операторы Swift и описывают, как определять свои собственные пользовательские операторы и реализовывать стандартные операторы для собственных пользовательских типов.

Терминология

Операторы унарные, двоичные или троичные:

  • Унарные операторы работают на одну цель (например, -a ). Унарные префиксныеоператоры появляются непосредственно перед их целью (например !b ), а унарные постфиксные операторы появляются сразу после их цели (например c! ).
  • Бинарные операторы работают с двумя целями (такими как ) и являются инфиксными, потому что они появляются между двумя целями. 2 + 3
  • Тернарные операторы работают на три цели. Как и C, Swift имеет только один троичный оператор - троичный условный оператор ( ). a ? b : c

Значения, на которые влияют операторы, являются операндами . В выражении , то символ является бинарным оператором и его два операнда являются значениями и . 1 + 2 + 1 2

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

Оператор присваивания ( ) инициализирует или обновляет значение со значением : a = b a b

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

В отличие от оператора присваивания в C и Objective-C, оператор присваивания в Swift сам по себе не возвращает значение. Следующее утверждение недопустимо:

Эта функция предотвращает = случайное использование оператора присваивания ( ), когда == фактически предполагается равенство с оператором ( ). Делая недействительным, Swift помогает вам избежать подобных ошибок в вашем коде. if x = y

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

Swift поддерживает четыре стандартных арифметических оператора для всех типов чисел:

  • Дополнение ( + )
  • Вычитание ( - )
  • Умножение ( * )
  • Отдел ( / )

В отличие от арифметических операторов в C и Objective-C, арифметические операторы Swift не допускают переполнения значений по умолчанию. Вы можете выбрать поведение переполнения, используя операторы переполнения Swift (например, ). Смотрите Операторы переполнения . a &+ b

Оператор сложения также поддерживается для String объединения:

Оставшийся оператор

Оператор remainder ( ) определяет, сколько крат будет помещаться внутри, и возвращает оставшееся значение (известное как остаток ). a % b b a

ЗАМЕТКА

Оператор остатка ( % ) также известен как оператор по модулю в других языках. Однако его поведение в Swift для отрицательных чисел означает, что, строго говоря, это остаток, а не операция по модулю.

Вот как работает оператор остатка. Чтобы рассчитать , вы сначала определите, сколько s поместится внутри : 9 % 4 4 9

Вы можете поместить два 4 s внутри 9 , а остальное 1 (показано оранжевым цветом).

В Swift это будет записано как:

Чтобы определить ответ для , оператор вычисляет следующее уравнение и возвращает его результат: a % b % remainder

a = ( b х ) + some multiplier remainder

где наибольшее число, кратное тому, что поместится внутри . some multiplier b a

Вставка 9 и 4 в это уравнение дает:

Тот же метод применяется при расчете остатка для отрицательного значения a :

Вставка -9 и 4 в уравнение дает:

давая остаток стоимости -1 .

Знак b игнорируется для отрицательных значений b . Это значит, что и всегда дают один и тот же ответ. a % b a % -b

Унарный минус оператор

Знак числового значения можно переключать с помощью префикса - , известного как унарный оператор минус :

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

Унар Плюс Оператор

Унарный плюс ( + ) просто возвращает значение, которое действует на, без каких - либо изменений:

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

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

Как и C, Swift предоставляет составные операторы присваивания, которые комбинируют метод assign ( = ) с другой операцией. Одним из примеров является оператор присваивания ( += ):

Выражение является сокращением для . По сути, сложение и назначение объединяются в одного оператора, который выполняет обе задачи одновременно. a += 2 a = a + 2

ЗАМЕТКА

Составные операторы присваивания не возвращают значение. Например, вы не можете писать . let b = a += 2

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

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

Swift поддерживает все стандартные операторы сравнения C :

  • Равно ( ) a == b
  • Не равно ( ) a != b
  • Больше чем ( ) a > b
  • Меньше чем ( ) a < b
  • Больше или равно ( ) a >= b
  • Меньше или равно ( ) a <= b

ЗАМЕТКА

Swift также предоставляет два идентификатора оператора ( === и !== ), которые вы используете, чтобы проверить, ссылаются ли обе ссылки на один и тот же экземпляр объекта. Для получения дополнительной информации см. Identity Operators .

Каждый из операторов сравнения возвращает Bool значение, чтобы указать, верно ли утверждение:

Операторы сравнения часто используются в условных выражениях, таких как if :

Для получения дополнительной информации об if операторе см. Поток управления .

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

В приведенном выше примере вы можете увидеть поведение сравнения слева направо в первой строке. Потому 1 что меньше чем 2 , считается меньше чем , независимо от любых других значений в кортежах. Неважно, что это не меньше , потому что сравнение уже определяется первыми элементами кортежей. Однако, когда первые элементы кортежей являются одинаковыми, их вторые элементы имеют по сравнению, это то , что происходит на второй и третьей линии. (1, "zebra") (2, "apple") "zebra" "apple"

Кортежи можно сравнивать с данным оператором, только если оператор можно применить к каждому значению в соответствующих кортежах. Например, как показано в приведенном ниже коде, вы можете сравнить два кортежа типа, так как и значения, и значения можно сравнить с помощью оператора. Напротив, два кортежа типа не могут сравниваться с оператором, потому что оператор не может быть применен к значениям. (String, Int) String Int < (String, Bool) < < Bool

ЗАМЕТКА

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

Тернарный условный оператор

Тройной условный оператор является специальным оператором с тремя частями, который принимает форму . Это ярлык для оценки одного из двух выражений в зависимости от того, является ли оно истинным или ложным. Если это правда, он оценивает и возвращает свое значение; в противном случае он оценивает и возвращает свое значение. question ? answer1 : answer2 question question answer1 answer2

Тернарный условный оператор является сокращением для кода ниже:

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

Пример выше является сокращением для кода ниже:

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

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

Ноль-коалесцирующий оператор

Оператор nil- coalescing ( ) разворачивает необязательное значение, если оно содержит значение, или возвращает значение по умолчанию, если оно есть . Выражение всегда имеет необязательный тип. Выражение должно соответствовать типу, который хранится внутри . a ?? b a b a nil a b a

Оператор nil-coalescing является сокращением для кода ниже:

Приведенный выше код использует троичный условный оператор и принудительный unwrapping ( a! ) для доступа к значению, заключенному внутри, a когда a его нет nil , и для возврата в b противном случае. Оператор nil-coalescing предоставляет более элегантный способ инкапсулировать эту условную проверку и развертывание в сжатой и читаемой форме.

ЗАМЕТКА

Если значение не a является nil , значение b не оценивается. Это известно как оценка короткого замыкания .

В приведенном ниже примере оператор nil-coalescing выбирает имя цвета по умолчанию и необязательное имя цвета, определяемое пользователем:

userDefinedColorName Переменная определяется как необязательный String , со значением по умолчанию nil . Поскольку userDefinedColorName это необязательный тип, вы можете использовать оператор nil-coalescing, чтобы рассмотреть его значение. В приведенном выше примере оператор используется для определения начального значения для String вызываемой переменной colorNameToUse . Потому userDefinedColorName что nil , выражение возвращает значение или . userDefinedColorName ?? defaultColorName defaultColorName "red"

Если вы назначите ненулевое nil значение и снова userDefinedColorName выполните проверку оператора nil-coalescing, userDefinedColorName вместо значения по умолчанию используется значение, заключенное внутри :

Операторы диапазона

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

Закрытый оператор

Диапазон оператор замкнутого ( a. b ) определяет диапазон , который проходит от a до b , и включает в себя значения a и b . Значение a не должно быть больше чем b .

Оператор закрытого диапазона полезен при итерации по диапазону, в котором вы хотите использовать все значения, например, с циклом for - in :

Более подробную информацию о for - in петлями см Flow Control .

Оператор полуоткрытого диапазона

Оператор полуоткрытого диапазона ( a..<b ) определяет диапазон, который работает от a до b , но не включает в себя b . Говорят, что он наполовину открыт, потому что содержит его первое значение, но не его окончательное значение. Как и в случае с оператором закрытого диапазона, значение a не должно быть больше, чем b . Если значение a равно b , то результирующий диапазон будет пустым.

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

Обратите внимание, что массив содержит четыре элемента, но 0..<count считается только до 3 (индекс последнего элемента в массиве), потому что это полуоткрытый диапазон. Для получения дополнительной информации о массивах см. Массивы .

Односторонние ряды

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

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

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

Логические операторы изменяют или объединяют значения логической логики true и false . Swift поддерживает три стандартных логических оператора в языках на основе C:

  • Логическое НЕ ( !a )
  • Логическое И ( ) a && b
  • Логическое ИЛИ ( ) a || b

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

Логический оператор НЕ ( !a ) инвертирует логическое значение , таким образом , что true становится false , и false становится true .

Логический оператор NOT является префиксным оператором и появляется непосредственно перед значением, с которым он работает, без пробелов. Его можно прочитать как «нет a », как показано в следующем примере:

Фраза может быть прочитана как «если недопустимая запись». Следующая строка выполняется только в том случае, если «недопустимая запись» имеет значение true; если есть . if !allowedEntry allowedEntry false

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

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

Логический оператор ( ) создает логические выражения , где оба значения должны быть для всего выражения также быть . a && b true true

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

В этом примере рассматриваются два Bool значения и разрешается доступ только в том случае, если оба значения true :

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

Оператор логического ИЛИ ( ) - это инфиксный оператор, состоящий из двух соседних символов канала. Вы используете его для создания логических выражений, в которых должно быть только одно из двух значений для общего выражения . a || b true true

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

В приведенном ниже примере первое Bool значение ( hasDoorKey ) есть false , а второе значение ( knowsOverridePassword ) есть true . Поскольку одно значение - true общее выражение также оценивается true , и доступ разрешен:

Объединение логических операторов

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

В этом примере используются несколько операторов && и || операторы для создания более длинного составного выражения. Тем не менее, && и || операторы по- прежнему работают только два значения, так что это на самом деле три меньших выражения прикован вместе. Пример можно прочитать как:

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

На основании значений enteredDoorCode , passedRetinaScan и hasDoorKey первые два подвыражения false . Однако пароль аварийного переопределения известен, поэтому общее составное выражение все равно оценивается как true .

ЗАМЕТКА

Логические операторы Swift && и || являются левоассоциативными, это означает, что составные выражения с несколькими логическими операторами сначала оценивают крайнее левое подвыражение.

Явные круглые скобки

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

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

В частности, как управление памятью Swift работает с дополнительными параметрами с использованием шаблона делегата?

Поскольку я привык писать шаблон делегата на Objective-C, мой инстинкт состоит в том, чтобы сделать делегата weak . Например, в Objective-C:

Однако сделать это в Swift не так просто.

Если у нас просто нормальный протокол:

Мы не можем объявить переменные этого типа слабыми:

'weak' не может применяться к типу, не являющемуся классом 'FooDelegate'

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

Что позволяет нам использовать weak , но не позволяет нам использовать structs или enums .

Если я не делаю свой протокол протоколом класса и, следовательно, не использую weak для моей переменной, я создаю цикл сохранения, правильно?

Есть ли вообразимая причина, по которой любой протокол, предназначенный для использования в качестве протокола делегата, не должен быть протоколом класса, чтобы переменные этого типа могли быть weak ?

Я в первую очередь спрашиваю, потому что в разделе делегирования официальная документация Apple по протоколам Swift, они предоставляют пример протокола, не относящегося к классу, и неслабой переменной, используемой в качестве делегата для их класса:

Следует ли нам воспринимать это как намек на то, что Apple считает, что мы должны использовать структуры в качестве делегатов? Или это просто плохой пример, и реально протоколы делегатов должны быть объявлены как протоколы только для классов, чтобы делегированный объект мог содержать слабую ссылку на своего делегата?

3 ответа

Следует ли нам воспринимать это как намек на то, что Apple считает, что мы должны использовать структуры в качестве делегатов? Или это просто плохой пример, и реально протоколы делегатов должны быть объявлены как протоколы только для классов, чтобы делегированный объект мог содержать слабую ссылку на своего делегата?

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

Итак, в реальном мире фреймворка Какао существует серьезная опасность неправильного владения или цикла сохранения. И это проблема, которую решает weak . Но работает, как вы правильно сказали, только с классами.

Однако пример в книге касается некоторых объектов, живущих в абстрактном искусственном мире, созданном только для Swift. В этом мире, пока вам не угрожает замкнутость (цикл сохранения), нет причин не использовать структуры и нет причин беспокоиться об управлении памятью. Но этот мир - не тот мир, в котором вы обычно будете программировать! И этот мир не является миром какао фреймворка, из которого исходит ваш шаблон делегата Objective-C и которому он принадлежит.

Если у вас должны быть structs и emums в вашем протоколе, то, если вы сделаете свой делегат nil непосредственно перед закрытием контроллера представления, это прервет цикл сохранения. Я проверил это в разделе "Распределение по инструментам".

Это необязательно, так что это действительно так.

Да, этот пример немного странный.

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

Это не приводит к циклу ссылок в данном случае , потому что DiceGameTracker - это вымышленный объект, которому не принадлежит сам DiceGame , но в реальном приложении возможно, даже вероятно, что делегат также может быть владельцем делегирующего объекта. (Например, контроллер представления может владеть DiceGame и реализовывать DiceGameDelegate , чтобы он мог обновлять свой пользовательский интерфейс в ответ на игровые события.)

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

Реально можно было бы ожидать, что для реализации этого в любом случае будут использоваться ссылочные типы (классы), даже если объявление протокола оставляет открытой возможность сделать это в противном случае. Даже в гипотетическом мире только для Swift, вероятно, имеет смысл сделать это таким образом . как правило, когда у вас есть что-то с долгим сроком службы, внутренним изменяемым состоянием и шаблоном использования, к которому обращается потенциально несколько других субъектов, вы хотите тип класса, даже если вы можете сортировать подделку, иначе с типами значений и var .

Читайте также: