Spec-Zone.ru › Swift Language

Атрибуты

Добавляйте информацию к объявлениям и типам.

В Swift есть два вида атрибутов — те, которые применяются к объявлениям, и те, которые применяются к типам. Атрибут предоставляет дополнительную информацию об объявлении или типе. Например, атрибут discardableResult на объявлении функции указывает, что, хотя функция возвращает значение, компилятор не должен генерировать предупреждение, если возвращаемое значение не используется.

Вы задаёте атрибут, написав символ @, за которым следует имя атрибута и любые аргументы, которые принимает атрибут:

@<#attribute name#>
@<#attribute name#>(<#attribute arguments#>)

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

Прикреплённые макросы и обёртки свойств также используют синтаксис атрибутов. Сведения о том, как макросы расширяются, см. в <doc:Expressions#Macro-Expansion-Expression>. Сведения об обёртках свойств см. в <doc:Attributes#propertyWrapper>.

Атрибуты объявлений

Вы можете применять атрибут объявления только к объявлениям.

attached

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

Первый аргумент этого атрибута указывает роль макроса:

  • макросы-партнёры: Запишите peer в качестве первого аргумента этого атрибута. Тип, реализующий макрос, соответствует протоколу PeerMacro. Эти макросы создают новые объявления в том же пространстве имён, что и объявление, к которому прикреплён макрос. Например, применение макроса-партнёра к методу структуры может определять дополнительные методы и свойства в этой структуре.

  • член-макросы: Запишите member в качестве первого аргумента этого атрибута. Тип, реализующий макрос, соответствует протоколу MemberMacro. Эти макросы генерируют новые объявления, которые являются членами типа или расширения, к которому прикреплён макрос. Например, применение члена-макроса к объявлению структуры может определять дополнительные методы и свойства в этой структуре.

  • атрибут-член: Запишите memberAttribute в качестве первого аргумента этого атрибута. Тип, реализующий макрос, соответствует протоколу MemberAttributeMacro. Эти макросы добавляют атрибуты к членам типа или расширения, к которому прикреплён макрос.

  • макросы-обработчики доступа: Запишите accessor в качестве первого аргумента этого атрибута. Тип, реализующий макрос, соответствует протоколу AccessorMacro. Эти макросы добавляют обработчики доступа к хранящемуся свойству, преобразуя его в вычисляемое свойство.

  • макросы расширения: Запишите extension в качестве первого аргумента этого атрибута. Тип, реализующий макрос, соответствует протоколу ExtensionMacro. Эти макросы могут добавлять соответствие протоколу, клаузу where и новые объявления, которые являются членами типа, к которому прикреплен макрос. Если макрос добавляет соответствие протоколам, укажите аргумент conformances: и перечислите эти протоколы. Список соответствия содержит имена протоколов, псевдонимы типов, которые ссылаются на элементы списка соответствия, или композиции протоколов элементов списка соответствия. Макрос расширения над вложенным типом расширяется до расширения на верхнем уровне этого файла. Вы не можете написать макрос расширения на расширении, псевдониме типа или типе, вложенном в функцию, или использовать макрос расширения для добавления расширения, имеющего макрос-партнёр.

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

