Официальное руководство swift

Documentation

If you are new to Swift, you may want to check out these additional resources.

  • Getting started guide
  • Swift resources at Apple.com

Swift Language

The Swift Programming Language Book

The Swift Programming Language is the authoritative reference for Swift,
offering a guided tour, a comprehensive guide, and a formal reference of the language.

Translations

We encourage you to participate in translating The Swift Programming Language into other languages.
Get involved with an existing translation project, or start a new one.

  • Read Chinese translation
  • Read Japanese translation
  • Read Korean translation
  • Read Spanish translation
  • Read Ukrainian translation

If you know of a quality translation project underway,
please let us know on the Compiler Development forums,
and we’ll provide a link to that project on this page.

Standard Library

The Swift standard library defines a base layer of functionality for writing Swift programs. Documentation for the standard library is presently hosted on the Apple Developer website.

Packages

There are a number of packages that are part of the core Swift project. Below is a list of packages that currently offer hosted documentation.

Swift-DocC

DocC is a documentation compiler that makes it easy for you to produce documentation for your Swift frameworks and packages. The compiler builds your documentation by combining the comments you write in source with extension files, articles, and tutorials that live alongside your package’s source code. This documentation is for using the DocC tool to generate documentation for your project.

API Design Guidelines

Delivering a clear, consistent developer experience when writing Swift code is largely defined by the names and idioms that appear in APIs. These design guidelines explain how to make sure that your code feels like a part of the larger Swift ecosystem.

Swift Package Manager

The Swift Package Manager is a tool for managing the distribution and use of “packages” of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies into target products.

Migration Guidelines

For users of Xcode, there is an included Swift migrator tool that helps you move your project to the latest version of Swift, or update it to work with the latest SDKs.

  • Migrating to Swift 5
  • Migrating to Swift 4.2

nullДанная документация является переводом официальной книги «Swift Programming Language» от Apple. Работа была проделана профессионалами, но в связи с огромным объемом текста и постоянным обновлением книги, мы не исключаем незначительных ошибок. Если вы вдруг обнаружили то, что на ваш взгляд нуждается в корректировке, то напишите нам об этом либо в комментариях, либо на почту и мы обязательно примем это во внимание. Кроме того, мы стараемся постоянно обновлять документацию, как только выходят официальные правки английского варианта книги. В конечном итоге, нашей целью является создание качественного и постоянно обновляемого источника информации о языке Swift.

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

Если вам нужно быстро пройтись по возможностям языка, то начните с главы «Знакомство со Swift». Если же требуется углубиться в Swift, пропустите главу «Знакомство со Swift» и сразу начинайте читать с главы «Основы».

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

Documentation Index

This page describes the overall organization of documentation for the Swift toolchain.
It is divided into the following sections:

  • Tutorials
    gently guide you towards achieving introductory tasks,
    while assuming minimal background knowledge.
  • How-To Guides
    help you complete specific tasks in a step-by-step fashion.
  • Explanations
    discuss key subsystems and concepts, at a high level.
    They also provide background information and talk about design tradeoffs.
  • Reference Guides
    contain a thorough technical reference for complex topics.
    They assume some overall understanding of surrounding subsystems.
  • Recommended Practices
    suggests guidelines for writing code and diagnostics.
  • Project Information
    tracks continuous integration (CI), branching and release history.
  • Evolution Documents
    includes proposals and manifestos for changes to Swift.
  • The External Resources section provides links to
    valuable discussions about Swift development, in the form of talks
    and blog posts.
  • The Uncategorized section is for documentation which does
    not fit neatly into any of the above categories. We would like to minimize
    items in this section; avoid adding new documentation here.

Sometimes documentation is not enough.
Especially if you are a new contributor, you might run into roadblocks
which are not addressed by the existing documentation.
Or they are addressed somewhere but you cannot find the relevant bits.
If you are stuck, please use the development category on the Swift forums
to ask for help!

Lastly, note that we are slowly moving towards a more structured form of
documentation, inspired by the Django project [1]
[2]. Hence parts of this page are aspirational
and do not reflect how much of the existing documentation is written.
Pull requests to clean up the Uncategorized section,
or generally fill gaps in the documentation are very welcome.
If you would like to make major changes, such as adding entire new pieces of
documentation, please create a thread on the Swift forums under the
development category to discuss your proposed changes.

Tutorials

  • libFuzzerIntegration.md:
    Using libFuzzer to fuzz Swift code.

How-To Guides

  • FAQ.md:
    Answers «How do I do X?» for a variety of common tasks.
  • FirstPullRequest.md:
    Describes how to submit your first pull request. This is the place to start
    if you’re new to the project!
  • GettingStarted.md:
    Describes how to set up a working Swift development environment
    for Linux and macOS, and get an edit-build-test-debug loop going.
  • DebuggingTheCompiler.md:
    Describes a variety of techniques for debugging.
  • Building for Android:
    • Android.md:
      How to run some simple programs and the Swift test suite on an Android device.
    • AndroidBuild.md:
      How to build the Swift SDK for Android on Windows.
  • Building for Windows:
    • Windows.md:
      Overview on how to build Swift for Windows.
    • WindowsBuild.md:
      How to build Swift on Windows using Visual Studio.
    • WindowsCrossCompile.md:
      How to cross compile Swift for Windows on a non-Windows host OS.
  • Building for OpenBSD:
    • OpenBSD.md:
      Overview of specific steps for building on OpenBSD.
  • RunningIncludeWhatYouUse.md:
    Describes how to run include-what-you-use
    on the Swift project.

Explanations

  • WebAssembly.md:
    Explains some decisions that were made while implementing the WebAssembly target.

