Swift что значит mutating

Mutating and non-mutating Swift contexts

In this article, let’s explore that keyword, as well as its nonmutating counterpart, and the sort of capabilities that those language features provide.

Swift что значит mutating. essentialDeveloper image. Swift что значит mutating фото. Swift что значит mutating-essentialDeveloper image. картинка Swift что значит mutating. картинка essentialDeveloper image

Essential Developer : Learn the most up-to-date techniques and strategies for testing new and legacy Swift code in this free practical course for developers who want to become complete senior iOS developers. This virtual event includes lectures, mentoring sessions, and step-by-step instructions. Click to learn more.

What can a mutating function do?

Essentially, a function that’s been marked as mutating can change any property within its enclosing value. The word “value” is really key here, since Swift’s concept of structured mutations only applies to value types, not to reference types like classes and actors.

For example, the following Meeting type’s cancel method is mutating, since it modifies its enclosing type’s state and reminderDate properties:

The above technique also works for other value types, such as structs, which can be really useful if we ever want to reset a value back to its default set of properties, or if we want to mutate a more complex value as a whole — for example like this:

The fact that we can assign a brand new value to self within a mutating function might initially seem a bit strange, but we have to remember that Swift structs are really just values — so just like how we can replace an Int value by assigning a new number to it, we can do the same thing with any other struct (or enum) as well.

Mutating protocol requirements

Although the concept of separating mutating and non-mutating APIs is something that’s unique to value types, we can still make a mutating function a part of a protocol as well — even if that protocol might end up being adopted by a reference type, such as a class. Classes can simply omit the mutating keyword when conforming to such a protocol, since they are inherently mutable.

What’s very interesting, though, is that if we extend a protocol with a default implementation of a mutating function, then we could implement things like the above reset API without actually knowing what type of value that we’re resetting — like this:

Performing mutations within initializers

While functions always need to be explicitly marked as mutating whenever we want to modify a value type’s internal state (whether that’s a property, or the entire value itself), initializers are always mutating by default. That means that, besides assigning initial values to a type’s properties, an initializer can also call mutating methods to perform its work (as long as self has been fully initialized beforehand).

For example, the following ProductGroup calls its own add method in order to add all of the products that were passed into its initializer — which makes it possible for us to use a single code path for that logic, regardless of whether it’s being run as part of the initialization process or not:

Non-mutating properties

So far, all of the examples that we’ve been taking a look at have been about mutable contexts, but Swift also offers a way to mark certain contexts as explicitly non-mutating as well. While the use cases for doing so are certainly more limited compared to opting into mutations, it can still be a useful tool in certain kinds of situations.

Now, if we look at the above not just as a SwiftUI view, but rather as a standard Swift struct (which it is), it’s actually quite strange that our code compiles. How come we can mutate our value property like that, within a closure, that’s not being called within a synchronous, mutable context?

The mystery continues to thicken if we then take a look at the declaration of the State property wrapper, which is also a struct, just like our view:

Although this is as far as we’re able to investigate without access to SwiftUI’s source code, State very likely uses some form of reference-based storage under the hood, which in turn makes it possible for it to opt out of Swift’s standard value mutation semantics (using the nonmutating keyword) — since the State wrapper itself is not actually being mutated when we assign a new property value.

Support Swift by Sundell by checking out this sponsor:

Swift что значит mutating. essentialDeveloper image. Swift что значит mutating фото. Swift что значит mutating-essentialDeveloper image. картинка Swift что значит mutating. картинка essentialDeveloper image

Essential Developer : Learn the most up-to-date techniques and strategies for testing new and legacy Swift code in this free practical course for developers who want to become complete senior iOS developers. This virtual event includes lectures, mentoring sessions, and step-by-step instructions. Click to learn more.

Conclusion

I hope that this article has given you a few insights into what separates a mutating context from a non-mutating one, what sort of capabilities that a mutating context actually has, and what Swift’s relatively new nonmutating keyword does.

If you have any questions, comments, or feedback, then feel free to reach out via either Twitter or email.

Thanks for reading!

More on similar topics

Auto-Equatable enums with associated values

Источник

Быстрая и изменяющаяся структура

Есть кое-что, чего я не совсем понимаю, когда дело касается изменения типов значений в Swift.

Как говорится в iBook «Язык программирования Swift»: По умолчанию свойства типа значения не могут быть изменены из его методов экземпляра.

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

Для меня не совсем ясно следующее: переменную можно изменить извне структуры, но нельзя изменить ее собственными методами. Мне это кажется нелогичным, так как в объектно-ориентированных языках вы обычно пытаетесь инкапсулировать переменные, чтобы их можно было изменять только изнутри. Со структурами, похоже, все наоборот. Чтобы уточнить, вот фрагмент кода:

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