Значение для этого аргумента — список из одного или нескольких из следующих:

  • named(<#name#>), где name — это фиксированное имя символа, для имени, которое известно заранее.

  • overloaded, для имени, которое совпадает с существующим символом.

  • prefixed(<#prefix#>), где prefix предшествует имени символа, для имени, которое начинается с фиксированной строки.

  • suffixed(<#suffix#>), где suffix добавляется к имени символа, для имени, которое заканчивается фиксированной строкой.

  • arbitrary, для имени, которое нельзя определить до расширения макроса.

В качестве специального случая вы можете написать prefixed($) для макроса, который ведёт себя подобно обёртке свойства.

available

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

Атрибут available всегда появляется со списком из двух или более аргументов атрибута, разделённых запятыми. Эти аргументы начинаются с одного из следующих имён платформ или языков:

  • iOS
  • iOSApplicationExtension
  • macOS
  • macOSApplicationExtension
  • macCatalyst
  • macCatalystApplicationExtension
  • watchOS
  • watchOSApplicationExtension
  • tvOS
  • tvOSApplicationExtension
  • visionOS
  • visionOSApplicationExtension
  • swift

Вы также можете использовать звездочку (*), чтобы указать доступность объявления на всех перечисленных выше именах платформ. Атрибут available, который указывает доступность с помощью номера версии Swift, не может использовать звездочку.

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

  • Аргумент unavailable указывает, что объявление недоступно на указанной платформе. Этот аргумент нельзя использовать при указании доступности версии Swift.

  • Аргумент introduced указывает первую версию указанной платформы или языка, в которой было введено объявление. Он имеет следующий вид:

    introduced: <#version number#>

    Номер версии состоит из одного или нескольких положительных целых чисел, разделённых точками.

  • Аргумент deprecated указывает первую версию указанной платформы или языка, в которой объявление было устаревшим. Он имеет следующий вид:

    deprecated: <#version number#>

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

  • Аргумент obsoleted указывает первую версию указанной платформы или языка, в которой объявление было устарело. Когда объявление устарело, оно удаляется с указанной платформы или языка и больше не может быть использовано. Он имеет следующий вид:

    obsoleted: <#version number#>

    Номер версии состоит из одного или нескольких положительных целых чисел, разделённых точками.

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

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

    Чтобы избежать этой проблемы, добавьте атрибут @available(*, noasync) к объявлению символа:

    extension pthread_mutex_t {
    
      @available(*, noasync)
      mutating func lock() {
          pthread_mutex_lock(&self)
      }
    
      @available(*, noasync)
      mutating func unlock() {
          pthread_mutex_unlock(&self)
      }
    }

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

    @available(*, noasync, message: "Migrate locks to Swift concurrency.")
    mutating func lock() {
      pthread_mutex_lock(&self)
    }

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

    // Provide a synchronous wrapper around methods with a noasync declaration.
    extension pthread_mutex_t {
      mutating func withLock(_ operation: () -> ()) {
        self.lock()
        operation()
        self.unlock()
      }
    }
    
    func downloadAndStore(key: Int,
                        dataStore: MyKeyedStorage,
                        dataLock: inout pthread_mutex_t) async {
      // Safely call the wrapper in an asynchronous context.
      dataLock.withLock {
        dataStore[key] = downloadContent()
      }
    }

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

  • Аргумент message предоставляет текстовое сообщение, которое компилятор отображает при выводе предупреждения или ошибки об использовании объявления, помеченного как deprecated, obsoleted или noasync. Он имеет следующий вид:

    message: <#message#>

    Сообщение состоит из строковой литералы.

  • Аргумент renamed предоставляет текстовое сообщение, которое указывает новое имя для объявления, которое было переименовано. Компилятор отображает новое имя при выводе ошибки об использовании переименованного объявления. Он имеет следующий вид:

    renamed: <#new name#>

    Новое имя состоит из строковой литералы.

    Вы можете применить атрибут available с аргументами renamed и unavailable к объявлению псевдонима типа, как показано ниже, чтобы указать, что имя объявления изменилось между выпусками фреймворка или библиотеки. Эта комбинация приводит к ошибке времени компиляции, что объявление было переименовано.

    // First release
    protocol MyProtocol {
        // protocol definition
    }
    // Subsequent release renames MyProtocol
    protocol MyRenamedProtocol {
        // protocol definition
    }
    
    @available(*, unavailable, renamed: "MyRenamedProtocol")
    typealias MyProtocol = MyRenamedProtocol

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

Если атрибут available указывает только аргумент introduced в дополнение к аргументу имени платформы или языка, вы можете использовать следующий сокращённый синтаксис вместо этого:

@available(<#platform name#> <#version number#>, *)
@available(swift <#version number#>)

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

@available(iOS 10.0, macOS 10.12, *)
class MyClass {
    // class definition
}

Атрибут available, который указывает доступность с помощью номера версии Swift, не может дополнительно указывать доступность объявления на платформе. Вместо этого используйте отдельные атрибуты available для указания доступности версии Swift и одну или несколько доступностей платформ.

@available(swift 3.0.2)
@available(macOS 10.12, *)
struct MyStruct {
    // struct definition
}

backDeployed

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

Этот атрибут принимает аргумент before:, определяющий первую версию платформ, предоставляющих этот символ. Эти версии платформы имеют такое же значение, как версия платформы, которую вы указываете для атрибута available. В отличие от атрибута available, список не может содержать звездочку (*) для ссылки на все версии. Например, рассмотрите следующий код:

@available(iOS 16, *)
@backDeployed(before: iOS 17)
func someFunction() { /* ... */ }

В приведенном выше примере iOS SDK предоставляет someFunction(), начиная с iOS 17. Кроме того, SDK делает someFunction() доступным на iOS 16 с помощью обратной развертки.

При компиляции кода, который вызывает эту функцию, Swift вставляет уровень косвенности, который находит реализацию функции. Если код выполняется с использованием версии SDK, которая включает эту функцию, используется реализация SDK. В противном случае используется копия, включенная в вызывающую программу. В приведенном выше примере вызов someFunction() использует реализацию из SDK при выполнении на iOS 17 или более поздних версиях, а при выполнении на iOS 16 он использует копию someFunction(), включенную в вызывающую программу.

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

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

  • Объявление является public или @usableFromInline.
  • Для методов экземпляра класса и методов типа класса метод помечен как final и не помечен как @objc.
  • Реализация удовлетворяет требованиям к инлайновой функции, описанным в <doc:Attributes#inlinable>.

discardableResult

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

dynamicCallable

Примените этот атрибут к классу, структуре, перечислению или протоколу, чтобы обрабатывать экземпляры типа как вызываемые функции. Тип должен реализовывать либо метод dynamicallyCall(withArguments:), либо метод dynamicallyCall(withKeywordArguments:), или оба.

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

@dynamicCallable
struct TelephoneExchange {
    func dynamicallyCall(withArguments phoneNumber: [Int]) {
        if phoneNumber == [4, 1, 1] {
            print("Get Swift help on forums.swift.org")
        } else {
            print("Unrecognized number")
        }
    }
}

let dial = TelephoneExchange()

// Use a dynamic method call.
dial(4, 1, 1)
// Prints "Get Swift help on forums.swift.org"

dial(8, 6, 7, 5, 3, 0, 9)
// Prints "Unrecognized number"

// Call the underlying method directly.
dial.dynamicallyCall(withArguments: [4, 1, 1])

Объявление метода dynamicallyCall(withArguments:) должно иметь один параметр, соответствующий протоколу ExpressibleByArrayLiteral — например, [Int] в примере выше. Тип возвращаемого значения может быть любым типом.

Вы можете включать метки в вызов динамического метода, если вы реализуете метод dynamicallyCall(withKeywordArguments:).

@dynamicCallable
struct Repeater {
    func dynamicallyCall(withKeywordArguments pairs: KeyValuePairs<String, Int>) -> String {
        return pairs
            .map { label, count in
                repeatElement(label, count: count).joined(separator: " ")
            }
            .joined(separator: "\n")
    }
}

let repeatLabels = Repeater()
print(repeatLabels(a: 1, b: 2, c: 3, b: 2, a: 1))
// a
// b b
// c c c
// b b
// a

Объявление метода dynamicallyCall(withKeywordArguments:) должно иметь один параметр, соответствующий протоколу ExpressibleByDictionaryLiteral, а тип возвращаемого значения может быть любым типом. Параметр Key должен быть ExpressibleByStringLiteral. В предыдущем примере используется KeyValuePairs в качестве типа параметра, чтобы вызывающие стороны могли включать повторяющиеся метки параметров — a и b появляются несколько раз в вызове repeat.

Если вы реализуете оба метода dynamicallyCall, метод dynamicallyCall(withKeywordArguments:) вызывается, когда вызов метода включает ключевые аргументы. Во всех других случаях вызывается метод dynamicallyCall(withArguments:).

Вы можете вызывать экземпляр динамически вызываемого типа только с аргументами и возвращаемым значением, соответствующими типам, указанным в одной из ваших реализаций метода dynamicallyCall. Вызов в следующем примере не компилируется, потому что нет реализации dynamicallyCall(withArguments:), которая принимает KeyValuePairs<String, String>.

repeatLabels(a: "four") // Error

dynamicMemberLookup

Примените этот атрибут к классу, структуре, перечислению или протоколу, чтобы разрешить поиск членов по имени во время выполнения. Тип должен реализовывать индекс subscript(dynamicMember:).

В явном выражении члена, если нет соответствующего объявления для именованного члена, выражение понимается как вызов индекса subscript(dynamicMember:) типа, передавая информацию о члене в качестве аргумента. Индекс может принимать параметр, который является либо путем ключа, либо именем члена; если вы реализуете оба индекса, используется индекс, принимающий аргумент пути ключа.

Реализация subscript(dynamicMember:) может принимать пути ключей, используя аргумент типа KeyPath, WritableKeyPath или ReferenceWritableKeyPath. Он может принимать имена членов, используя аргумент типа, соответствующего протоколу ExpressibleByStringLiteral — в большинстве случаев, String. Тип возвращаемого значения индекса может быть любым типом.

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

@dynamicMemberLookup
struct DynamicStruct {
    let dictionary = ["someDynamicMember": 325,
                      "someOtherMember": 787]
    subscript(dynamicMember member: String) -> Int {
        return dictionary[member] ?? 1054
    }
}
let s = DynamicStruct()

// Use dynamic member lookup.
let dynamic = s.someDynamicMember
print(dynamic)
// Prints "325"

// Call the underlying subscript directly.
let equivalent = s[dynamicMember: "someDynamicMember"]
print(dynamic == equivalent)
// Prints "true"

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

struct Point { var x, y: Int }

@dynamicMemberLookup
struct PassthroughWrapper<Value> {
    var value: Value
    subscript<T>(dynamicMember member: KeyPath<Value, T>) -> T {
        get { return value[keyPath: member] }
    }
}

let point = Point(x: 381, y: 431)
let wrapper = PassthroughWrapper(value: point)
print(wrapper.x)

freestanding

Примените атрибут freestanding к объявлению свободной макросы.

frozen

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

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

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

Замороженные типы, типы сохраненных свойств замороженных структур и связанные значения замороженных случаев перечисления должны быть публичными или помечены атрибутом usableFromInline. Свойства замороженной структуры не могут иметь наблюдателей свойств, а выражения, предоставляющие начальное значение для сохраненных свойств экземпляра, должны следовать тем же ограничениям, что и инлайновые функции, как описано в <doc:Attributes#inlinable>.

Чтобы включить режим эволюции библиотеки в командной строке, передайте опцию -enable-library-evolution компилятору Swift. Чтобы включить его в Xcode, установите значение параметра «Строить библиотеки для распространения» (BUILD_LIBRARY_FOR_DISTRIBUTION) в «Да», как описано в Справке Xcode.

Инструкция switch над замороженным перечислением не требует случая default, как описано в <doc:Statements#Switching-Over-Future-Enumeration-Cases>. Включение случая default или @unknown default при переключении над замороженным перечислением приводит к предупреждению, потому что этот код никогда не выполняется.

GKInspectable

Примените этот атрибут, чтобы экспонировать свойство пользовательского компонента GameplayKit в пользовательском интерфейсе редактора SpriteKit. Применение этого атрибута также подразумевает атрибут objc.

inlinable

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

Инлайновый код может взаимодействовать с open и public символами, объявленными в любом модуле, и он может взаимодействовать с internal символами, объявленными в том же модуле, которые помечены атрибутом usableFromInline. Инлайновый код не может взаимодействовать с private или fileprivate символами.

Этот атрибут не может быть применен к объявлениям, вложенным внутри функций, или к объявлениям fileprivate или private. Функции и замыкания, определенные внутри инлайновой функции, неявно инлайновые, хотя они не могут быть помечены этим атрибутом.

main

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

@main
struct MyTopLevel {
    static func main() {
        // Top-level code goes here
    }
}

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

protocol ProvidesMain {
    static func main() throws
}

Код Swift, который вы компилируете для создания исполняемого файла, может содержать не более одной точки входа верхнего уровня, как обсуждается в <doc:Declarations#Top-Level-Code>.

nonobjc

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

Применение этого атрибута к расширению имеет тот же эффект, что и его применение ко всем членам этого расширения, которые не помечены явно атрибутом objc.

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

Метод, помеченный атрибутом nonobjc, не может переопределять метод, помеченный атрибутом objc. Однако метод, помеченный атрибутом objc, может переопределять метод, помеченный атрибутом nonobjc. Аналогично, метод, помеченный атрибутом nonobjc, не может удовлетворять требованию протокола для метода, помеченного атрибутом objc.

NSApplicationMain

Устаревшее: Этот атрибут устарел; используйте атрибут <doc:Attributes#main> вместо него. В Swift 6 использование этого атрибута будет ошибкой.

Примените этот атрибут к классу, чтобы указать, что это делегат приложения. Использование этого атрибута эквивалентно вызову функции NSApplicationMain(_:_:).

Если вы не используете этот атрибут, предоставьте файл main.swift с кодом на верхнем уровне, который вызывает функцию NSApplicationMain(_:_:) следующим образом:

import AppKit
NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

Код Swift, который вы компилируете для создания исполняемого файла, может содержать не более одной точки входа верхнего уровня, как обсуждается в <doc:Declarations#Top-Level-Code>.

NSCopying

Примените этот атрибут к хранимому свойству переменной класса. Этот атрибут заставляет установщик свойства синтезироваться с копией значения свойства — возвращаемого методом copyWithZone(_:) — вместо значения самого свойства. Тип свойства должен соответствовать протоколу NSCopying.

Атрибут NSCopying ведет себя аналогично атрибуту свойства Objective-C copy.

NSManaged

Примените этот атрибут к методу экземпляра или хранимому свойству переменной класса, унаследованного от NSManagedObject, чтобы указать, что Core Data динамически предоставляет свою реализацию во время выполнения, на основе связанного описания сущности. Для свойства, помеченного атрибутом NSManaged, Core Data также предоставляет хранилище во время выполнения. Применение этого атрибута также подразумевает атрибут objc.

objc

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

Применение этого атрибута к расширению имеет тот же эффект, что и его применение ко всем членам этого расширения, которые не помечены явно атрибутом nonobjc.

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

Атрибут objc также неявно добавляется в следующих случаях:

  • Объявление является переопределением в подклассе, а объявление суперкласса имеет атрибут objc.
  • Объявление удовлетворяет требованию протокола, который имеет атрибут objc.
  • Объявление имеет атрибуты IBAction, IBSegueAction, IBOutlet, IBDesignable, IBInspectable, NSManaged или GKInspectable.

Если вы применяете атрибут objc к перечислению, каждый случай перечисления экспонируется коду Objective-C как конкатенация имени перечисления и имени случая. Первая буква имени случая заглавная. Например, случай, названный venus в Swift-перечислении Planet, экспонируется коду Objective-C как случай, названный PlanetVenus.

Атрибут objc необязательно принимает один аргумент атрибута, который состоит из идентификатора. Идентификатор указывает имя, которое должно быть экспонировано коду Objective-C для сущности, к которой применяется атрибут objc. Вы можете использовать этот аргумент, чтобы назвать классы, перечисления, случаи перечислений, протоколы, методы, геттеры, сеттеры и инициализаторы. Если вы указываете имя Objective-C для класса, протокола или перечисления, добавьте трехбуквенный префикс к имени, как описано в Конвенции в Программирование с Objective-C. Пример ниже экспонирует геттер для свойства enabled класса ExampleClass коду Objective-C как isEnabled, а не просто как имя самого свойства.

class ExampleClass: NSObject {
    @objc var enabled: Bool {
        @objc(isEnabled) get {
            // Return the appropriate value
        }
    }
}

Дополнительную информацию см. в Импортирование Swift в Objective-C.

Примечание: Аргумент атрибута objc также может изменить имя во время выполнения для данного объявления. Вы используете имя во время выполнения при вызове функций, которые взаимодействуют с Objective-C runtime, например, NSClassFromString(_:), и при указании имен классов в файле Info.plist приложения. Если вы указываете имя, передавая аргумент, это имя используется как имя в Objective-C-коде и как имя во время выполнения. Если вы опустите аргумент, имя, используемое в Objective-C-коде, соответствует имени в Swift-коде, а имя во время выполнения следует стандартной Swift-компиляторной конвенции именования.

objcMembers

Примените этот атрибут к объявлению класса, чтобы неявно применить атрибут objc ко всем совместимым с Objective-C членам класса, его расширений, подклассов и всех расширений его подклассов.

Большинство кода должно использовать атрибут objc вместо этого, чтобы экспонировать только необходимые объявления. Если вам нужно экспонировать много объявлений, вы можете сгруппировать их в расширении, которое имеет атрибут objc. Атрибут objcMembers является удобным способом для библиотек, которые активно используют средства интроспекции Objective-C runtime. Применение атрибута objc, когда он не нужен, может увеличить размер вашего двоичного файла и негативно повлиять на производительность.

preconcurrency

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

  • Импорты
  • Структуры, классы и акторы
  • Перечисления и случаи перечислений
  • Протоколы
  • Переменные и константы
  • Индексные свойства
  • Инициализаторы
  • Функции

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

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

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

  1. Включите строгие проверки.
  2. Добавьте атрибут preconcurrency к импортам для модулей, которые не включили строгие проверки.
  3. После миграции модуля к строгим проверкам удалите атрибут preconcurrency. Компилятор предупредит вас о местах, где атрибут preconcurrency для импорта больше не оказывает эффекта и его следует удалить.

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

Объявления из Objective-C всегда импортируются так, как будто они помечены атрибутом preconcurrency.

propertyWrapper

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

Обёртка должна определить свойство экземпляра wrappedValue. Оборачиваемое значение свойства — это значение, которое отображают методы-геттер и сеттер для этого свойства. В большинстве случаев wrappedValue — это вычисляемое значение, но оно может быть и сохранённым. Обёртка определяет и управляет любым необходимым базовым хранилищем для своего оборачиваемого значения. Компилятор синтезирует хранилище для экземпляра типа обёртки, добавляя префикс «_» к имени оборачиваемого свойства (_) — например, обёртка для someProperty хранится как _someProperty. Синтезированное хранилище обёртки имеет уровень доступа private.

Свойство, имеющее обёртку свойства, может содержать блоки willSet и didSet, но не может переопределять синтезированные компилятором блоки get или set.

Swift предоставляет две формы синтаксического сахара для инициализации обёртки свойства. Можно использовать синтаксис присваивания в определении оборачиваемого значения, чтобы передать выражение в правой части присваивания в качестве аргумента параметру wrappedValue инициализатора обёртки свойства. Также можно указать аргументы атрибута при его применении к свойству, и эти аргументы будут переданы в инициализатор обёртки свойства. Например, в приведенном ниже коде SomeStruct вызывает каждый из инициализаторов, которые определяет wrappedValue.

@propertyWrapper
struct SomeWrapper {
    var wrappedValue: Int
    var someValue: Double
    init() {
        self.wrappedValue = 100
        self.someValue = 12.3
    }
    init(wrappedValue: Int) {
        self.wrappedValue = wrappedValue
        self.someValue = 45.6
    }
    init(wrappedValue value: Int, custom: Double) {
        self.wrappedValue = value
        self.someValue = custom
    }
}

struct SomeStruct {
    // Uses init()
    @SomeWrapper var a: Int

    // Uses init(wrappedValue:)
    @SomeWrapper var b = 10

    // Both use init(wrappedValue:custom:)
    @SomeWrapper(custom: 98.7) var c = 30
    @SomeWrapper(wrappedValue: 30, custom: 98.7) var d
}

Проектируемое значение для оборачиваемого свойства — это второе значение, которое обёртка свойства может использовать для экспонирования дополнительного функционала. Автор типа обёртки свойства отвечает за определение смысла проектируемого значения и интерфейса, который оно экспонирует. Чтобы спроецировать значение из обёртки свойства, определите свойство экземпляра projectedValue в типе обёртки. Компилятор синтезирует идентификатор для проектируемого значения, добавляя префикс «$» к имени оборачиваемого свойства ($) — например, проектируемое значение для someProperty — это $someProperty. Уровень доступа к проектируемому значению совпадает с уровнем доступа к исходному оборачиваемому свойству.

@propertyWrapper
struct WrapperWithProjection {
    var wrappedValue: Int
    var projectedValue: SomeProjection {
        return SomeProjection(wrapper: self)
    }
}
struct SomeProjection {
    var wrapper: WrapperWithProjection
}

struct SomeStruct {
    @WrapperWithProjection var x = 123
}
let s = SomeStruct()
s.x           // Int value
s.$x          // SomeProjection value
s.$x.wrapper  // WrapperWithProjection value

resultBuilder

Примените этот атрибут к классу, структуре или перечислению, чтобы использовать этот тип в качестве билдера результатов. Билдер результатов — это тип, который поэтапно строит вложенную структуру данных. Вы используете билдеры результатов для реализации языка доменной области (DSL) для создания вложенных структур данных естественным и декларативным способом. Пример использования атрибута resultBuilder см. в <doc:AdvancedOperators#Result-Builders>.

Методы построения результата

Билдер результатов реализует статические методы, описанные ниже. Поскольку весь функционал билдера результатов предоставляется через статические методы, вы никогда не инициализируете экземпляр этого типа. Билдер результатов должен реализовать либо метод buildBlock(_:), либо оба метода buildPartialBlock(first:) и buildPartialBlock(accumulated:next:). Другие методы, которые предоставляют дополнительный функционал в DSL, необязательны. В объявлении типа билдера результатов фактически не обязательно указывать соответствие протоколу.

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

Методы построения блоков:

  • метод static func buildBlock(_ components: Component...) -> Component: Объединяет массив частичных результатов в один частичный результат.

  • метод static func buildPartialBlock(first: Component) -> Component: Строит компонент частичного результата из первого компонента. Реализуйте этот метод и метод buildPartialBlock(accumulated:next:), чтобы поддерживать построение блоков по одному компоненту за раз. В сравнении с buildBlock(_:) этот подход снижает необходимость в универсальных перегрузках, обрабатывающих разное количество аргументов.

  • метод static func buildPartialBlock(accumulated: Component, next: Component) -> Component: Строит компонент частичного результата путём объединения накопленного компонента с новым компонентом. Реализуйте этот метод и метод buildPartialBlock(first:), чтобы поддерживать построение блоков по одному компоненту за раз. В сравнении с buildBlock(_:) этот подход снижает необходимость в универсальных перегрузках, обрабатывающих разное количество аргументов.

Билдер результатов может реализовать все три метода построения блоков, перечисленных выше; в этом случае доступность определяет, какой метод будет вызван. По умолчанию Swift вызывает методы buildPartialBlock(first:) и buildPartialBlock(accumulated:next:). Чтобы Swift вызывал метод buildBlock(_:) вместо этого, отметьте окружающее объявление как доступное раньше доступности, указанной в buildPartialBlock(first:) и buildPartialBlock(accumulated:next:).

Дополнительные методы построения результатов:

  • метод static func buildOptional(_ component: Component?) -> Component: Строит частичный результат из частичного результата, который может быть nil. Реализуйте этот метод, чтобы поддержать операторы if, не содержащие клаузу else.

  • метод static func buildEither(first: Component) -> Component: Строит частичный результат, значение которого зависит от некоторого условия. Реализуйте этот метод и метод buildEither(second:), чтобы поддержать операторы switch и операторы if, включающие клаузу else.

  • метод static func buildEither(second: Component) -> Component: Строит частичный результат, значение которого зависит от некоторого условия. Реализуйте этот метод и метод buildEither(first:), чтобы поддержать операторы switch и операторы if, включающие клаузу else.

  • метод static func buildArray(_ components: [Component]) -> Component: Строит частичный результат из массива частичных результатов. Реализуйте этот метод, чтобы поддержать циклы for.

  • метод static func buildExpression(_ expression: Expression) -> Component: Строит частичный результат из выражения. Вы можете реализовать этот метод для выполнения предварительной обработки — например, преобразования выражений в внутренний тип — или для предоставления дополнительной информации для вывода типов в местах использования.

  • метод static func buildFinalResult(_ component: Component) -> FinalResult: Строит итоговый результат из частичного результата. Вы можете реализовать этот метод в рамках билдера результатов, который использует разные типы для частичного и итогового результатов, или для выполнения другой постобработки результата перед его возвращением.

  • метод static func buildLimitedAvailability(_ component: Component) -> Component: Строит частичный результат, стирающий информацию о типе. Вы можете реализовать этот метод, чтобы предотвратить распространение информации о типе за пределы управляемого компилятором оператора, который выполняет проверку доступности.

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

@resultBuilder
struct ArrayBuilder {
    typealias Component = [Int]
    typealias Expression = Int
    static func buildExpression(_ element: Expression) -> Component {
        return [element]
    }
    static func buildOptional(_ component: Component?) -> Component {
        guard let component = component else { return [] }
        return component
    }
    static func buildEither(first component: Component) -> Component {
        return component
    }
    static func buildEither(second component: Component) -> Component {
        return component
    }
    static func buildArray(_ components: [Component]) -> Component {
        return Array(components.joined())
    }
    static func buildBlock(_ components: Component...) -> Component {
        return Array(components.joined())
    }
}

Преобразования результатов

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

  • Если у билдера результатов есть метод buildExpression(_:), каждое выражение преобразуется в вызов этого метода. Эта трансформация всегда выполняется первой. Например, следующие объявления эквивалентны:

    @ArrayBuilder var builderNumber: [Int] { 10 }
    var manualNumber = ArrayBuilder.buildExpression(10)
  • Оператор присваивания преобразуется как выражение, но считается, что он вычисляется в (). Вы можете определить перегрузку buildExpression(_:), принимающую аргумент типа (), чтобы специально обработать присваивания.

  • Оператор ветвления, проверяющий условие доступности, превращается в вызов метода buildLimitedAvailability(_:), если этот метод реализован. Если вы не реализуете метод buildLimitedAvailability(_:), то операторы ветвления, проверяющие доступность, преобразуются так же, как и другие операторы ветвления. Эта трансформация происходит перед преобразованием в вызов buildEither(first:), buildEither(second:) или buildOptional(_:).

    Вы используете метод buildLimitedAvailability(_:) для удаления информации о типе, которая меняется в зависимости от выбранного ветвления. Например, методы buildEither(first:) и buildEither(second:) ниже используют обобщённый тип, который захватывает информацию о типе для обоих ветвей.

    protocol Drawable {
        func draw() -> String
    }
    struct Text: Drawable {
        var content: String
        init(_ content: String) { self.content = content }
        func draw() -> String { return content }
    }
    struct Line<D: Drawable>: Drawable {
        var elements: [D]
        func draw() -> String {
            return elements.map { $0.draw() }.joined(separator: "")
        }
    }
    struct DrawEither<First: Drawable, Second: Drawable>: Drawable {
        var content: Drawable
        func draw() -> String { return content.draw() }
    }
    
    @resultBuilder
    struct DrawingBuilder {
        static func buildBlock<D: Drawable>(_ components: D...) -> Line<D> {
            return Line(elements: components)
        }
        static func buildEither<First, Second>(first: First)
                -> DrawEither<First, Second> {
            return DrawEither(content: first)
        }
        static func buildEither<First, Second>(second: Second)
                -> DrawEither<First, Second> {
            return DrawEither(content: second)
        }
    }

    Однако этот подход создаёт проблему в коде с проверками доступности:

    @available(macOS 99, *)
    struct FutureText: Drawable {
        var content: String
        init(_ content: String) { self.content = content }
        func draw() -> String { return content }
    }
    @DrawingBuilder var brokenDrawing: Drawable {
        if #available(macOS 99, *) {
            FutureText("Inside.future")  // Problem
        } else {
            Text("Inside.present")
        }
    }
    // The type of brokenDrawing is Line<DrawEither<Line<FutureText>, Line<Text>>>

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

    Чтобы решить эту проблему, реализуйте метод buildLimitedAvailability(_:) для стирания информации о типе, возвращая тип, который всегда доступен. Например, код ниже создаёт значение AnyDrawable из проверки доступности.

    struct AnyDrawable: Drawable {
        var content: Drawable
        func draw() -> String { return content.draw() }
    }
    extension DrawingBuilder {
        static func buildLimitedAvailability(_ content: some Drawable) -> AnyDrawable {
            return AnyDrawable(content: content)
        }
    }
    
    @DrawingBuilder var typeErasedDrawing: Drawable {
        if #available(macOS 99, *) {
            FutureText("Inside.future")
        } else {
            Text("Inside.present")
        }
    }
    // The type of typeErasedDrawing is Line<DrawEither<AnyDrawable, Line<Text>>>
  • Оператор ветвления преобразуется в серию вложенных вызовов методов buildEither(first:) и buildEither(second:). Условия и варианты оператора отображаются на листья двоичного дерева, и оператор превращается во вложенный вызов методов buildEither, следуя пути от корня до этого листа.

    Например, если вы используете оператор switch с тремя случаями, компилятор использует двоичное дерево с тремя листьями. Также, поскольку путь от корня к второму случаю — «второй потомок», а затем «первый потомок», этот случай становится вложенным вызовом, как buildEither(first: buildEither(second: ... )). Следующие объявления эквивалентны:

    let someNumber = 19
    @ArrayBuilder var builderConditional: [Int] {
        if someNumber < 12 {
            31
        } else if someNumber == 19 {
            32
        } else {
            33
        }
    }
    
    var manualConditional: [Int]
    if someNumber < 12 {
        let partialResult = ArrayBuilder.buildExpression(31)
        let outerPartialResult = ArrayBuilder.buildEither(first: partialResult)
        manualConditional = ArrayBuilder.buildEither(first: outerPartialResult)
    } else if someNumber == 19 {
        let partialResult = ArrayBuilder.buildExpression(32)
        let outerPartialResult = ArrayBuilder.buildEither(second: partialResult)
        manualConditional = ArrayBuilder.buildEither(first: outerPartialResult)
    } else {
        let partialResult = ArrayBuilder.buildExpression(33)
        manualConditional = ArrayBuilder.buildEither(second: partialResult)
    }
  • Оператор ветвления, который может не возвращать значение, например, оператор if без условия else, преобразуется в вызов buildOptional(_:). Если условие оператора if выполняется, его блок кода преобразуется и передаётся в качестве аргумента; в противном случае вызывается buildOptional(_:) с nil в качестве аргумента. Например, следующие объявления эквивалентны:

    @ArrayBuilder var builderOptional: [Int] {
        if (someNumber % 2) == 1 { 20 }
    }
    
    var partialResult: [Int]? = nil
    if (someNumber % 2) == 1 {
        partialResult = ArrayBuilder.buildExpression(20)
    }
    var manualOptional = ArrayBuilder.buildOptional(partialResult)
  • Если билдер результатов реализует методы buildPartialBlock(first:) и buildPartialBlock(accumulated:next:), блок кода или оператор do становятся вызовами этих методов. Первое выражение внутри блока преобразуется в аргумент метода buildPartialBlock(first:), а остальные выражения становятся вложенными вызовами метода buildPartialBlock(accumulated:next:). Например, следующие объявления эквивалентны:

    struct DrawBoth<First: Drawable, Second: Drawable>: Drawable {
        var first: First
        var second: Second
        func draw() -> String { return first.draw() + second.draw() }
    }
    
    @resultBuilder
    struct DrawingPartialBlockBuilder {
        static func buildPartialBlock<D: Drawable>(first: D) -> D {
            return first
        }
        static func buildPartialBlock<Accumulated: Drawable, Next: Drawable>(
            accumulated: Accumulated, next: Next
        ) -> DrawBoth<Accumulated, Next> {
            return DrawBoth(first: accumulated, second: next)
        }
    }
    
    @DrawingPartialBlockBuilder var builderBlock: some Drawable {
        Text("First")
        Line(elements: [Text("Second"), Text("Third")])
        Text("Last")
    }
    
    let partialResult1 = DrawingPartialBlockBuilder.buildPartialBlock(first: Text("first"))
    let partialResult2 = DrawingPartialBlockBuilder.buildPartialBlock(
        accumulated: partialResult1,
        next: Line(elements: [Text("Second"), Text("Third")])
    )
    let manualResult = DrawingPartialBlockBuilder.buildPartialBlock(
        accumulated: partialResult2,
        next: Text("Last")
    )
  • В противном случае блок кода или оператор do преобразуется в вызов метода buildBlock(_:). Каждое выражение внутри блока преобразуется поочерёдно и становится аргументом метода buildBlock(_:). Например, следующие объявления эквивалентны:

    @ArrayBuilder var builderBlock: [Int] {
        100
        200
        300
    }
    
    var manualBlock = ArrayBuilder.buildBlock(
        ArrayBuilder.buildExpression(100),
        ArrayBuilder.buildExpression(200),
        ArrayBuilder.buildExpression(300)
    )
  • Цикл for становится временной переменной, циклом for и вызовом метода buildArray(_:). Новый цикл for проходит по последовательности и добавляет каждый частичный результат в массив. Временный массив передаётся в качестве аргумента в вызов buildArray(_:). Например, следующие объявления эквивалентны:

    @ArrayBuilder var builderArray: [Int] {
        for i in 5...7 {
            100 + i
        }
    }
    
    var temporary: [[Int]] = []
    for i in 5...7 {
        let partialResult = ArrayBuilder.buildExpression(100 + i)
        temporary.append(partialResult)
    }
    let manualArray = ArrayBuilder.buildArray(temporary)
  • Если билдер результатов имеет метод buildFinalResult(_:), окончательный результат становится вызовом этого метода. Эта трансформация всегда выполняется последней.

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

Вы не можете использовать операторы break, continue, defer, guard или return, операторы while или операторы do-catch в коде, преобразуемом билдером результатов.

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

Когда это возможно, трансформации объединяются. Например, выражение 4 + 5 * 6 превращается в buildExpression(4 + 5 * 6), а не в несколько вызовов этой функции. Аналогично, вложенные операторы ветвления превращаются в единое двоичное дерево вызовов методов buildEither.

Атрибуты пользовательского билдера результатов

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

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

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

requires_stored_property_inits

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

testable

Примените этот атрибут к объявлению import, чтобы импортировать этот модуль с изменениями в его контроле доступа, которые упрощают тестирование кода модуля. Сущности в импортированном модуле, помеченные модификатором уровня доступа internal, импортируются так, как будто они были объявлены с модификатором уровня доступа public. Классы и члены классов, помеченные модификаторами доступа internal или public, импортируются так, как будто они были объявлены с модификатором уровня доступа open. Импортированный модуль должен быть скомпилирован с включённым тестированием.

UIApplicationMain

Устаревшее: Этот атрибут устарел; используйте атрибут <doc:Attributes#main> вместо него. В Swift 6 использование этого атрибута будет ошибкой.

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

Если вы не используете этот атрибут, предоставьте файл main.swift с кодом в верхней части, который вызывает функцию UIApplicationMain(_:_:_:_:). Например, если ваше приложение использует пользовательский подкласс UIApplication в качестве основного класса, вызовите функцию UIApplicationMain(_:_:_:_:) вместо использования этого атрибута.

Код Swift, который вы компилируете для создания исполняемого файла, может содержать не более одной точки входа верхнего уровня, как обсуждается в <doc:Declarations#Top-Level-Code>.

unchecked

Примените этот атрибут к типу протокола в качестве части списка принятых протоколов объявления типа, чтобы отключить проверку требований этого протокола.

Поддерживается только протокол Sendable.

usableFromInline

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

Подобно модификатору доступа public, этот атрибут экспонирует объявление как часть публичного интерфейса модуля. В отличие от public, компилятор не позволяет ссылаться на объявления, помеченные как usableFromInline, по имени в коде за пределами модуля, даже если символ объявления экспортирован. Однако код за пределами модуля всё ещё может взаимодействовать со символом объявления с помощью поведения во время выполнения.

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

warn_unqualified_access

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

Например, стандартная библиотека Swift включает как функцию верхнего уровня min(_:_:), так и метод min() для последовательностей с сопоставимыми элементами. Метод последовательности объявлен с атрибутом warn_unqualified_access, чтобы уменьшить путаницу при попытке использовать один или другой из них внутри расширения Sequence.

Атрибуты объявлений, используемые интерфейсным билдером

Атрибуты Interface Builder — это атрибуты объявления, используемые Interface Builder для синхронизации с Xcode. Swift предоставляет следующие атрибуты Interface Builder: IBAction, IBSegueAction, IBOutlet, IBDesignable и IBInspectable. Эти атрибуты концептуально аналогичны своим аналогам в Objective-C.

Вы применяете атрибуты IBOutlet и IBInspectable к объявлениям свойств класса. Вы применяете атрибуты IBAction и IBSegueAction к объявлениям методов класса и атрибут IBDesignable к объявлениям классов.

Применение атрибутов IBAction, IBSegueAction, IBOutlet, IBDesignable или IBInspectable также подразумевает атрибут objc.

Атрибуты типов

Вы можете применять атрибуты типов только к типам.

autoclosure

Примените этот атрибут, чтобы отложить вычисление выражения, автоматически обернув его в замыкание без аргументов. Вы применяете его к типу параметра в объявлении функции или метода, для параметра, тип которого — функция без аргументов, возвращающая значение типа выражения. Пример использования атрибута autoclosure см. в <doc:Closures#Autoclosures> и <doc:Types#Function-Type>.

convention

Примените этот атрибут к типу функции, чтобы указать её соглашения вызова.

Атрибут convention всегда используется с одним из следующих аргументов:

  • Аргумент swift указывает на ссылку на Swift-функцию. Это стандартное соглашение вызова для значений функций в Swift.
  • Аргумент block указывает на ссылку на блок, совместимый с Objective-C. Значение функции представляется как ссылка на объект блока, который является объектом Objective-C, совместимым с id, содержащим в себе функцию вызова. Функция вызова использует соглашение вызова C.
  • Аргумент c указывает на ссылку на C-функцию. Значение функции не несёт контекста и использует соглашение вызова C.

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

escaping

Примените этот атрибут к типу параметра в объявлении функции или метода, чтобы указать, что значение параметра может быть сохранены для последующего выполнения. Это означает, что значение может существовать дольше, чем период выполнения вызова. Параметры типа функции с атрибутом типа escaping требуют явного использования self. для свойств или методов. Пример использования атрибута escaping см. в <doc:Closures#Escaping-Closures>.

Sendable

Примените этот атрибут к типу функции, чтобы указать, что функция или замыкание являются sendable. Применение этого атрибута к типу функции эквивалентно соответствию не-функционального типа протоколу Sendable.

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

Тип sendable функции является подтипом соответствующего nonsendable типа функции.

Атрибуты switch-case

Вы можете применять атрибуты switch-case только к switch-case.

unknown

Примените этот атрибут к switch-case, чтобы указать, что он не ожидается для соответствия любому случаю перечисления, известному на момент компиляции кода. Пример использования атрибута unknown см. в <doc:Statements#Switching-Over-Future-Enumeration-Cases>.

Грамматика атрибута:

attribute → @ attribute-name attribute-argument-clause_?_
attribute-name → identifier
attribute-argument-clause → ( balanced-tokens_?_ )
attributes → attribute attributes_?_

balanced-tokens → balanced-token balanced-tokens_?_
balanced-token → ( balanced-tokens_?_ )
balanced-token → [ balanced-tokens_?_ ]
balanced-token → { balanced-tokens_?_ }
balanced-token → Любой идентификатор, ключевое слово, литерал или оператор
balanced-token → Любой знак препинания, кроме (, ), [, ], { или }

This source file is part of the Swift.org open source project
Copyright © 2014 - 2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API