Compiler and Runtime Subsystems

  • Driver:
    • Driver.md:
      Provides an overview of the driver, compilation model, and the compiler’s
      command-line options. Useful for integration into build systems other than
      SwiftPM or Xcode.
    • DriverInternals.md:
      Provides a bird’s eye view of the driver’s implementation.

  • DependencyAnalysis.md:
    Describes different kinds of dependencies across files in the same module,
    important for understanding incremental builds.
  • DifferentiableProgrammingImplementation.md:
    Describes how automatic differentiation is implemented in the Swift compiler.
  • C and ObjC interoperability: Clang Importer and PrintAsClang
    • CToSwiftNameTranslation.md:
      Describes how C and ObjC entities are imported into Swift
      by the Clang Importer.
    • CToSwiftNameTranslation-OmitNeedlessWords.md:
      Describes how the «Omit Needless Words» algorithm works,
      making imported names more idiomatic.
  • Type-checking and inference:
    • TypeChecker.md:
      Provides an overview of how type-checking and inference work.
    • RequestEvaluator.md:
      Describes the request evaluator architecture, which is used for
      lazy type-checking and efficient caching.
    • Literals.md:
      Describes type-checking and inference specifically for literals.
  • Serialization.md:
    Gives an overview of the LLVM bitcode format used for swiftmodules.

    • StableBitcode.md:
      Describes how to maintain compatibility when changing the serialization
      format.
  • SIL and SIL Optimizations:
    • SILFunctionConventions.md:
    • SILMemoryAccess.md:
    • SILProgrammersManual.md:
      Provides an overview of the implementation of SIL in the compiler.
    • OptimizerDesign.md:
      Describes the design of the optimizer pipeline.
    • HighLevelSILOptimizations.rst:
      Describes how the optimizer understands the semantics of high-level
      operations on currency data types and
      optimizes accordingly.
      Includes a thorough discussion of the @_semantics attribute.
  • Runtime specifics:
    • Backtracing.rst:
      Describes Swift’s backtracing and crash catching support.

SourceKit subsystems

  • SwiftLocalRefactoring.md:
    Describes how refactorings work and how they can be tested.

Language subsystems

  • Swift’s Object Model
    • LogicalObjects.md:
      Describes the differences between logical and physical objects and
      introduces materialization and writeback.
    • MutationModel.rst: Outdated.
  • DocumentationComments.md:
    Describes the format of Swift’s documentation markup, including
    specially-recognized sections.

Stdlib Design

  • SequencesAndCollections.rst:
    Provides background on the design of different collection-related protocols.
  • StdlibRationales.rst:
    Provides rationale for common questions/complaints regarding design decisions
    in the Swift stdlib.

Reference Guides

  • DriverParseableOutput.md:
    Describes the output format of the driver’s -parseable-output flag,
    which is suitable for consumption by editors and IDEs.
  • ObjCInterop.md
    Documents how Swift interoperates with ObjC code and the ObjC runtime.
  • LibraryEvolution.rst:
    Specifies what changes can be made without breaking binary compatibility.
  • SIL.rst:
    Documents the Swift Intermediate Language (SIL).

    • TransparentAttr.md:
      Documents the semantics of the @_transparent attribute.
  • DynamicCasting.md:
    Behavior of the dynamic casting operators is, as?, and as!.
  • Runtime.md:
    Describes the ABI interface to the Swift runtime.

  • Lexicon.md:
    Canonical reference for terminology used throughout the project.
  • UnderscoredAttributes.md:
    Documents semantics for underscored (unstable) attributes.

ABI

  • CallConvSummary.rst:
    A concise summary of the calling conventions used for C/C++, Objective-C
    and Swift on Apple platforms. Contains references to source documents,
    where further detail is required.
  • CallingConvention.rst:
    Describes in detail the Swift calling convention.
  • GenericSignature.md:
    Describes what generic signatures are and how they are used in the ABI,
    including the algorithms for minimization and canonicalization.
  • KeyPaths.md:
    Describes the layout of key path objects (instantiated by the runtime,
    and therefore not strictly ABI).
    TODO: The layout of key path patterns (emitted by the compiler,
    to represent key path literals) isn’t documented yet.
  • Mangling.rst:
    Describes the stable mangling scheme, which produces unique symbols for
    ABI-public declarations.
  • TypeLayout.rst:
    Describes the algorithms/strategies for fragile struct and tuple layout;
    class layout; fragile enum layout; and existential container layout.
  • TypeMetadata.rst:
    Describes the fields, values, and layout of metadata records, which can be
    used (by reflection and debugger tools) to discover information about types.

Recommended Practices

Coding

  • AccessControlInStdlib.md:
    Describes the policy for access control modifiers and related naming
    conventions in the stdlib.

  • IndexInvalidation.md:
    Describes the expected behavior of indexing APIs exposed by the stdlib.
  • StdlibAPIGuidelines.rst:
    Provides guidelines for designing stdlib APIs.

  • StandardLibraryProgrammersManual.md:
    Provides guidelines for working code in the stdlib.
  • OptimizationTips.rst:
    Provides guidelines for writing high-performance Swift code.

Diagnostics

Project Information

  • Branches.md:
    Describes how different branches are setup and what the automerger does.
  • ContinuousIntegration.md:
    Describes the continuous integration setup, including the @swift_ci bot.

Evolution Documents

Manifestos

  • ABI Stability and Library Evolution
    • ABIStabilityManifesto.md:
      Describes the goals and design for ABI stability.
    • LibraryEvolutionManifesto.md:
      Describes the goals and design for Library Evolution.
  • BuildManifesto.md:
    Provides an outline for modularizing the build system for the Swift toolchain.
  • CppInteroperabilityManifesto.md:
    Describes the motivation and design for first-class Swift-C++ interoperability.
  • DifferentiableProgramming.md:
    Outlines a vision and design for first-class differentiable programming in Swift.
  • GenericsManifesto.md:
    Communicates a vision for making the generics system in Swift more powerful.
  • OwnershipManifesto.md:
    Provides a framework for understanding ownership in Swift,
    and highlights potential future directions for the language.
  • StringManifesto.md:
    Provides a long-term vision for the String type.

Proposals

Old proposals are present in the /docs/proposals directory.
More recent proposals are located in the apple/swift-evolution repository.
You can see the status of different proposals at
https://apple.github.io/swift-evolution/.

Surveys

  • CallingConvention.rst:
    This whitepaper discusses the Swift calling convention (high-level semantics;
    ownership transfer; physical representation; function signature lowering).
  • ErrorHandlingRationale.md:
    Surveys error-handling in a variety of languages, and describes the rationale
    behind the design of error handling in Swift.
  • WeakReferences.md:
    Discusses weak references, including the designs in different languages,
    and proposes changes to Swift (pre-1.0).

Archive

These documents are known to be out-of-date and are superseded by other
documentation, primarily The Swift Programming Language (TSPL).
They are preserved mostly for historical interest.

  • AccessControl.md
  • Arrays.md
  • Generics.rst
  • ErrorHandling.md
  • StringDesign.rst
  • TextFormatting.rst

External Resources

External resources are listed in ExternalResources.md.
These cover a variety of topics,
such as the design of different aspects of the Swift compiler and runtime
and contributing to the project more effectively.

Uncategorized

Needs refactoring