Если значение присваивается изменяемому хранилищу (мы называем его var или переменной в Swift), вы можете изменять их состояние, и разрешается вызов метода изменения.

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

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

Для программистов на C / C ++ это тоже очень знакомая концепция. Это именно то, что const ключевое слово делает в C / C ++.

Обновить

И тогда у вас может возникнуть вопрос, почему по умолчанию используется неизменяемый? Это потому, что очень трудно предсказать будущее состояние изменяющихся значений, и это обычно становится основным источником головной боли и ошибок. Многие люди согласились с тем, что решение избегает изменяемых вещей, и тогда неизменяемость по умолчанию была на первом месте в списке желаний на протяжении десятилетий в языках семейства C / C ++ и его производных.

Надеюсь, это поможет.

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

Осторожно: условия непрофессионала впереди.

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

Поэтому я хочу попытаться просто и прямо ответить на вопрос «почему».

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

Итак, большая картина, это во многом связано с философией, которая поддерживает Swift Swift .

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

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

Приказ был: «Иди, смени свои волосы на синие и скажи мне, когда закончишь», но этот приказ получил зеленый парень. После того, как синий парень въезжает, уведомление о завершении работы все равно нужно отправить обратно. Но синий парень ничего об этом не знает.

Вот почему Swift хочет, чтобы мы использовали mutating ключевое слово!

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

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

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

РЕДАКТИРОВАТЬ:

Привет, чувак / чувак, который отверг меня, я просто полностью переписал свой ответ. Если вам так больше нравится, вы уберете отрицательный голос?

Источник

What does the Swift ‘mutating’ keyword mean?

Why must I insert mutating before implementing a method on a struct when adopting protocols?

4 Answers 4

The mutating keyword is only required if you are changing any state contained within the struct. Since Swift structs are immutable objects, calling a mutating function actually returns a new struct in-place (much like passing an inout parameter to a function). The mutating keyword lets callers know that the method is going to make the value change. The best way to conceptualize this is to think of your struct the same as you would a number: if you perform the operation 4 + 1, 4 doesn’t become 5, you’ve just gotten a new value after performing the operation. Mutating functions operate on the same principle. You cannot call mutating functions on constants (e.g. let someStruct = SomeStruct() ), because that would be the same thing as trying to assign the constant to a new value. Because of this behavior mutating functions can only be performed on variables (e.g var someStruct = SomeStruct() ).

Swift что значит mutating. Tpwfq. Swift что значит mutating фото. Swift что значит mutating-Tpwfq. картинка Swift что значит mutating. картинка Tpwfq

Being the value type structs are immutable. Meaning other variables can not change the values for instance of structure at any given point.

The mutating word is required for changing the values of self variables inside structure’s function ONLY.

Here as we are trying to change value of variable abc inside function declared in struct itself, we get the compile time error.

So here we need to make function mutating to make change value inside structure. Hence the correct code will be:

EDIT:

When declaring protocol, it can be declared commonly for reference and value types, so these kind of protocols itself declares the functions as mutating so that it can be adopted by both classes and structures.

Since being reference type the mutating keyword is removed (or we can say not required) in the classes, but for structures being value types the mutating keyword is required.

If you define a protocol instance method requirement that is intended to mutate instances of any type that adopts the protocol, mark the method with the mutating keyword as part of the protocol’s definition. This enables structures and enumerations to adopt the protocol and satisfy that method requirement.

If you mark a protocol instance method requirement as mutating, you don’t need to write the mutating keyword when writing an implementation of that method for a class. The mutating keyword is only used by structures and enumerations.

Источник

Документация

Swift что значит mutating. 400%D1%85111 2%D1%85. Swift что значит mutating фото. Swift что значит mutating-400%D1%85111 2%D1%85. картинка Swift что значит mutating. картинка 400%D1%85111 2%D1%85 Swift что значит mutating. snow 1374%D1%85182 2%D1%85. Swift что значит mutating фото. Swift что значит mutating-snow 1374%D1%85182 2%D1%85. картинка Swift что значит mutating. картинка snow 1374%D1%85182 2%D1%85

Swift что значит mutating. 684%D1%85112 2%D1%85. Swift что значит mutating фото. Swift что значит mutating-684%D1%85112 2%D1%85. картинка Swift что значит mutating. картинка 684%D1%85112 2%D1%85 Swift что значит mutating. snow 1374%D1%85182 2%D1%85. Swift что значит mutating фото. Swift что значит mutating-snow 1374%D1%85182 2%D1%85. картинка Swift что значит mutating. картинка snow 1374%D1%85182 2%D1%85