The documents in this section might be worth breaking up into several documents,
and linking one document from the other. Breaking up into components will
provide greater clarity to contributors wanting to add new documentation.

  • ARCOptimization.md:
    Covers how ARC optimization works, with several examples.
    TODO: Not clear if this is intended to be an explanation or a reference guide.
  • CompilerPerformance.md:
    Thoroughly discusses different ways of measuring compiler performance
    and common pitfalls.
    TODO: Consider breaking up into one high-level explanation explaining key
    concepts and individual how-to guides that can be expanded independently.
    Also, it’s not the right place to explain details of different compiler modes.
  • DevelopmentTips.md:
    Contains an assortment of tips for better productivity when working on the
    compiler.
    TODO: Might be worthwhile to make a dedicated how-to guide or explanation.
    It might also be valuable to introduce the tips in context, and have the
    explanation link to all the different tips.
  • Diagnostics.md:
    Describes how to write diagnostic messages and associated educational notes.
    TODO: Consider splitting into how-tos and recommended practices.
    For example, we could have a how-to guide on adding a new diagnostic,
    and have a recommended practices page which explains the writing style
    for diagnostics and educational notes.
  • HowSwiftImportsCAPIs.md:
    Contains a thorough description of the mapping between C/ObjC entities and
    Swift entities.
    TODO: Not clear if this is intended to be language documentation
    (for Swift developers), an explanation or a reference guide.
  • Modules.md: was written for Swift pre-1.0, but is still
    relevant and covers behavior that’s underspecified in either TSPL or the
    language reference.
  • OptimizerCountersAnalysis.md:
    TODO: Consider breaking up into a how-to guide
    on dumping and analyzing the counters
    and an explanation for the counter collection system.
  • Testing.md:
    TODO: Consider splitting into a how-to guide on writing a new test case
    and an explanation for how the compiler is tested.
  • SwiftIndent.md:
    TODO: Unclear if this is intended to be an explanation or a reference guide.
  • Random.md: Stub.

Archive

  • FailableInitializers.md:
    Superseded by documentation in The Swift Programming Language.
  • InitializerProblems.rst:
    Describes some complexities around initialization in Swift.
    TODO: It would be great to have an explanation, say InitializationModel.md,
    that covers the initialization model and new attributes like
    @_hasMissingDesignatedInitializers. Some of this is covered in
    TSPL’s initialization section but that doesn’t include newly added
    attributes.
  • Swift3Compatibility.md:
    Discusses the Swift 3 -> Swift 4 migration.
  • StoredAndComputedVariables.rst: for Swift pre-1.0.

Книги по Swift программированию для iOS, iPAD, macOS, watchOS

С выходом Swift 5 обучающие ресурсы и технические авторы обновили свои книги по Swift как для начинающих, так и опытных разработчиков приложений для операционных систем Apple Platforms (iOS, iPadOS, macOS, tvOS и watchOS).

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

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

Большинство книг для изучения языка Swift доступны на английском языке, но в статье представлены издания и на русском языке популярных в сообществе iOS-разработчиков авторов.

Swift Apprentice

Книга Swift Apprentice (raywenderlich)

Книга Swift Apprentice (raywenderlich)
  • автор: raywenderlich.com
  • год издания: 2021
  • язык издания: EN

Это книга для новичков в современном языке программирования Apple — Swift.

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

Swift. Основы разработки приложений под iOS, iPadOS и macOS (6-е издание)

Swift Основы разработки приложений под iOS, iPadOS и macOS 6-е издание, Усов В

Swift Основы разработки приложений под iOS, iPadOS и macOS
  • автор: Усов В. А.
  • год издания: 2021
  • язык издания: русский

Что нового в 6-м издании? По сравнению с предыдущим изданием эта книга содержит следующие изменения и дополнения:

  • формат книги изменен (теперь она больше и толще).
  • учебный материал актуализирован в соответствии со Swift 5.3 и Xcode 12. Переписаны и обновлены большинство глав в книге
  • добавлен новый материал, который ранее не входил в книгу
  • пример использования фреймворка SwiftUI
  • о выборе между классами и структурами
  • о протокол-ориентированном программировании
  • о числовом типе данных Decimal
  • о ключевом слове some
  • о принципах работы ARC и хранении value type и reference type в памяти
  • о новых методах для работы с массивами
  • добавлены разделы «Для чего это использовать», которые кратко показывают, для чего в реальных проектах могут быть использованы изученные возможности
  • наборы (set) переименованы в множества
  • обновлены графические материалы (схемы, рисунки, графики и скриншоты)

Язык программирования Swift (Swift 5.7 Edition)

  • автор: Apple
  • год издания: 2022
  • язык издания: русский (перевод)

Это перевод на русский язык официального руководства «The Swift Programming Language» от Apple.

Если вам нужно быстро пройтись по возможностям языка, то начните с главы «Знакомство со Swift». Если же требуется углубиться в Swift, пропустите главу «Знакомство со Swift» и сразу начинайте читать с главы «Основы».

С содержанием книги можно ознакомиться на нашем сайте, а также скачать электронную версию в формате .ePub

Data Structures & Algorithms in Swift

Книга data structures algorithms in swift

Книга Data Structures Algorithms in Swift
  • автор: raywenderlich.com
  • год издания: 2021
  • язык издания: EN

Самая популярная и полная книга об алгоритмах и структурах данных Swift! Охватывает поиск, сортировку, деревья, стопки и многое другое.

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

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

Российской Национальной Ассоциацией SWIFT подготовлен перевод на русский язык Руководства пользователя SWIFT (UHB) версии ноября 2020 года, в который вошли следующие тома:

Корпоративные и правовые документы:

Словарь терминов
Устав SWIFT
Правила корпорации
Общие положения и условия
Прайс-лист на Сообщения и Решения SWIFT
Процедура оформления заказа, выставление счетов и порядок оплаты
Код BIC: Общие правила (Политика BIC)
Правила защиты персональных данных

 Описание сервисов:

MA–CUG. Для корпораций
SCORE 2.6. Для корпораций

Расследования и обработка нестандартных ситуаций

(Exceptions and Investigations) E&I версия 1.2

Описание
Банк-Банк. Руководство по использованию сообщений
Руководство по интеграции

Bulk Payments 2.1
Cash reporting 5.0

SWIFTNet FIN:

Коды ошибок FIN
Описание службы FIN
Системные сообщения FIN
Стандарты МТ. Рекомендации по использованию
Стандарты. Общая информация

Стандарты:

Категория 1 – Клиентские платежи и чеки
Категория 2 – Переводы финансовых организаций
Категория 3
– Рынки финансовых ресурсов – валютообменные и денежные операции, производные инструменты. Том 1 (МТ 300 – МТ 341)
– Рынки финансовых ресурсов – валютообменные и денежные операции, производные инструменты. Том 2 (МТ 350 – МТ 399)

Категория 4 – Инкассо и кассовые письма
Категория 5
– Рынки ценных бумаг. Рекомендации по использованию сообщений
Рынки ценных бумаг. Том 1 (МТ 500 – 518)
Рынки ценных бумаг. Том 2 (МТ 519 – 543)
Рынки ценных бумаг. Том 3 (МТ 544 – 567)
Рынки ценных бумаг. Том 4 (МТ 568 – 599)

Категория 6 – Рынки финансовых ресурсов — Товары
Категория 7 – Документарные аккредитивы и гарантии
Категория 8 – Дорожные чеки
Категория 9 – Управление денежными средствами и статус клиента
Категория n – Сообщения общей группы

Рекомендации:

SWIFT-RUR

SWIFT-RUR (на английском языке)

SWIFT-RUS

SWIFT-RUS (на английском языке)

ISO 20022.RU

Актуальные версии томов выкладываются в разделе Документация Ресурс-центра РОССВИФТ* по мере их изготовления.

* Для доступа к Ресурс-центру требуется авторизация на сайте РОССВИФТ. Заполнение авторизационной формы будет предложено Вам автоматически. Вам потребуется ввести Ваши логин и пароль. Если Вы еще не зарегистрированы, то в авторизационной форме нажмите на ссылку Регистрация и заполните регистрационную форму. После валидации Ваших данных модератором, Вам будут высланы логин и пароль.

Что можно почитать, если вы в начале пути.

https://gbcdn.mrgcdn.ru/uploads/post/1567/og_cover_image/7217d3175d572c5aab5f774e3de21b52

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

Мы подобрали только актуальные книги по Swift, которые вышли недавно либо затрагивают области, не зависящие от версии языка.

Официальная книга Swift Programming Language от Apple

Если с другими более устоявшимися языками разработчики советуют проверенные издания классических IT-авторов, то со Swift вас в первую очередь отправят читать официальную книгу от компании Apple, которая этот язык и разработала.

Swift Programming Language (Swift 4.1 edition) можно бесплатно скачать в itunes. На форумах и личных блогах можно найти переводы российских разработчиков, но они тоже затрагивают только предыдущие версии языка. Если вы читаете на английском, скачивайте последнюю официальную версию книги от Apple. Язык изложения сухой и довольно технический, но есть много примеров кода и даже иллюстрации различных приложений.

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

«По традиции, первая программа на новом языке должна выводить на экран словосочетание «Hello, world». На Swift это пишется всего в одну строку:

print("Hello, world!")

Если вы писали до этого код на C или Objective-C, этот синтаксис должен быть вам знаком. На Swift эта строка является законченной программой. Не нужно дополнительно импортировать отдельные библиотеки для таких функций, как ввод/вывод или обработка строк. Код, написанный в глобальной области, используется как входная точка для программы, так что функция main() больше не нужна. Также вам не нужно писать точки с запятой после каждой строки».

Swift для детей

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

«Swift для детей» — самое свежее издание об этом языке на русском. Для российских читателей издательство «Манн, Иванов и Фербер» выпустило ее в январе 2018 года. Авторы книги — разработчики iOS, многодетная мама Глория Уинквсит и руководитель отдела по созданию приложений для врачей и пациентов Мэтт Маккарти.

Первый раздел посвящен редактору Xcode: как его установить, настроить и написать первый код в XcodePlayground. Cледующие две части — практические. Шаг за шагом авторы издания предлагают написать приложение Birthday Tracker и игру Schoolhouse Skateboarder. В конце учебника — краткий справочник с информацией по официальной документации Swift, комбинациями клавиш для Xcode и симулятора IOS.

Несмотря на красочные детские иллюстрации (а может и благодаря им), книга хорошо подойдет и взрослым. Чтобы оценить, насколько хорошо авторы объясняют материал, посмотрите на отрывок из главы «Как давать названия константам и переменным»:

«Переменную и константу можно называть как угодно, но только не словами, которые используются самим Swift. К примеру, вы не можете называть переменную словом var. Запись var var может привести в замешательство и вас, и компьютер. Если попытаетесь назвать переменную или константу словом, зарезервированным Swift, у вас возникнет ошибка. Также в одном блоке программы «не уживутся» две переменные и константы с одним именем. Не бойтесь использовать длинные названия, избегайте сокращений. Так будет проще разобраться, зачем нужна переменная или константа. Если бы изучали чужую программу, что для вас было бы понятнее — numKids или numberOfKidsInMyClass?».

iOS 11 Programming Fundamentals with Swift: Swift, Xcode, and Cocoa Basics

Автор книги Мэтт Нойбург, судя по его краткой биографии в предисловии, — человек уникальный. С самого детства его одновременно интересовали и литература, и программирование; в обеих сферах он достиг больших успехов. Нойбург защитил докторскую по древнегреческой литературе, написал множество гайдов для программистов и разработал приложения MemoryStick, NotLight и Thucydides. Наверное, поэтому его книги с очень практическим значением такой приятный язык и отличный стиль изложения.

Последняя версия книга вышла в октябре прошлого года и разбирает всю теорию программирования на  Swift 4.0. Информация в издании разбита на 3 большие части:

  • Language (язык)
  • IDE (интегрированная среда разработки)
  • Cocoa (объектно-ориентированный API для macOS)

В предисловии автор довольно нескромно, но очень мотивационно пишет о своей методике обучения Swift:

«Мой способ обучения программированию на Swift отличается от других методик, в том числе от того, что предлагает Apple. Мой подход — систематический, евклидианский, все обучающие блоки связаны между собой и выстроены именно в той последовательности, которую я считаю наиболее эффективной. В то же время, в этом издании я постарался ограничиться основами — не уходить в детали. Swift — язык не сложный, но у него есть свои подводные камни. Я считаю, что не нужно глубоко вникать во все его нюансы сразу, поэтому осознанно не стал объяснять некоторые темы в книге. Например, в этой книге вы не найдете ничего о Swift Playgrounds или REPL. Я сфокусировался на актуальной практике программирования под IOS, поэтому в книге много советов из моего личного опыта разработчика».

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

Swift предоставляет свои собственные версии фундаментальных типов C и Objective-C, включая Int для целых чисел, Double и Float для значений с плавающей точкой, Bool для булевых значений, String для текста. Swift также предоставляет мощные версии трех основных типов коллекций, Array, Set и Dictionary, как описано в разделе Типы коллекций.

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

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

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

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

Константы и переменные

Константы и переменные связывают имя (например, maximumNumberOfLoginAttempts или welcomeMessage) со значением определенного типа (например, число 10 или строка «Hello»). Значение константы не может быть изменено после его установки, тогда как переменной может быть установлено другое значение в будущем.

Объявление констант и переменных

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

let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0

Этот код можно прочесть как:

«Объяви новую константу с именем maximumNumberOfLoginAttempts, и задай ей значение 10. Потом, объяви новую переменную с именем currentLoginAttempt, и задай ей начальное значение 0

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

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

var x = 0.0, y = 0.0, z = 0.0

Заметка

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

Аннотация типов

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

Этот пример добавляет обозначение типа для переменной с именем welcomeMessage, чтобы обозначить, что переменная может хранить String:

var welcomeMessage: String

Двоеточие в объявлении значит «…типа…», поэтому код выше может быть прочитан как:

«Объяви переменную с именем welcomeMessage, тип которой будет String»

Фраза «тип которой будет String» означает «может хранить любое String значение». Представьте, что словосочетание «тип которой будет такой-то» означает — значение, которое будет храниться.

Теперь переменной welcomeMessage можно присвоить любое текстовое значение, без каких либо ошибок:

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

var red, green, blue: Double

Заметка

Редко когда вам понадобится обозначать тип на практике. Когда вы даете начальное значение константе или переменной на момент объявления, Swift всегда может вывести тип, который будет использовать в константе или переменной. Это описано в Строгая типизация и Вывод типов. В примере welcomeMessage выше, не было присвоения начального значения, так что тип переменной welcomeMessage указывается с помощью обозначения типа вместо того, чтобы вывести из начального значения.

Название констант и переменных

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

let π = 3.14159
let 你好 = "你好世界"
let ?? = "dogcow"

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

Заметка

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

Вы можете изменить значение переменной на другое значение совместимого типа. В примере ниже значение friendlyWelcome изменено с “Hello!” на “Bonjour!”:

var friendlyWelcome = “Hello!”
friendlyWelcome = “Bonjour!”
// теперь friendlyWelcome имеет значение “Bonjour!”

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

let languageName = "Swift"
languageName = "Swift++"
// Это ошибка компилляции: languageName cannot be changed (значение languageName не может быть изменено).

Печать констант и переменных

Вы можете напечатать текущее значение константы или переменной при помощи функции print(_:separator:terminator:):

print(friendlyWelcome)
// Выведет "Bonjour!"

Функция print(_:separator:terminator:) является глобальной, которая выводит одно или более значений в подходящем виде. В Xcode, например, функция print(_:separator:terminator:) выводит значения в консоль. Параметры separator и terminator имеют дефолтные значения, так что при использовании функции их можно просто пропустить. По умолчанию функция заканчивает вывод символом переноса строки. Чтобы вывести в консоль значения без переноса на новую строку, вам нужно указать пустую строку в параметре terminator, например, print(someValue, terminator: «»). Для получения дополнительной информации по дефолтным значениям параметров обратитесь в раздел «Значения по умолчанию для параметров».

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

print("Текущее значение friendlyWelcome равно (friendlyWelcome)")
// Выведет "Текущее значение friendlyWelcome равно Bonjour!"

Заметка

Все опции, которые вы можете использовать в интерполяции строки вы сможете найти в разделе «Интерполяция строк».

Комментарии

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

Комментарии в Swift очень похожи на комментарии в C. Однострочные комментарии начинаются с двух слешей (//):

Вы также можете написать многострочные комментарии, которые начинаются со слеша и звездочки (/*) и заканчиваются звездочкой, за которой следует слеш (*/):

/* это тоже комментарий,
но написанный на двух строках */

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

/* это начало первого многострочного комментария
/* это второго, вложенного многострочного комментария */
это конец первого многострочного комментария */

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

Точки с запятой

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

let cat = "?"; print(cat)
// Выведет "?"

Целые числа

Integer (целое число) — это число, не содержащее дробной части, например, как 42 и -23. Целые числа могут быть либо знаковыми (положительными, ноль или отрицательными) либо беззнаковыми (положительными или ноль).

Swift предусматривает знаковые и беззнаковые целые числа в 8, 16, 32 и 64 битном форматах. Эти целые числа придерживаются соглашения об именах, аналогичных именам в C, в том, что 8-разрядное беззнаковое целое число имеет тип Uint8, а 32-разрядное целое число имеет тип Int32. Как и все типы в Swift, эти типы целых чисел пишутся с заглавной буквы.

Границы целых чисел

Вы можете получить доступ к минимальному и максимальному значению каждого типа целого числа с помощью его свойств min и max:

let minValue = UInt8.min // minValue равен 0, а его тип UInt8
let maxValue = UInt8.max // maxValue равен 255, а его тип UInt8

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

Int

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

  • На 32-битной платформе, Int того же размера что и Int32
  • На 64-битной платформе, Int того же размера что и Int64

Если вам не нужно работать с конкретным размером целого числа, всегда используйте в своем коде Int для целых чисел. Это придает коду логичность и совместимость. Даже на 32-битных платформах, Int может хранить любое значение в пределах -2 147 483 648 и 2 147 483 647, а этого достаточно для многих диапазонов целых чисел.

UInt

Swift также предусматривает беззнаковый тип целого числа — UInt, который имеет тот же размер что и разрядность системы:

  • На 32-битной платформе, UInt того же размера что и UInt32
  • На 64-битной платформе, UInt того же размера что и UInt64

Заметка

Используйте UInt, только когда вам действительно нужен тип беззнакового целого с размером таким же, как разрядность системы. Если это не так, использовать Int предпочтительнее, даже когда известно, что значения будут неотрицательными. Постоянное использование Int для целых чисел способствует совместимости кода, позволяет избежать преобразования между разными типами чисел, и соответствует выводу типа целого числа, как описано в Строгая типизация и Вывод Типов.

Числа с плавающей точкой

Число с плавающей точкой — это число с дробной частью, например как 3.14159, 0.1, и -273.15.

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

  • Double — представляет собой 64-битное число с плавающей точкой. Используйте его когда число с плавающей точкой должно быть очень большим или чрезвычайно точным
  • Float — представляет собой 32-битное число с плавающей точкой. Используйте его, когда значение не нуждается в 64-битной точности.

Заметка

Double имеет точность минимум 15 десятичных цифр, в то время как точность Float может быть всего лишь 6 десятичных цифр. Соответствующий тип числа с плавающей точкой используется в зависимости от характера и диапазона значений, c которыми вы должны работать в коде. В случаях, где возможно использование обоих типов, предпочтительным считается Double.

Строгая типизация и Вывод типов

Swift — язык со строгой типизацией. Язык со строгой типизацией призывает вас иметь четкое представление о типах значений, с которыми может работать ваш код. Если часть вашего кода ожидает String, вы не сможете передать ему Int по ошибке.

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

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

Благодаря выводу типов, Swift требует гораздо меньше объявления типов, чем языки, такие как C или Objective-C. Константам и переменным все же нужно присваивать тип, но большая часть работы с указанием типов будет сделана за вас.

Вывод типов особенно полезен, когда вы объявляете константу или переменную с начальным значением. Часто это делается путем присвоения литерального значения (или литерала) к константам или переменным в момент объявления​​. (Литеральное значение — значение, которое появляется непосредственно в исходном коде, например как 42 и 3,14159 в примерах ниже.)

Например, если вы присваиваете литеральное значение 42 к новой константе не сказав какого она типа, Swift делает вывод, что вы хотите чтобы константа была Int, потому что вы присвоили ей значение, которое похоже на целое число:

let meaningOfLife = 42
// meaningOfLife выводится как тип Int

Точно так же, если вы не указали тип для литерала с плавающей точкой, Swift делает вывод, что вы хотите создать Double:

let pi = 3.14159
// pi выводится как тип Double

Swift всегда выбирает Double (вместо Float), когда выводит тип чисел с плавающей точкой.

Если объединить целые литералы и литералы с плавающей точкой в одном выражении, в этом случае тип будет выводиться как Double:

let anotherPi = 3 + 0.14159
// anotherPi тоже выводится как тип Double

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

Числовые литералы

Числовые литералы могут быть написаны как:

  • Десятичное число, без префикса
  • Двоичное число, с префиксом 0b
  • Восьмеричное число, с префиксом 0o
  • Шестнадцатеричное число, с префиксом 0x

Все эти литералы целого числа имеют десятичное значение 17:

let decimalInteger = 17
let binaryInteger = 0b10001 // 17 в двоичной нотации
let octalInteger = 0o21 // 17 в восмеричной нотации
let hexadecimalInteger = 0x11 // 17 в шестнадцатеричной нотации

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

Для десятичных чисел с показателем степени ехр, базовое число умножается на 10exp:

  • 1.25e2 означает 1.25 × 102, или 125.0.
  • 1.25e-2 означает 1.25 × 10-2, или 0.0125.

Для шестнадцатеричных чисел с показателем степени ехр, базовое число умножается на 2exp:

  • 0xFp2 означает 15 × 22, или 60.0.
  • 0xFp-2 означает 15 × 2-2, или 3.75.

Все эти числа с плавающей точкой имеют десятичное значение 12.1875:

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

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

let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

Преобразования числовых типов

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

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

Преобразования целых чисел

Диапазон значений, который может храниться в целочисленных константах и переменных, различен для каждого числового типа. Int8 константы и переменные могут хранить значения между -128 и 127, тогда как UInt8 константы и переменные могут хранить числа между 0 и 255. Если число не подходит для переменной или константы с определенным размером, выводится ошибка во время компиляции:

let cannotBeNegative: UInt8 = -1
// UInt8 не может хранить отрицательные значения, поэтому эта строка выведет ошибку
let tooBig: Int8 = Int8.max + 1
// Int8 не может хранить число больше своего максимального значения,
// так что это тоже выведет ошибку

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

Чтобы преобразовать один числовой тип в другой, необходимо создать новое число желаемого типа из существующего значения. Ниже, в примере, константа twoThousand имеет тип UInt16, тогда как константа one — UInt8. Сложить их напрямую не получится, потому что они разного типа. Вместо этого, в примере вызывается функция UInt16(one) для создания нового числа UInt16 из значения константы one:

let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

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

НазваниеТипа(начальноеЗначение) — стандартный способ вызвать инициализатор типов Swift и передать начальное значение. Честно говоря, у UInt16 есть инициализатор, который принимает UInt8 значение, и, таким образом, этот инициализатор используется, чтобы создать новый UInt16 из существующего UInt8. Здесь вы не можете передать любой тип, однако это должен быть тип, для которого у UInt16 есть инициализатор. Расширение существующих типов с помощью создания инициализаторов, которые принимают новые типы (включая объявление вашего типа) рассматривается в главе Расширения.

Преобразования целых чисел и чисел с плавающей точкой

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

let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi равно 3.14159, и для него выведен тип Double

Здесь, значение константы three используется для создания нового значения типа Double, так что обе части сложения имеют один тип. Без этого преобразования сложение не будет проходить. Обратное преобразование числа с плавающей точкой в целое число тоже должно происходить явно. Так что тип целого числа может быть инициализирован с помощью Double и Float значений:

let integerPi = Int(pi)
// integerPi равен 3, и для него выведен тип Int

Числа с плавающей точкой всегда урезаются, когда вы используете инициализацию целого числа через этот способ. Это означает, что 4.75 будет 4, а -3.9 будет -3.

Заметка

Правила объединения числовых констант и переменных отличается от правил числовых литералов. Литеральное значение 3 может напрямую сложиться с литеральным значением 0.14159, потому что числовые литералы сами по себе не имеют явного типа. Их тип выводится только в момент оценки значения компилятором.

Псевдонимы типов

Псевдонимы типов задают альтернативное имя для существующего типа. Можно задать псевдоним типа с помощью ключевого слова typealias.

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

typealias AudioSample = UInt16

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

var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound теперь 0

Здесь AudioSample определен как псевдоним для UInt16. Поскольку это псевдоним, вызов AudioSample.min фактически вызовет UInt16.min, что показывает начальное значение 0 для переменной maxAmplitudeFound.

Логические типы

В Swift есть простой логический тип Bool. Этот тип называют логическим, потому что он может быть только true или false. Swift предусматривает две логические константы, true и false соответственно:

let orangesAreOrange = true
let turnipsAreDelicious = false

Типы для orangesAreOrange и turnipsAreDelicious были выведены как Bool, исходя из того факта, что мы им присвоили логические литералы. Так же как с Int и Double в предыдущих главах, вам не нужно указывать константы или переменные как Bool, если при создании вы присвоили им значения true или false. Вывод типов помогает сделать код Swift кратким и читабельным тогда, когда вы создаете константы или переменные со значениями которые точно известны.

Логические значения очень полезны когда вы работаете с условными операторами, такими как оператор if:

if turnipsAreDelicious {
 print("Mmm, tasty turnips!")
} else {
 print("Eww, turnips are horrible.")
}
// Выведет "Eww, turnips are horrible."

Условные операторы, такие как оператор if детально рассматриваются в главе Управление потоком.

Строгая типизация Swift препятствует замене значения Bool на не логическое значение. Следующий пример выведет ошибку компиляции:

let i = 1
if i {
 // этот пример не скомпилируется, и выдаст ошибку компиляции
}

Тем не менее, альтернативный пример ниже правильный:

let i = 1
if i == 1 {
 // этот пример выполнится успешно
}

Результат сравнения i == 1 имеет тип Bool, и поэтому этот второй пример совершает проверку типов. Такие сравнения как i == 1 обсуждаются в главе Базовые операторы.

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

Кортежи

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

В данном примере (404, «Not Found») это кортеж, который описывает код HTTP статуса. Код HTTP статуса — особое значение, возвращаемое веб-сервером каждый раз, когда вы запрашиваете веб-страницу. Код статуса 404 Not Found возвращается, когда вы запрашиваете страницу, которая не существует.

let http404Error = (404, "Not Found")
// http404Error имеет тип (Int, String), и равен (404, "Not Found")

Чтобы передать код статуса, кортеж (404, «Not Found») группирует вместе два отдельных значения Int и String: число и понятное человеку описание. Это может быть описано как «кортеж типа (Int, String)«.

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

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

let (statusCode, statusMessage) = http404Error
print("The status code is (statusCode)")
// Выведет "The status code is 404"
print("The status message is (statusMessage)")
// Выведет "The status message is Not Found"

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

let (justTheStatusCode, _) = http404Error
print("The status code is (justTheStatusCode)")
// Выведет "The status code is 404"

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

print("The status code is (http404Error.0)")
// Выведет "The status code is 404"
print("The status message is (http404Error.1)")
// Выведет "The status message is Not Found"

Вы можете давать имена отдельным элементам кортежа во время объявления:

let http200Status = (statusCode: 200, description: "OK")

Когда вы присвоили имя элементу кортежа, вы можете обратиться к нему по имени:

print("The status code is (http200Status.statusCode)")
// Выведет "The status code is 200"
print("The status message is (http200Status.description)")
// Выведет "The status message is OK"

Кортежи особенно полезны в качестве возвращаемых значений функций. Функция, которая пытается получить веб-страницу, может вернуть кортеж типа (Int, String), чтобы описать успех или неудачу в поиске страницы. Возвращая кортеж с двумя отдельными значениями разного типа, функция дает более полезную информацию о ее результате, чем, если бы, возвращала единственное значение одного типа, возвращаемое функцией. Для более подробной информации смотрите главу Функции, возвращающие несколько значений.

Заметка

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

Опциональные типы (опционалы)

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

Заметка

В C или Objective-C нет понятия опционалов. Ближайшее понятие в Objective-C это возможность вернуть nil из метода, который в противном случае вернул бы объект. В этом случае nil обозначает «отсутствие допустимого объекта». Тем не менее, это работает только для объектов, и не работает для структур, простых типов C, или значений перечисления. Для этих типов, методы Objective-C, как правило, возвращают специальное значение (например, NSNotFound), чтобы указать отсутствие значения. Этот подход предполагает, что разработчик, который вызвал метод, знает, что есть это специальное значение и что его нужно учитывать. Опционалы Swift позволяют указать отсутствие значения для абсолютно любого типа, без необходимости использования специальных констант.

Приведем пример, который покажет, как опционалы могут справиться с отсутствием значения. У типа Int в Swift есть инициализатор, который пытается преобразовать значение String в значение типа Int. Тем не менее, не каждая строка может быть преобразована в целое число. Строка «123» может быть преобразована в числовое значение 123, но строка «hello, world» не имеет очевидного числового значения для преобразования.

В приведенном ниже примере используется метод Int() для попытки преобразовать String в Int:

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// для convertedNumber выведен тип "Int?", или "опциональный Int"

Поскольку метод Int() может иметь недопустимый аргумент, он возвращает опциональный Int, вместо Int. Опциональный Int записывается как Int?, а не Int. Знак вопроса означает, что содержащееся в ней значение является опциональным, что означает, что он может содержать некое Int значение, или он может вообще не содержать никакого значения. (Он не может содержать ничего другого, например, Bool значение или значение String. Он либо Int, либо вообще ничто)

nil

Мы можем установить опциональную переменную в состояние отсутствия значения, путем присвоения ему специального значения nil

var serverResponseCode: Int? = 404
// serverResponseCode содержит реальное Int значение 404
serverResponseCode = nil
// serverResponseCode теперь не содержит значения

Заметка

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

Если объявить опциональную переменную без присвоения значения по умолчанию, то переменная автоматически установится в nil для вас:

var surveyAnswer: String?
// surveyAnswer автоматически установится в nil

Заметка

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

Инструкция If и Принудительное извлечение

Вы можете использовать инструкцию if, сравнивая опционал с nil, чтобы проверить, содержит ли опционал значение. Это сравнение можно сделать с помощью оператора «равенства» (==) или оператора «неравенства» (!=).

Если опционал имеет значение, он будет рассматриваться как «неравным» nil:

if convertedNumber != nil {
    print("convertedNumber contains some integer value.")
}
// Выведет "convertedNumber contains some integer value."

Если вы уверены, что опционал содержит значение, вы можете получить доступ к его значению, добавив восклицательный знак (!) в конце имени опционала. Восклицательный знак фактически говорит: «Я знаю точно, что этот опционал содержит значение, пожалуйста, используй его». Это выражение известно как Принудительное извлечение значения опционала:

if convertedNumber != nil {
    print("convertedNumber has an integer value of (convertedNumber!).")
}
// Выведет "convertedNumber has an integer value of 123."

Более подробную информацию об инструкции if можно получить в главе Управление потоком.

Заметка

Попытка использовать ! к несуществующему опциональному значению вызовет runtime ошибку. Всегда будьте уверены в том, что опционал содержит не-nil значение, перед тем как использовать ! чтобы принудительно извлечь это значение.

Привязка опционалов

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

Привязку опционалов для инструкции if можно писать как показано ниже:

  1. if let constantName = someOptional {
  2.     statements
  3. }

Мы можем переписать пример possibleNumber сверху, используя привязку опционалов, а не принудительное извлечение:

if let actualNumber = Int(possibleNumber) {
    print("(possibleNumber) has an integer value of (actualNumber)")
} else {
    print("(possibleNumber) could not be converted to an integer")
}
// Выведет "123" has an integer value of 123

Это может быть прочитано как:

«Если опциональный Int возвращаемый Int(possibleNumber) содержит значение, установи в новую константу с названием actualNumber значение, содержащееся в опционале.»

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

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

Вы можете включать столько опциональных привязок и логических условий в единственную инструкцию if, сколько вам требуется, разделяя их запятыми. Если какое-то значение в опциональной привязке равно nil, или любое логическое условие вычисляется как false, то все условия выражения будет считаться false. Следующие инструкции if эквиваленты:

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("(firstNumber) < (secondNumber) < 100")
}
// Выведет "4 < 42 < 100"
 
if let firstNumber = Int("4") {
    if let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("(firstNumber) < (secondNumber) < 100")
        }
    }
}
// Выведет "4 < 42 < 100"

Заметка

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

Неявно извлеченные опционалы

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

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

Эти виды опционалов называются неявно извлеченные опционалы. Их можно писать, используя восклицательный знак (String!), вместо вопросительного знака (String?), после типа, который вы хотите сделать опциональным.

Вместо того, чтобы ставить восклицательный знак (!) после опционала, когда вы его используете, поместите восклицательный знак (!) после опционала, когда вы его объявляете.

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

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

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // необходим восклицательный знак

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // восклицательный знак не нужен

Вы можете считать неявно извлеченные опционалы обычными опционалами дающими разрешение на принудительное извлечение, если это требуется. Когда вы используете неявно извлеченный опционал, то Swift сначала пробует использовать его в качестве обычного опционального значения, если так его использовать не получается, то уже пробует принудительно извлечь значение. В коде выше опциональное значение assumedString является принудительно извлеченным прежде, чем будет записано в implicitString, так как implicitString имеет явный неопциональный тип String. В коде ниже optionalString не имеет явного типа, так что является обычным опционалом.

let optionalString = assumedString
// Тип optionalString является "String?" и assumedString не является принудительно извлеченным значением.

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

Вы можете проверить не является ли неявно извлеченный опционал nil точно так же как вы проверяете обычный опционал:

if assumedString != nil {
    print(assumedString!)
}
// Выведет "An implicitly unwrapped optional string."

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

if let definiteString = assumedString {
  print(definiteString)
}
// Выведет "An implicitly unwrapped optional string."

Заметка

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

Обработка ошибок

Вы используете обработку ошибок в ответ на появление условий возникновения ошибок во время выполнения программы.

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

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

func canThrowAnError() throws {
// эта функция может сгенерировать ошибку
}

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

do {
  try canThrowAnError()
  // ошибка не была сгенерирована
} catch {
  // ошибка сгенерирована
}

Выражение do создает область, содержащую объект, которая позволяет ошибкам быть переданными в одно или несколько условий catch.

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

func makeASandwich() throws {
    // ...
}
 
do {
    try makeASandwich()
    eatASandwich()
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

В этом примере, функция makeASandwich() генерирует ошибку, если нет чистых тарелок или если отсутствуют какие-либо ингредиенты. Так как makeASandwich() может выдавать ошибку, то вызов функции заворачивают в выражении try. При заворачивании вызова функции в выражение do, генерация каких-либо ошибок, будет передаваться на предусмотренные условия catch.

Если ошибка не генерируется, то вызывается функция eatASandwich(). Если ошибка все таки генерируется, и она соответствует SandwichError.outOfCleanDishes, то вызывается функция washDishes(). Если генерируется ошибка, и она соответствует SandwichError.missingIngredients , то функция buyGroceries(_:) вызывается с соответствующим значением [String], захваченным шаблоном catch.

Генерация, вылавливание и передача ошибок рассмотрены более подробно в главе Обработка ошибок.

Утверждения и предусловия

Утверждения и предусловия являются проверками во время исполнения. Вы используете их для того, чтобы убедиться, что какое-либо условие уже выполнено, прежде чем начнется исполнение последующего кода. Если булево значение в утверждении или в предусловии равно true, то выполнение кода просто продолжается далее, но если значение равно false, то текущее состояние исполнения программы некорректно и выполнение кода останавливается и ваше приложение завершает работу.

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

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

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

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

Отладка с помощью утверждений

Утверждения записываются как функция стандартной библиотеки Swift assert(_:_:file:line:). Вы передаете в эту функцию выражение, которые оценивается как true или false и сообщение, которое должно отображаться, если результат условия будет false. Например:

let age = -3
assert(age >= 0, "Возраст человека не может быть меньше нуля")
// это приведет к вызову утверждения, потому что age >= 0, а указанное значение < 0.

В этом примере, выполнение кода продолжится, только если age >= 0 вычислится в true, что может случиться, если значение age не отрицательное. Если значение age отрицательное, как в коде выше, тогда age >= 0 вычислится как false, и запустится утверждение, завершив за собой приложение.

Сообщение утверждения можно пропускать по желанию, как в следующем примере:

Если код уже проверяет условие, то вы используете функцию assertionFailure(_:file:line:) для индикации того, что утверждение не выполнилось. Например:

if age > 10 {
    print("Ты можешь покататься на американских горках и чертовом колесе.")
} else if age > 0 {
    print("Ты можешь покататься на чертовом колесе.")
} else {
    assertionFailure("Возраст человека не может быть отрицательным.")
}

Обеспечение предусловиями

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

Для использования предусловий вызовите функцию precondition(_:_:file:line:). Вы передаете этой функции выражение, которое вычисляется как true или false и сообщение, которое должно отобразиться, если условие будет иметь значение как false. Например:

 // В реализации сабскрипта...
precondition(index > 0, "Индекс должен быть больше нуля.")

Вы так же можете вызвать функцию preconditionFailure(_:_:file:line:) для индикации, что отказ работы уже произошел, например, если сработал дефолтный кейс инструкции switch, когда известно, что все валидные значения должны быть обработаны любым кейсом, кроме дефолтного.

Заметка

Если вы компилируете в режиме -0unchecked, то предусловия не проверяются. Компилятор предполагает, что предусловия всегда получают значения true, и он оптимизирует ваш код соответствующим образом. Однако, функция fatalError(_:file:line:) всегда останавливает исполнение, несмотря на настройки оптимизации.

Вы можете использовать функцию fatalError (_:file:line:) во время прототипирования или ранней разработки для создания заглушек для функциональности, которая еще не реализована, написав fatalError («Unimplemented») в качестве реализации заглушки. Поскольку фатальные ошибки никогда не оптимизируются, в отличие от утверждений или предусловий, вы можете быть уверены, что выполнение кода всегда прекратится, если оно встречает реализацию заглушки.

Понравилась статья? Поделить с друзьями:
  • Пик руководство пользователя
  • Perkins 4006 23tag3a руководство по эксплуатации на русском
  • Руководства эксплуатации фольксваген тигуан
  • Ацц инструкция по применению взрослым для лечения бронхита
  • Специалист по работе с претензиями должностная инструкция