Структуры и классы

Структуры и классы

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

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

Заметка

Сравнение классов и структур

Классы и структуры в Swift имеют много общего. И в классах и в структурах можно:

Для получения дополнительной информации смотрите главы Свойства, Методы, Индексы, Инициализация, Расширения и Протоколы.

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

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

Заметка

Пример определения структуры и класса:

Экземпляры класса и структуры

Объявление структуры Resolution и класса VideoMode только описывают как Resolution и VideoMode будут выглядеть. Сами по себе они не описывают специфическое разрешение или видеорежим. Для того чтобы это сделать нам нужно создать экземпляр структуры или класса.

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

Доступ к свойствам

Вы можете углубиться в подсвойства, например, свойство width свойства resolution класса VideoMode :

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

Поэлементные инициализаторы структурных типов

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

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

Заметка

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

Рассмотрим пример, который использует структуру Resolution из предыдущего примера:

Однако свойство width исходного hd экземпляра осталось 1920 :

То же поведение применимо к перечислениям:

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

Следующее, что мы сделаем, это tenEighty присвоим новой константе alsoTenEighty и изменим частоту кадров:

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

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

Иногда бывает полезно выяснить ссылаются ли две константы или переменные на один и тот же экземпляр класса. Для проверки этого в Swift есть два оператора тождественности:

Можно использовать эти операторы для проверки того, ссылаются ли две константы или переменные на один и тот же экземпляр:

Обратите внимание, что «идентичность» (в виде трех знаков равенства, или === ) не имеет в виду «равенство» (в виде двух знаков равенства, или == ). Идентичность или тождественность значит, что две константы или переменные ссылаются на один и тот же экземпляр класса. Равенство значит, что экземпляры равны или эквивалентны в значении в самом обычном понимании «равны».

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

Указатели

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Источник

Продвинутая интерполяция строк в Swift 5.0

Swift что значит mutating. image loader. Swift что значит mutating фото. Swift что значит mutating-image loader. картинка Swift что значит mutating. картинка image loader

Интерполяция строк была в Swift с ранних версий, но в Swift 5.0 этот функционал был расширен, стал быстрее и значительно мощнее.

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

Основы

Мы используем базовую интерполяцию строк вот так:

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

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

Да, конечный результат был бы тем же, но Swift пришлось бы добавить s1 к s2 чтобы получить s5, добавить s5 к s3 чтобы получить s6, и добавить s6 к s4 чтобы получить s7, перед присвоением all.

Интерполяция строк практически не менялась со Swift 1.0, единственное значимое изменение пришло вместе с Swift 2.1, где мы получили возможность использовать в интерполяции string literals:

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

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

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

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

Но что, если мы хотим отформатировать результат как-то по-другому?

Используя новую систему интерполяции строк в in Swift 5.0 мы можем написать экстеншн String.StringInterpolation, чтобы добавить свой собственный метод интерполяции:

Теперь код выведет целую переменную как текст: “Hi, I’m thirty-eight.”

Мы можем использовать похожую технику чтобы поправить форматирование даты, поскольку вид даты по умолчанию в виде string не слишком привлекателен:

Вы увидите, что Swift выведет текущую дату в виде что-то вроде: “2019-02-21 23:30:21 +0000”. Мы можем сделать это красивее используя своё собственное форматирование даты:

Теперь результат выглядит гораздо лучше, что-то вроде: “February 21, 2019 23:30:21”.

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

Теперь мы вызовем этот метод с именованным параметром:

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

Интерполяция с параметрами

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

Например, мы можем переписать код, чтобы обрабатывать сообщения в Twitter:

Теперь мы можем написать так:

Но зачем нам ограничиваться одним параметром? Для нашего примера форматирования числа нет никакого смысла принуждать пользователей использовать один параметр конвертирования (.spellOut) — так что мы изменим метод, добавив второй параметр:

И используем его так:

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

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

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

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

Erica Sadun предложила по-настоящему короткий и красивый пример того, как можно упростить код:

Добавление интерполяции строк для пользовательских типов

Мы можете использовать интерполяцию строк для своих собственных типов:

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

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

Конечно же, вы можете использовать все возможности Swift, чтобы создать своё собственное форматирование. Например, мы можем написать реализацию, которая принимает любой объект Encodable и выводит его в JSON:

Если мы сделаем Person соответствующим протоколу Encodable, то мы можем сделать так:

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

Всё, что мы до сих пор рассматривали — это просто модификации способов интерполяции строк.

Создание собственных типов при помощи интерполяции

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

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

На самом деле, под капотом тут один синтаксический сахар. Заключительную часть мы вполне могли бы написать вручную:

Заключение

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

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *