import Combine import CoreData import CoreFoundation import CoreGraphics import Darwin import DeveloperToolsSupport import Foundation import SwiftUI import UIKit import UniformTypeIdentifiers import os.log import os import os.signpost /// An object that publishes its changes. /// /// ### Understanding `ObservableObject` /// /// The `ObservableObject` protocol definition is as follows: /// /// ``` /// public protocol ObservableObject: AnyObject { /// associatedtype ObjectWillChangePublisher: Publisher /// /// var objectWillChange: ObjectWillChangePublisher { get } /// } /// ``` /// /// `ObservableObject` has one simple requirement - the `objectWillChange` /// publisher. The `objectWillChange` publisher is responsible for emitting just /// before the object changes. /// /// This requirement is fundamental to how the SwiftUI runtime interacts with /// your object-based data models. It allows the runtime to react to changes /// in your data, and queue view updates for the UI's next render cycle. /// /// ### Using `ObservableObject` /// /// To conform to `ObservableObject`, simply add it to the class definition. /// /// ``` /// class AppModel: ObservableObject { /// @Published var foo: Bool = false /// } /// ``` /// /// `ObservableObject` provides a default implementation for ``ObservableObject/objectWillChange`` /// using `Combine/ObservableObjectPublisher`. /// /// To trigger `objectWillChange` events when your data changes, annotate your /// properties with the `@Published` property wrapper. Adding `@Published` to a /// variable causes the object to emit an `objectWillChange` event any time that /// variable is modified. /// /// Note: This only works if you are using the default `ObservableObject` /// implementation, or if `objectWillChange` is an instance of /// `ObservableObjectPublisher`. If you use a custom `Publisher` type, you are /// responsible for triggering updates yourself. /// /// ### Manually triggering `objectWillChange` /// /// You can also manually trigger updates by calling /// `ObservableObjectPublisher/send()`. /// /// This is useful for cases where `@Published` does not suffice. For example: /// /// ``` /// class AppModel: ObservableObject { /// class ChildModel { /// var foo: String = "Apple" /// } /// /// var childModel = ChildModel() /// /// func updateChildModel() { /// childModel.foo = "Banana" /// /// objectWillChange.send() /// } /// } /// ``` /// /// In this example, `AppModel` holds a reference to a child model, /// `ChildModel`. Adding a `@Published` to the `childModel` variable would /// have no effect because `ChildModel` is a class and not a value type. /// Therefore, to emit a change event, you must manually call /// `objectWillChange.send()` when updating the child model. /// /// ### Using a custom publisher /// /// In some cases, you may want to use a custom `Publisher` type for /// `objectWillChange`. For example: /// /// ``` /// class AppModel: ObservableObject { /// public let objectWillChange = PassthroughSubject() /// } /// ``` /// /// This example uses a ``Combine/PassthroughSubject`` for its `objectWillChange` /// requirement. A passthrough subject is a publisher that lets you send values /// manually (i.e. "passes through" any values sent to it). /// /// - Note: The `@Published` property wrapper does not work with custom /// publishers. If you use a custom publisher, you are responsible for updating /// the object yourself. For example: /// /// ``` /// class AppModel: ObservableObject { /// public let objectWillChange = PassthroughSubject() /// /// var foo: Bool = false { /// willSet { /// objectWillChange.send() /// } /// } /// } /// ``` /// /// Here `objectWillChange.send()` is manually called everytime `foo` is about /// to update, using the `willSet` observer. /// /// ### Using `ObservableObject` with SwiftUI /// /// An observable object can be used to drive changes in a ``View``, via three /// property wrapper types: /// /// - `@ObservedObject` /// - `@EnvironmentObject` /// - `@StateObject` /// /// #### Usage with `@StateObject` /// /// ![7EA88B2E-3B0C-4306-AF48-2D2D14818823](7EA88B2E-3B0C-4306-AF48-2D2D14818823.png) /// ``` /// class AppModel: ObservableObject { /// @Published var foo: Bool = false /// } /// /// struct ContentView: View { /// @StateObject var appModel = AppModel() /// /// var body: some View { /// Toggle("Foo", isOn: $appModel.foo) /// } /// } /// ``` /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public protocol ObservableObject : AnyObject { /// The type of publisher that emits before the object has changed. associatedtype ObjectWillChangePublisher : Publisher = ObservableObjectPublisher where Self.ObjectWillChangePublisher.Failure == Never /// A publisher that emits before the object has changed. var objectWillChange: Self.ObjectWillChangePublisher { get } } /// AccessibilityActionKind denotes the type of action for an Accessibility Action to support. /// /// This struct is almost always found as an input to the /// ``View/accessibilityAction(_:_:)`` View modifier. /// To learn more about delivering exceptional accessibility experiences, /// see /// [Delivering an Exceptional Accessibility Experience](https://developer.apple.com/documentation/uikit/accessibility_for_ios_and_tvos/delivering_an_exceptional_accessibility_experience) /// or /// [iOS Accessibility Tutorial](https://www.raywenderlich.com/4720178-ios-accessibility-tutorial-making-custom-controls-accessible). @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct AccessibilityActionKind : Equatable { /// The inferred accessibility action inherited from the view type. /// /// This constant will default to the accessibility action associated with the modified object. /// For example, a button, label, or text would all default to their unique accessibility behaviors. public static let `default`: AccessibilityActionKind /// A two finger scrub gesture performed while VoiceOver focus is on or inside the component. public static let escape: AccessibilityActionKind /// A double tap with two fingers while VoiceOver focus is on or inside the component. @available(iOS 13.0, tvOS 13.0, watchOS 6.0, *) @available(macOS, unavailable) public static let magicTap: AccessibilityActionKind /// Initialize an ``AccessibilityActionKind`` with the name of the action type. /// /// An example of an accessibility action name could be "Open address in Maps" or /// "Call Fred" where "Fred" is a string variable. When VoiceOver is on the iPhone /// will read this name to the user. public init(named name: Text) { } /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (a: AccessibilityActionKind, b: AccessibilityActionKind) -> Bool { } } /// A directional indicator you use when making an accessibility adjustment. @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public enum AccessibilityAdjustmentDirection { /// Increment an adjustable component. /// /// VoiceOver generates this action when the component has a role of /// `adjustable` and the user places focus on it and swipes upward. case increment /// Decrement an adjustable component. /// /// VoiceOver generates this action when the component has a role of /// `adjustable` and the user places focus on it and swipes downward. case decrement /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (a: AccessibilityAdjustmentDirection, b: AccessibilityAdjustmentDirection) -> Bool { } /// The hash value. /// /// Hash values are not guaranteed to be equal across different executions of /// your program; do not save hash values to use during a future execution. /// /// - Important: `hashValue` is deprecated as a `Hashable` requirement. To /// conform to `Hashable`, implement the `hash(into:)` requirement instead. public var hashValue: Int { get } /// Hashes the essential components of this value by feeding them into the /// given hasher. /// /// Implement this method to conform to the `Hashable` protocol. The /// components used for hashing must be the same as the components compared /// in your type's `==` operator implementation. Call `hasher.combine(_:)` /// with each of these components. /// /// - Important: Never call `finalize()` on `hasher`. Doing so may become a /// compile-time error in the future. /// /// - Parameter hasher: The hasher to use when combining the components /// of this instance. public func hash(into hasher: inout Hasher) { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AccessibilityAdjustmentDirection : Equatable { } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AccessibilityAdjustmentDirection : Hashable { } /// A ``ViewModifier`` used to provide accessibility content. /// /// The ``AccessibilityAttachmentModifier`` is most commonly found as the /// modified content in an accessibility modifiers attached to a View. /// See ``View/accessibilityAction(_:_:)`` for example usage. See /// [Creating Accessible Views](https://developer.apple.com/documentation/swiftui/view/accessibility/creating_accessible_views?changes=_8) /// for an example accessibility project. @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct AccessibilityAttachmentModifier : ViewModifier { /// The type of view representing the body. public typealias Body = Never } /// Defines the children's behavior of accessibility elements. /// /// See /// [Accessibility in SwiftUI](https://swiftwithmajid.com/2019/09/10/accessibility-in-swiftui/) /// for more information on implementing accessibility functionality. @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct AccessibilityChildBehavior : Hashable { /// Hashes the essential components of this value by feeding them into the /// given hasher. /// /// Implement this method to conform to the `Hashable` protocol. The /// components used for hashing must be the same as the components compared /// in your type's `==` operator implementation. Call `hasher.combine(_:)` /// with each of these components. /// /// - Important: Never call `finalize()` on `hasher`. Doing so may become a /// compile-time error in the future. /// /// - Parameter hasher: The hasher to use when combining the components /// of this instance. public func hash(into hasher: inout Hasher) { } /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (lhs: AccessibilityChildBehavior, rhs: AccessibilityChildBehavior) -> Bool { } /// The hash value. /// /// Hash values are not guaranteed to be equal across different executions of /// your program. Do not save hash values to use during a future execution. /// /// - Important: `hashValue` is deprecated as a `Hashable` requirement. To /// conform to `Hashable`, implement the `hash(into:)` requirement instead. public var hashValue: Int { get } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AccessibilityChildBehavior { /// Child accessibility elements are ignored public static let ignore: AccessibilityChildBehavior /// Any child accessibility elements become children of the new /// accessibility element public static let contain: AccessibilityChildBehavior /// Combine any child accessibility element's properties for the /// new accessibility element public static let combine: AccessibilityChildBehavior } /// Pair related views such that one view serves as the view content, and one /// view serves as the view label. /// /// ``AccessibilityLabeledPairRole`` is almost always used in conjunction with the ``View/accessibilityLabeledPair(role:id:in:)`` modifier. @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) @frozen public enum AccessibilityLabeledPairRole { /// This element represents the label part of the label / content pair. /// /// For example, it might be the explanatory text to the left of a control, /// describing what the control does. case label /// This element represents the content part of the label / content pair. /// /// For example, it might be the custom control itself. case content /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (a: AccessibilityLabeledPairRole, b: AccessibilityLabeledPairRole) -> Bool { } } extension AccessibilityLabeledPairRole : Hashable { /// The hash value. /// /// Hash values are not guaranteed to be equal across different executions of /// your program. Do not save hash values to use during a future execution. /// /// - Important: `hashValue` is deprecated as a `Hashable` requirement. To /// conform to `Hashable`, implement the `hash(into:)` requirement instead. public var hashValue: Int { get } /// Hashes the essential components of this value by feeding them into the /// given hasher. /// /// Implement this method to conform to the `Hashable` protocol. The /// components used for hashing must be the same as the components compared /// in your type's `==` operator implementation. Call `hasher.combine(_:)` /// with each of these components. /// /// - Important: Never call `finalize()` on `hasher`. Doing so may become a /// compile-time error in the future. /// /// - Parameter hasher: The hasher to use when combining the components /// of this instance. public func hash(into hasher: inout Hasher) { } } /// A struct used to define the characteristics of a view when accessed for /// accessibility. /// /// `AccessibilityTraits` are almost always used in conjunction with the /// ``View/accessibilityAddTraits(_:)`` view modifier. /// They are used to tell an assistive accessibility application (such as /// VoiceOver) /// how an element should be treated. /// /// For example: /// /// ``` /// struct ExampleView: View { /// var body: some View { /// Button("I'm a button! 😏") { /// // Do something on button click /// } /// .accessibilityAddTraits(.isButton) /// } /// } /// ``` /// /// ![6014639F-AD04-4B82-9FD7-EECD9109F555](6014639F-AD04-4B82-9FD7-EECD9109F555.png) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct AccessibilityTraits : SetAlgebra { /// The accessibility element is a button. public static let isButton: AccessibilityTraits /// The accessibility element is a header that divides content into sections, /// like the title of a navigation bar. public static let isHeader: AccessibilityTraits /// The accessibility element is currently selected. public static let isSelected: AccessibilityTraits /// The accessibility element is a link. public static let isLink: AccessibilityTraits /// The accessibility element is a search field. public static let isSearchField: AccessibilityTraits /// The accessibility element is an image. public static let isImage: AccessibilityTraits /// The accessibility element plays its own sound when activated. public static let playsSound: AccessibilityTraits /// The accessibility element behaves as a keyboard key. public static let isKeyboardKey: AccessibilityTraits /// The accessibility element is a static text that cannot be modified by the user. public static let isStaticText: AccessibilityTraits /// The accessibility element provides summary information when the application starts. /// /// Use this trait to characterize an accessibility element that provides a summary of /// current conditions, settings, or state, like the temperature in the Weather app. public static let isSummaryElement: AccessibilityTraits /// The accessibility element frequently updates its label or value. /// /// Include this trait when you want an assistive application to poll for changes /// when it needs updated information. For example, you might use this trait to /// characterize the readout of a stopwatch. public static let updatesFrequently: AccessibilityTraits /// The accessibility element starts a media session when it is activated. /// /// Use this trait to silence the audio output of an assistive technology, /// such as VoiceOver, during a media session that should not be interrupted. /// For example, you might use this trait to silence VoiceOver speech while the user is recording audio. public static let startsMediaSession: AccessibilityTraits /// The accessibility element allows direct touch interaction for VoiceOver users. public static let allowsDirectInteraction: AccessibilityTraits /// The accessibility element causes an automatic page turn when VoiceOver finishes reading the text within it. public static let causesPageTurn: AccessibilityTraits /// The siblings of this accessibility element will be ignored by accessibility. public static let isModal: AccessibilityTraits /// Creates an empty set. /// /// This initializer is equivalent to initializing with an empty array /// literal. For example, you create an empty `Set` instance with either /// this initializer or with an empty array literal. /// /// var emptySet = Set() /// print(emptySet.isEmpty) /// // Prints "true" /// /// emptySet = [] /// print(emptySet.isEmpty) /// // Prints "true" public init() { } /// Adds the elements of the given set to the set. /// /// In the following example, the elements of the `visitors` set are added to /// the `attendees` set: /// /// var attendees: Set = ["Alicia", "Bethany", "Diana"] /// let visitors: Set = ["Diana", "Marcia", "Nathaniel"] /// attendees.formUnion(visitors) /// print(attendees) /// // Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]" /// /// If the set already contains one or more elements that are also in /// `other`, the existing members are kept. /// /// var initialIndices = Set(0..<5) /// initialIndices.formUnion([2, 3, 6, 7]) /// print(initialIndices) /// // Prints "[2, 4, 6, 7, 0, 1, 3]" /// /// - Parameter other: A set of the same type as the current set. public mutating func formUnion(_ other: AccessibilityTraits) { } /// Returns a new set with the elements that are common to both this set and /// the given set. /// /// In the following example, the `bothNeighborsAndEmployees` set is made up /// of the elements that are in *both* the `employees` and `neighbors` sets. /// Elements that are in only one or the other are left out of the result of /// the intersection. /// /// let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"] /// let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"] /// let bothNeighborsAndEmployees = employees.intersection(neighbors) /// print(bothNeighborsAndEmployees) /// // Prints "["Bethany", "Eric"]" /// /// - Parameter other: A set of the same type as the current set. /// - Returns: A new set. /// /// - Note: if this set and `other` contain elements that are equal but /// distinguishable (e.g. via `===`), which of these elements is present /// in the result is unspecified. public func intersection(_ other: AccessibilityTraits) -> AccessibilityTraits { } /// Removes the elements of this set that aren't also in the given set. /// /// In the following example, the elements of the `employees` set that are /// not also members of the `neighbors` set are removed. In particular, the /// names `"Alicia"`, `"Chris"`, and `"Diana"` are removed. /// /// var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"] /// let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"] /// employees.formIntersection(neighbors) /// print(employees) /// // Prints "["Bethany", "Eric"]" /// /// - Parameter other: A set of the same type as the current set. public mutating func formIntersection(_ other: AccessibilityTraits) { } /// Returns a new set with the elements that are either in this set or in the /// given set, but not in both. /// /// In the following example, the `eitherNeighborsOrEmployees` set is made up /// of the elements of the `employees` and `neighbors` sets that are not in /// both `employees` *and* `neighbors`. In particular, the names `"Bethany"` /// and `"Eric"` do not appear in `eitherNeighborsOrEmployees`. /// /// let employees: Set = ["Alicia", "Bethany", "Diana", "Eric"] /// let neighbors: Set = ["Bethany", "Eric", "Forlani"] /// let eitherNeighborsOrEmployees = employees.symmetricDifference(neighbors) /// print(eitherNeighborsOrEmployees) /// // Prints "["Diana", "Forlani", "Alicia"]" /// /// - Parameter other: A set of the same type as the current set. /// - Returns: A new set. public func symmetricDifference(_ other: AccessibilityTraits) -> AccessibilityTraits { } /// Removes the elements of the set that are also in the given set and adds /// the members of the given set that are not already in the set. /// /// In the following example, the elements of the `employees` set that are /// also members of `neighbors` are removed from `employees`, while the /// elements of `neighbors` that are not members of `employees` are added to /// `employees`. In particular, the names `"Bethany"` and `"Eric"` are /// removed from `employees` while the name `"Forlani"` is added. /// /// var employees: Set = ["Alicia", "Bethany", "Diana", "Eric"] /// let neighbors: Set = ["Bethany", "Eric", "Forlani"] /// employees.formSymmetricDifference(neighbors) /// print(employees) /// // Prints "["Diana", "Forlani", "Alicia"]" /// /// - Parameter other: A set of the same type. public mutating func formSymmetricDifference(_ other: AccessibilityTraits) { } /// Returns a Boolean value that indicates whether the given element exists /// in the set. /// /// This example uses the `contains(_:)` method to test whether an integer is /// a member of a set of prime numbers. /// /// let primes: Set = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37] /// let x = 5 /// if primes.contains(x) { /// print("\(x) is prime!") /// } else { /// print("\(x). Not prime.") /// } /// // Prints "5 is prime!" /// /// - Parameter member: An element to look for in the set. /// - Returns: `true` if `member` exists in the set; otherwise, `false`. public func contains(_ member: AccessibilityTraits) -> Bool { } /// Returns a new set with the elements of both this and the given set. /// /// In the following example, the `attendeesAndVisitors` set is made up /// of the elements of the `attendees` and `visitors` sets: /// /// let attendees: Set = ["Alicia", "Bethany", "Diana"] /// let visitors = ["Marcia", "Nathaniel"] /// let attendeesAndVisitors = attendees.union(visitors) /// print(attendeesAndVisitors) /// // Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]" /// /// If the set already contains one or more elements that are also in /// `other`, the existing members are kept. /// /// let initialIndices = Set(0..<5) /// let expandedIndices = initialIndices.union([2, 3, 6, 7]) /// print(expandedIndices) /// // Prints "[2, 4, 6, 7, 0, 1, 3]" /// /// - Parameter other: A set of the same type as the current set. /// - Returns: A new set with the unique elements of this set and `other`. /// /// - Note: if this set and `other` contain elements that are equal but /// distinguishable (e.g. via `===`), which of these elements is present /// in the result is unspecified. public func union(_ other: AccessibilityTraits) -> AccessibilityTraits { } /// Removes the given element and any elements subsumed by the given element. /// /// - Parameter member: The element of the set to remove. /// - Returns: For ordinary sets, an element equal to `member` if `member` is /// contained in the set; otherwise, `nil`. In some cases, a returned /// element may be distinguishable from `newMember` by identity comparison /// or some other means. /// /// For sets where the set type and element type are the same, like /// `OptionSet` types, this method returns any intersection between the set /// and `[member]`, or `nil` if the intersection is empty. public mutating func remove(_ member: AccessibilityTraits) -> AccessibilityTraits? { } /// Inserts the given element in the set if it is not already present. /// /// If an element equal to `newMember` is already contained in the set, this /// method has no effect. In this example, a new element is inserted into /// `classDays`, a set of days of the week. When an existing element is /// inserted, the `classDays` set does not change. /// /// enum DayOfTheWeek: Int { /// case sunday, monday, tuesday, wednesday, thursday, /// friday, saturday /// } /// /// var classDays: Set = [.wednesday, .friday] /// print(classDays.insert(.monday)) /// // Prints "(true, .monday)" /// print(classDays) /// // Prints "[.friday, .wednesday, .monday]" /// /// print(classDays.insert(.friday)) /// // Prints "(false, .friday)" /// print(classDays) /// // Prints "[.friday, .wednesday, .monday]" /// /// - Parameter newMember: An element to insert into the set. /// - Returns: `(true, newMember)` if `newMember` was not contained in the /// set. If an element equal to `newMember` was already contained in the /// set, the method returns `(false, oldMember)`, where `oldMember` is the /// element that was equal to `newMember`. In some cases, `oldMember` may /// be distinguishable from `newMember` by identity comparison or some /// other means. public mutating func insert(_ newMember: AccessibilityTraits) -> (inserted: Bool, memberAfterInsert: AccessibilityTraits) { } /// Inserts the given element into the set unconditionally. /// /// If an element equal to `newMember` is already contained in the set, /// `newMember` replaces the existing element. In this example, an existing /// element is inserted into `classDays`, a set of days of the week. /// /// enum DayOfTheWeek: Int { /// case sunday, monday, tuesday, wednesday, thursday, /// friday, saturday /// } /// /// var classDays: Set = [.monday, .wednesday, .friday] /// print(classDays.update(with: .monday)) /// // Prints "Optional(.monday)" /// /// - Parameter newMember: An element to insert into the set. /// - Returns: For ordinary sets, an element equal to `newMember` if the set /// already contained such a member; otherwise, `nil`. In some cases, the /// returned element may be distinguishable from `newMember` by identity /// comparison or some other means. /// /// For sets where the set type and element type are the same, like /// `OptionSet` types, this method returns any intersection between the /// set and `[newMember]`, or `nil` if the intersection is empty. public mutating func update(with newMember: AccessibilityTraits) -> AccessibilityTraits? { } /// A type for which the conforming type provides a containment test. public typealias Element = AccessibilityTraits /// The type of the elements of an array literal. public typealias ArrayLiteralElement = AccessibilityTraits /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (a: AccessibilityTraits, b: AccessibilityTraits) -> Bool { } } /// A storage type for an action sheet presentation. /// /// Use this structure with the ``View/actionSheet(item:content:)`` and /// ``View/actionSheet(ispresented:content:)`` view modifiers to present /// the user with an **action sheet**. /// /// ### What is an action sheet? /// /// An ``ActionSheet`` is a modal alert that appears towards the bottom /// of a user's screen. It provides **two or more** options /// to the user based on the app context. /// /// An ``ActionSheet`` is similar to an ``Alert``, but it appears at the bottom /// of the screen instead of in the middle. To let the user respond /// to the **state** of the app, use an ``Alert`` instead. /// /// - Note: See Apple's /// [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/ios/views/action-sheets/) /// for more about when to use action sheets. /// /// ### Creating an action sheet /// /// Creating an action sheet involves 3 components: /// 1. A **title**, which is in bold font at the top of the sheet /// 2. A **message**, which is optional, and appears under the title /// 3. An **array of buttons**, which determine what the user can do from the /// action sheet. /// /// The buttons can take 3 styles: ``Alert/Button/cancel(_:action:)`` /// ``Alert/Button/default(_:action:)``, and /// ``Alert/Button/destructive(_:action:)``. /// Check out ``Alert/Button`` for the full overview of action sheet buttons, /// the available styles, and how to create them. /// /// ### Using an action sheet /// /// Once you have an action sheet, it is simple to use. Just pass /// it as a trailing closure to the ``View/actionSheet(ispresented:content:)`` /// view modifier. The action sheet will be presented whenever /// the `isPresented` binding parameter is `true`. /// /// The following example passes an ``ActionSheet`` to this view modifier, /// and illustrates the 3 different types of /// action sheet buttons. /// /// ``` /// struct ContentView: View { /// @State private var showActionSheet = false /// /// var body: some View { /// Button("Eat 🍌") { /// showActionSheet = true /// } /// .actionSheet(isPresented: $showActionSheet) { /// ActionSheet( /// title: Text("Food alert!"), /// message: Text("You have made a selection"), /// buttons: [ /// .cancel(), /// .destructive(Text("Change to 🍑")) { /* override */ }, /// .default(Text("Confirm")) { /* confirm */ } /// ] /// ) /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a button reading "Eat 🍌", that once pressed /// triggers the appearance of an action sheet titled "Food alert" with two /// options, "Change to 🍑" and "Confirm", and a text message beneath the title /// reading "You have made a selection".](action-sheet-main-ex.gif) /// /// Notes: /// - The system can override your button order. In the example above, /// the cancel button is displayed last, because that is customary. /// - If your action sheet requires a parameter, you can pass one in by /// using the ``View/actionSheet(item:content:)`` view modifier instead. /// @available(iOS 13.0, tvOS 13.0, watchOS 6.0, *) @available(macOS, unavailable) public struct ActionSheet { /// Creates an action sheet with the provided buttons. public init(title: Text, message: Text? = nil, buttons: [ActionSheet.Button] = [.cancel()]) { } /// A button representing an operation of an action sheet presentation. public typealias Button = Alert.Button } /// A representation for an alert presentation. /// /// An ``Alert`` is a modal-like presentation which contains a title, message, and /// between one and two action buttons. Alerts often convey important information /// about the state of the app and typically request feedback from the user. While the /// styling of alerts is semi-fixed, there are three available styles for the buttons to choose from: /// ``Alert/Button/default(_:action:)``, ``Alert/Button/destructive(_:action:)``, /// and ``Alert/Button/cancel(_:action:)``. To actually present an alert, see /// ``View/alert(isPresented:content:)``. /// /// An alert can be created with one of two initializers, depending on if one button /// or two is required. For example, to create an Alert with one button: /// /// ``` /// struct ExampleAlertView: View { /// @State private var showAlert = false /// /// var body: some View { /// Button("Tap to view alert") { /// showAlert = true /// } /// .alert(isPresented: $showAlert) { /// Alert( /// title: Text("An important title!"), /// message: Text("A message that adds additional context on the alert.") /// ) /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a button reading "Tap to view alert", that /// once pressed triggers the appearance of an alert titled "An important title!" /// with the text message "A message that adds additional context on the alert." a /// and an "OK" button that hides the alert when pressed.](alert-example-1.gif) /// /// If the `dismissButton` value is left unspecified (as it was in this example), /// it will default to a dismiss button with the text "Ok". /// /// In order to customize the type of button (or to create an alert with two buttons), /// create a new ``Alert/Button`` instance and pass it in as a part of the initializer. /// For example, to make an alert with a cancel and destructive button: /// /// /// ``` /// struct ExampleAlertView: View { /// @State private var showAlert = false /// /// var body: some View { /// Button("Tap to view alert") { /// showAlert = true /// } /// .alert(isPresented: $showAlert) { /// Alert( /// title: Text("Are you sure?"), /// message: Text("The following action will delete everything. Please confirm."), /// primaryButton: Alert.Button.destructive(Text("Delete")), /// secondaryButton: Alert.Button.cancel(Text("No, take me back!")) /// ) /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a button reading "Tap to view alert", that /// once pressed triggers the appearance of an alert titled "Are you sure?" /// with the text message "The following action will delete everything. Please /// confirm."; the alert has two buttons, a primary destructive button reading /// "Delete" and a secondary cancel button reading "No, take me back!"](alert-example-2.gif) /// /// For illustrative purposes, the alert button values used the expanded syntax in this example. /// It is also valid to use the shorthand syntax when declaring alert buttons: `.default(_:action:)`, /// `.cancel(_:)`, or `.destructive(_:action:)` /// /// Notes: /// - Stylistically, `.default` and `.cancel` alert button styles are nearly identical with /// the exception that `.cancel` has a bolded font weight. /// - Alert is the equivalent to UIKit's [`UIAlertController`](https://developer.apple.com/documentation/uikit/uialertcontroller). /// - For information on the human interface guidelines for alerts, see: /// [https://developer.apple.com/design/human-interface-guidelines/ios/views/alerts/](https://developer.apple.com/design/human-interface-guidelines/ios/views/alerts/) @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct Alert { /// Creates an alert with one button. /// /// If the `dismissButton` parameter is left unspecified, it will default to a button with the text "Ok". /// /// For example, to create a new Alert with this initializer and present it: /// /// ``` /// struct ExampleAlertView: View { /// @State private var showAlert = false /// /// var body: some View { /// Button("Tap to view alert") { /// showAlert = true /// } /// .alert(isPresented: $showAlert) { /// Alert( /// title: Text("An important title!"), /// message: Text("A message that adds additional context on the alert."), /// dismissButton: .default(Text("I understand.")) /// ) /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a button reading "Tap to view alert", that /// once pressed triggers the appearance of an alert titled "An important title!" /// with the text message "A message that adds additional context on the alert." /// and a default dismiss button that reads "I understand".](alert-example-3.gif) /// public init(title: Text, message: Text? = nil, dismissButton: Alert.Button? = nil) { } /// Creates an alert with two buttons. /// /// When the screen is too small to display both buttons horizontally, they will /// switch to being vertically stacked. The system determines the visual /// ordering of the buttons based on their type and /// if they are a primary or secondary button. /// /// For example, to create a new Alert with this initializer and present it: /// /// ``` /// struct ExampleAlertView: View { /// @State private var showAlert = false /// /// var body: some View { /// Button("Tap to view alert") { /// showAlert = true /// } /// .alert(isPresented: $showAlert) { /// Alert( /// title: Text("Are you sure?"), /// message: Text("The following action will delete everything. Please confirm."), /// primaryButton: .destructive(Text("Delete")), /// secondaryButton: .cancel(Text("No, take me back!")) /// ) /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a button reading "Tap to view alert", that /// once pressed triggers the appearance of an alert titled "Are you sure?" /// with the text message "The following action will delete everything. Please /// confirm."; the alert has two buttons, a primary destructive button reading /// "Delete" and a secondary cancel button reading "No, take me back!"](alert-example-2.gif) /// public init(title: Text, message: Text? = nil, primaryButton: Alert.Button, secondaryButton: Alert.Button) { } /// A button representing an ``Alert`` button action. public struct Button { /// Creates an ``Alert/Button`` with the default style. The `.default` alert /// button is styled nearly identically with `.cancel` except that `.cancel` /// has a bolded font weight. /// /// For example, to create a new alert button with the default style: /// /// ``` /// Alert( /// title: Text("An important title!"), /// message: Text("A message that adds additional context on the alert."), /// dismissButton: .default(Text("A default button"), action: { /// print("Default button pressed, do something.") /// }) /// ) /// ``` public static func `default`(_ label: Text, action: (() -> Void)? = {}) -> Alert.Button { } /// Creates an ``Alert/Button`` that indicates cancellation of some /// operation. The `.cancel` alert button is styled nearly identically with /// `.default` except that `.cancel` has a bolded font weight. /// /// For example, to create a new alert button with the cancel style: /// /// ``` /// Alert( /// title: Text("An important title!"), /// message: Text("A message that adds additional context on the alert."), /// dismissButton: .cancel(Text("A cancel button"), action: { /// print("Cancel button pressed, do something.") /// }) /// ) /// ``` public static func cancel(_ label: Text, action: (() -> Void)? = {}) -> Alert.Button { } /// Creates an ``Alert/Button`` that indicates cancellation of some /// operation. The `.cancel` alert button is styled nearly identically with /// `.default` except that `.cancel` has a bolded font weight. /// /// The system automatically chooses the label of the button for the appropriate locale. /// For the English locale, this defaults to "Cancel" /// /// For example, to create a new alert button with the cancel style: /// /// ``` /// Alert( /// title: Text("An important title!"), /// message: Text("A message that adds additional context on the alert."), /// dismissButton: .cancel(action: { /// print("Cancel button pressed, do something.") /// }) /// ) /// ``` public static func cancel(_ action: (() -> Void)? = {}) -> Alert.Button { } /// Creates an ``Alert/Button`` with a style indicating destruction of /// some data. /// /// For example, to create a new alert button with the destructive style: /// /// ``` /// Alert( /// title: Text("An important title!"), /// message: Text("A message that adds additional context on the alert."), /// dismissButton: .destructive(Text("A destructive button"), action: { /// print("Destructive button pressed, do something.") /// }) /// ) /// ``` public static func destructive(_ label: Text, action: (() -> Void)? = {}) -> Alert.Button { } } } /// An alignment in both axes. /// /// Use this structure to align a view when it has both a vertical and /// horizontal degree of freedom. /// /// ### What is an `Alignment`? /// /// An alignment is made up of 2 properties: /// 1. The ``Alignment/vertical`` alignment, of type ``VerticalAlignment`` /// 2. The ``Alignment/horizontal`` alignment, of type ``HorizontalAlignment`` /// /// Each of those axes have their own options and initializers. To /// create an ``Alignment``, you can set both properties directly /// using the initializer, /// or choose one of ``Alignment``'s static properties. /// /// #### The ``Alignment`` initializer /// /// You can also create your own alignments from the /// ``Alignment/init(horizontal:vertical:)`` initializer /// /// - Note: The /// clear color is added to expand the view to the entire screen, /// so that the alignment movement can be seen /// /// ``` /// struct ContentView: View { /// let alignment = Alignment(horizontal: .center, vertical: .top) /// /// var body: some View { /// ZStack(alignment: alignment) { /// Text("I'm top aligned 🤠") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with center horizontal alignment and top /// vertical alignment and the text "I'm top aligned 🤠"; The text /// is displayed at the top center of the frame.](alignment-initalizer.png) /// /// #### The ``Alignment`` static properties /// /// There are 9 out-of-the-box alignments: /// 1. ``Alignment/topLeading`` /// 2. ``Alignment/top`` /// 3. ``Alignment/topTrailing`` /// 4. ``Alignment/leading`` /// 5. ``Alignment/center`` /// 6. ``Alignment/trailing`` /// 7. ``Alignment/bottomLeading`` /// 8. ``Alignment/bottom`` /// 9. ``Alignment/bottomTrailing`` /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack(alignment: Alignment.bottomLeading) { //Try changing this! /// Text("Move me around 🤠") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with bottomLeading alignment and the text /// "Move me around 🤠"; The text is displayed in the bottom left corner of /// the frame.](alignment-bottom-leading.png) /// /// ### Using an ``Alignment`` /// /// This structure is used in 4 places: /// - ``ZStack``, in the initializer /// - ``View/overlay(_:alignment:)``, in the view modifier /// - ``View/background(_:alignment:)``, in the view modifier /// - ``View/frame(width:height:alignment:)``, in the view modifier /// /// ``` /// struct ContentView: View { /// var body: some View { /// Color.clear /// .background( /// Text("Move me around 🤠"), /// alignment: .leading /// ) /// } /// } /// ``` /// /// ![A view containing a clear background with the text view "Move me around /// 🤠" and text alignment leading; The text is displayed on the /// leftmost edge halfway down the frame.](alignment-leading.png) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct Alignment : Equatable { /// The alignment on the horizontal axis. /// /// An ``Alignment`` is simply a combination of a vertical alignment /// and a horizontal alignment. This is the ``HorizontalAlignment`` /// component. /// /// This is usually specified indirectly using one of the pre-defined /// alignments or through the ``Alignment/init(horizontal:vertical)`` /// initializer. However, you can also specify it directly: /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// var alignment = Alignment.topLeading /// alignment.horizontal = .center /// /// return ZStack(alignment: alignment) { /// Text("Move me around 🤠") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view that returns a ZStack with the text "Move me around 🤠" with a /// topLeading vertical alignment and center horizontal alignment; The text /// is displayed at the top center of the frame.](14.11.38.png) /// public var horizontal: HorizontalAlignment /// The alignment on the vertical axis. /// /// An ``Alignment`` is simply a combination of a vertical alignment /// and a horizontal alignment. This is the ``VerticalAlignment`` /// component. /// /// This is usually specified indirectly using one of the pre-defined /// alignments or through the ``Alignment/init(horizontal:vertical:)`` /// initializer. However, you can also specify it directly: /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// var alignment = Alignment.topLeading /// alignment.vertical = .center /// /// return ZStack(alignment: alignment) { /// Text("Move me around 🤠") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view that returns a ZStack with the text "Move me around 🤠" with a /// topLeading horizontal alignment and center vertical alignment; The text /// is displayed at the left edge halfway down the frame.](14.14.47.png) /// public var vertical: VerticalAlignment /// Creates an instance with the given horizontal and vertical alignments. /// /// An ``Alignment`` is simply a combination of a vertical alignment /// and a horizontal alignment. Use this initializer to specify /// the components directly. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// let alignment = Alignment(horizontal: .leading, vertical: .top) /// /// return ZStack(alignment: alignment) { /// Text("Move me around 🤠") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view that returns a ZStack with the text "Move me around 🤠" with a /// leading horizontal alignment and top vertical alignment; The text /// is displayed at the top left corner of the frame.](14.18.52.png) /// /// - Parameters: /// - horizontal: The alignment on the horizontal axis. /// - vertical: The alignment on the vertical axis. @inlinable public init(horizontal: HorizontalAlignment, vertical: VerticalAlignment) { } /// A guide marking the center of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .center) { /// Text("🤠") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "🤠" and center alignment; /// The text is displayed at the very center of the frame.](14.22.04.png) /// public static let center: Alignment /// A guide marking the leading edge of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .leading) { /// Text("⬅️") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "⬅️" and leading alignment; /// The text is displayed at the leftmost edge halfway down the frame.](14.23.18.png) /// public static let leading: Alignment /// A guide marking the trailing edge of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .trailing) { /// Text("➡️") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "➡️" and trailing alignment; /// The text is displayed at the rightmost edge halfway down the frame.](14.27.25.png) /// public static let trailing: Alignment /// A guide marking the top edge of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .top) { /// Text("⬆️") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "⬆️" and top alignment; /// The text is displayed at the topmost edge halfway across the frame.](14.28.22.png) /// public static let top: Alignment /// A guide marking the bottom edge of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .bottom) { /// Text("⬇️") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "⬇️" and top alignment; /// The text is displayed at the bottommost edge halfway across the frame.](14.29.14.png) /// public static let bottom: Alignment /// A guide marking the top and leading edges of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .topLeading) { /// Text("↖️") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "↖️" and topLeading alignment; /// The text is displayed in the top left corner of the frame.](14.30.26.png) /// public static let topLeading: Alignment /// A guide marking the top and trailing edges of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .topTrailing) { /// Text("↖️") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "↖️" and topTrailing alignment; /// The text is displayed in the top right corner of the frame.](14.31.17.png) /// public static let topTrailing: Alignment /// A guide marking the bottom and leading edges of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .bottomLeading) { /// Text("↙️") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "↙️" and bottomLeading alignment; /// The text is displayed in the bottom left corner of the frame.](14.33.12.png) /// public static let bottomLeading: Alignment /// A guide marking the bottom and trailing edges of the view. /// /// ``` /// struct AlignmentView: View { /// var body: some View { /// ZStack(alignment: .bottomTrailing) { /// Text("↘️") /// Color.clear /// } /// } /// } /// ``` /// /// ![A view containing a ZStack with the text "↙️" and bottomTrailing alignment; /// The text is displayed in the bottom right corner of the frame.](14.35.44.png) /// public static let bottomTrailing: Alignment /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (a: Alignment, b: Alignment) -> Bool { } } /// Types used to identify alignment guides. /// /// Use this protocol to create custom alignment guides. Custom /// alignment guides are needed to align views which are not /// in the same container. /// /// To conform to this protocol, there is only one requirement: /// ``AlignmentID/defaultValue(in:)``. /// /// The most convenient way to create a custom alignment is with an /// extension. /// /// A custom vertical alignment: /// /// ``` /// extension VerticalAlignment { /// enum CustomAlignment: AlignmentID { /// static func defaultVAlue(in d: ViewDimensions) -> CGFloat { /// d[VerticalAlignment.center] /// } /// } /// static let custom = VerticalAlignment(CustomAlignment.self) /// } /// ``` /// /// To create a custom alignment for a ``ZStack``, extend both /// ``VerticalAlignment`` and ``HorizontalAlignment``: /// /// ``` /// extension VerticalAlignment { /// enum CustomAlignment: AlignmentID { /// static func defaultVAlue(in d: ViewDimensions) -> CGFloat { /// d[.top] /// } /// } /// static let vertical = VerticalAlignment(CustomAlignment.self) /// } /// /// extension HorizontalAlignment { /// enum CustomAlignment: AlignmentID { /// static func defaultVAlue(in d: ViewDimensions) -> CGFloat { /// d[.leading] /// } /// } /// static let horizontal = HorizontalAlignment(CustomAlignment.self) /// } /// /// extension Alignment { /// static let custom = Alignment(horizontal: .horizontal, vertical: .vertical) /// } /// ``` /// /// For more on creating your own alignments, check out /// [this article](https://swiftui-lab.com/alignment-guides/). @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public protocol AlignmentID { } extension AlignmentID { /// The value of the corresponding guide in the given context when not /// otherwise set in that context. /// /// This is the only requirement of conforming to the ``AlignmentID`` /// protocol. /// /// See ``ViewDimensions`` for information on the parameter of this /// function. /// /// For more on creating your own alignments, check out /// [this article](https://swiftui-lab.com/alignment-guides/). /// /// Here is a simple example of implementing this function: /// /// ``` /// extension VerticalAlignment { /// enum CustomAlignment: AlignmentID { /// static func defaultVAlue(in d: ViewDimensions) -> CGFloat { /// d[VerticalAlignment.center] /// } /// } /// static let custom = VerticalAlignment(CustomAlignment.self) /// } /// ``` /// /// - Parameter context: The view dimensions for aligning the view. /// /// - Returns: A default alignment value for the custom alignment. static func defaultValue(in context: ViewDimensions) -> CGFloat { } } /// An opaque value derived from an anchor source and a particular view. /// /// You can convert the anchor to a `Value` in the coordinate space of a target /// view by using a ``GeometryProxy`` to specify the target view. @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct Anchor { /// A type-erased geometry value that produces an anchored value of a given /// type. /// /// SwiftUI passes anchored geometry values around the view tree via /// preference keys. It then converts them back into the local coordinate /// space using a ``GeometryProxy`` value. @frozen public struct Source { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Anchor.Source where Value == CGRect { /// Returns an anchor source rect defined by `r` in the current view. public static func rect(_ r: CGRect) -> Anchor.Source { } /// An anchor source rect defined as the entire bounding rect of the current /// view. public static var bounds: Anchor.Source { get } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Anchor.Source where Value == CGPoint { /// Returns an anchor source point defined by a point `p` in the current view. /// /// - Parameter p: The `CGPoint` to anchor. public static func point(_ p: CGPoint) -> Anchor.Source { } /// Returns an anchor source point defined by a point `p` in the current view. /// /// - Parameter p: The ``UnitPoint`` to anchor. public static func unitPoint(_ p: UnitPoint) -> Anchor.Source { } /// An anchor source point defined by the top leading corner of the current view. public static var topLeading: Anchor.Source { get } /// An anchor source point defined by the center of the top edge of the current view. public static var top: Anchor.Source { get } /// An anchor source point defined by the top trailing corner of the current view. public static var topTrailing: Anchor.Source { get } /// An anchor source point defined by the center of the leading edge of the current view. public static var leading: Anchor.Source { get } /// An anchor source point defined by the center point of the current view. public static var center: Anchor.Source { get } /// An anchor source point defined by the center of the trailing edge of the current view. public static var trailing: Anchor.Source { get } /// An anchor source point defined by the bottom leading corner of the current view. public static var bottomLeading: Anchor.Source { get } /// An anchor source point defined by the center of the bottom edge of the current view. public static var bottom: Anchor.Source { get } /// An anchor source point defined by the bottom trailing corner of the current view. public static var bottomTrailing: Anchor.Source { get } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Anchor.Source { /// Creates an anchor source with generic type array from an array of anchor source. /// /// - Parameter array: The array of anchor source points. public init(_ array: [Anchor.Source]) where Value == [T] { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Anchor.Source { /// Creates an anchor source with generic type optional from an optional anchor source. /// /// - Parameter anchor: The optional anchor source. public init(_ anchor: Anchor.Source?) where Value == T? { } } /// A geometric angle whose value you access in either radians or degrees. /// /// `Angle`s are used all over SwiftUI to specify a geometric angle. /// Common uses include **rotation** and **drawing**. /// /// ### Creating an `Angle` /// /// You can create an ``Angle`` by using either **radians** or **degrees**. /// Each has an initializer as well as a static method: /// /// - **Radians**: /// - ``Angle/init(radians:)`` /// - ``Angle/radians(_:)`` /// - **Degrees**: /// - ``Angle/init(degrees:)`` /// - ``Angle/degrees(_:)`` /// /// See usage examples below. /// /// ### Using an `Angle` with rotation /// /// `Angles` are commonly used with the ``View/rotationEffect(_:anchor:)`` /// and similar modifiers: /// /// ``` /// struct ContentView: View { /// var body: some View { /// VStack(spacing: 50) { /// Rectangle() /// .frame(width: 100, height: 100) /// .rotationEffect(Angle(degrees: 15)) /// .border(Color.orange) /// Rectangle() /// .frame(width: 100, height: 100) /// .rotationEffect(.degrees(15)) /// .border(Color.orange) /// } /// } /// } /// ``` /// /// ![A view containing a VStack with two rectangle, each with a frame width and /// height of 100, a 15 degree rotation effect, and border color orange, which /// illustrates the rotation by remaining in the original position; one rectangles /// rotation effect is defined by the init modifier and the other with the angle modifier.](angle.png) /// /// ### Using an `Angle` with drawing /// /// `Angle`s can also be used with drawing. Below, we define a custom /// ``Shape`` called `Arc`, and make its parameter type `Angle`. In our /// ``View``, we pass `270` as the degrees parameter to specify the size of /// the `Arc` to be displayed: /// /// ``` /// struct Arc: Shape { /// var endAngle: Angle /// /// func path(in rect: CGRect) -> Path { /// Path { p in /// p.addArc(center: CGPoint(x: rect.midX, y: rect.midY), /// radius: rect.width / 2 , /// startAngle: Angle.zero, /// endAngle: endAngle, /// clockwise: false) /// } /// } /// } /// /// struct ArcView: View { /// var body: some View { /// Arc(endAngle: Angle.degrees(270)) /// .stroke(Color.orange, lineWidth: 20) /// } /// } /// ``` /// /// ![A view containing an arch, which has been defined by a shape struct in the /// code, with stroke color orange and line width 20; the orange arch completes /// 270 degrees of a circle, as defined by the parameter type angle and degrees /// parameter of 270.](angle-2.png) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct Angle { /// The size of the angle, measured in radians. /// /// Usually, this property is specified using the /// ``Angle/init(radians:)`` initializer, or the /// ``Angle/radians(_:)`` static function. /// /// ``` /// struct ContentView: View { /// let angle = Angle(radians: Double.pi / 6) /// /// var body: some View { /// Rectangle() /// .rotationEffect(angle) /// .frame(width: 100, height: 100) /// .border(Color.orange) /// } /// } /// ``` /// /// ![A view containing a rectangle, with a rotation effect defined by an /// radians, a frame width and height of 100, and border color /// orange, which illustrates the clockwise rotation by remaining in the /// original position.](angle-radians.png) /// public var radians: Double /// The size of the angle, measured in degrees. /// /// Usually, this property is specified using the /// ``Angle/init(degrees:)`` initializer, or the /// ``Angle/degrees(_:)`` static function. /// /// ``` /// struct ContentView: View { /// let angle = Angle(degrees: 15) /// /// var body: some View { /// Rectangle() /// .rotationEffect(angle) /// .frame(width: 100, height: 100) /// .border(Color.orange) /// } /// } /// ``` /// /// ![A view containing a rectangle, with a rotation effect defined by an /// degrees, a frame width and height of 100, and border color /// orange, which illustrates the clockwise rotation by remaining in the /// original position.](angle-degrees.png) /// /// @inlinable public var degrees: Double /// Creates an angle of 0 degrees or 0 radians. /// /// ``` /// struct ContentView: View { /// let angle = Angle() /// /// var body: some View { /// Rectangle() /// .rotationEffect(angle) //Does nothing /// .frame(width: 100, height: 100) /// .border(Color.orange) /// } /// } /// ``` /// /// ![A view containing a rectangle, with a rotation effect defined by an /// empty Angle() struct, a frame width and height of 100, and border color /// orange, which illustrates lack of rotation by the rectangle.](angle-zero.png) /// @inlinable public init() { } /// Creates an angle from a specified number of radians. /// /// Use this initializer to create an ``Angle`` of a specified number of `radians`. /// /// ``` /// struct ContentView: View { /// let angle = Angle(radians: Double.pi / 6) /// /// var body: some View { /// Rectangle() /// .rotationEffect(angle) /// .frame(width: 100, height: 100) /// .border(Color.orange) /// } /// } /// ``` /// /// ![A view containing a rectangle, with a rotation effect defined by /// radians in Angle(), a frame width and height of 100, and border color /// orange, which illustrates the clockwise rotation of the /// rectangle by remaining in the original position.](angle-radians.png) /// /// - Parameter radians: The number of radians in the angle. @inlinable public init(radians: Double) { } /// Creates an angle from a specified number of degrees. /// /// Use this initializer to create an ``Angle`` of a specified number of `degrees`. /// /// ``` /// struct ContentView: View { /// let angle = Angle(degrees: 15) /// /// var body: some View { /// Rectangle() /// .rotationEffect(angle) /// .frame(width: 100, height: 100) /// .border(Color.orange) /// } /// } /// ``` /// /// ![A view containing a rectangle, with a rotation effect defined by /// degrees in Angle(), a frame width and height of 100, and border color /// orange, which illustrates the 15 degree clockwise rotation of the rectangle by /// remaining in the original position.](angle-degrees.png) /// /// - Parameter degrees: The number of degrees in the angle. @inlinable public init(degrees: Double) { } /// Changes the size of an angle to a specified number of radians. /// /// This can be a convenient shorthand for the ``Angle/init(radians:)`` /// initializer, especially when the type can be inferred. /// /// ``` /// struct ContentView: View { /// var body: some View { /// Rectangle() /// .rotationEffect(.radians(Double.pi / 6)) /// .frame(width: 100, height: 100) /// .border(Color.orange) /// } /// } /// ``` /// /// ![A view containing a rectangle, with a rotation effect defined by /// radians, a frame width and height of 100, and border color /// orange, which illustrates the clockwise rotation of the rectangle by /// remaining in the original position.](angle-radians.png) /// /// - Parameter radians: The number of radians the new angle should be. @inlinable public static func radians(_ radians: Double) -> Angle { } /// Changes the size of an angle to a specified number of degrees. /// /// This can be a convenient shorthand for the ``Angle/init(degrees:)`` /// initializer, especially when the type can be inferred. /// /// ``` /// struct ContentView: View { /// var body: some View { /// Rectangle() /// .rotationEffect(.degrees(15)) /// .frame(width: 100, height: 100) /// .border(Color.orange) /// } /// } /// ``` /// /// ![A view containing a rectangle, with a rotation effect defined by /// degrees, a frame width and height of 100, and border color /// orange, which illustrates the clockwise rotation of the rectangle by /// remaining in the original position](angle-degrees.png) /// /// - Parameter degrees: The number of degrees the new angle should be. @inlinable public static func degrees(_ degrees: Double) -> Angle { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Angle : Hashable, Comparable { /// Returns a Boolean value indicating whether the value of the first /// argument is less than that of the second argument. /// /// This function is the only requirement of the `Comparable` protocol. The /// remainder of the relational operator functions are implemented by the /// standard library for any type that conforms to `Comparable`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. @inlinable public static func < (lhs: Angle, rhs: Angle) -> Bool { } /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (a: Angle, b: Angle) -> Bool { } /// The hash value. /// /// Hash values are not guaranteed to be equal across different executions of /// your program. Do not save hash values to use during a future execution. /// /// - Important: `hashValue` is deprecated as a `Hashable` requirement. To /// conform to `Hashable`, implement the `hash(into:)` requirement instead. public var hashValue: Int { get } /// Hashes the essential components of this value by feeding them into the /// given hasher. /// /// Implement this method to conform to the `Hashable` protocol. The /// components used for hashing must be the same as the components compared /// in your type's `==` operator implementation. Call `hasher.combine(_:)` /// with each of these components. /// /// - Important: Never call `finalize()` on `hasher`. Doing so may become a /// compile-time error in the future. /// /// - Parameter hasher: The hasher to use when combining the components /// of this instance. public func hash(into hasher: inout Hasher) { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Angle : Animatable { /// The data to animate. public var animatableData: Double /// Creates an angle of 0 degrees or 0 radians. /// /// This static property can be a convenient shorthand for /// the ``Angle/init()`` initializer, especially when the /// type can be inferred: /// /// ``` /// struct ContentView: View { /// var body: some View { /// Rectangle() /// .rotationEffect(.zero) // Does nothing /// .frame(width: 100, height: 100) /// .border(Color.orange) /// } /// } /// ``` /// /// ![A view containing a rectangle, with a rotation effect defined by /// the zero type property, a frame width and height of 100, and border color /// orange, which illustrates the lack of rotation of the rectangle.](angle-zero.png) /// @inlinable public static var zero: Angle { get } /// The type defining the data to animate. public typealias AnimatableData = Double } /// An angular gradient. /// /// An angular gradient is also known as a "conic" gradient. This gradient /// applies the color function as the angle changes, relative to a center point /// and defined start and end angles. If `endAngle - startAngle > 2π`, the /// gradient only draws the last complete turn. If `endAngle - startAngle < 2π`, /// the gradient fills the missing area with the colors defined by gradient /// locations one and zero, transitioning between the two halfway across the /// missing area. The gradient maps the unit-space center point into the /// bounding rectangle of each shape filled with the gradient. /// /// There are 3 main cases where AngularGradient can change: /// 1. `endAngle - startAngle = 2π` /// 2. `endAngle - startAngle > 2π` /// 3. `endAngle - startAngle < 2π` /// /// Note: Angles default to a clockwise rotation, but angles can be a negative /// value which will rotate the color counter-clockwise. /// /// ## End Angle - Start Angle = 2π /// /// This is the normal case where the start and end angles make a complete circle. /// Every color will evenly distribute. /// /// ``` /// struct AngularGradientView: View { /// let colors: [Color] = [.yellow, .red,.blue, .purple] /// /// var body: some View { /// Rectangle() /// .fill(AngularGradient(gradient: Gradient(colors: colors), center: .center)) /// .frame(width:200, height:200) /// } /// } /// ``` /// /// ![A view containing a rectangle with a frame of width and height 200 and an /// angular gradient fill in which the end and start angles make a complete /// circle; this results in a square that fades from yellow to red to blue to /// purple starting and the center and going clockwise.](491E0F0F-86BB-4B03-B05A-C6ABEA7CDC13.png) /// /// ## End Angle - Start Angle > 2π /// /// This is the case where the total angle is greater than a circle. /// The gradient will only draw the last complete turn which effectively writes /// over the first circle portion. /// /// ``` /// struct AngularGradientView: View { /// let colors: [Color] = [.yellow, .red,.blue, .purple] /// /// var body: some View { /// VStack { /// Rectangle() /// .fill(AngularGradient(gradient: Gradient(colors: colors), center: .center)) /// .frame(width:200, height:200) /// Rectangle() /// .fill(AngularGradient(gradient: Gradient(colors: colors), center: .center,startAngle: .degrees(0), endAngle: .degrees(360 + 45))) /// .frame(width:200, height:200) /// } /// } /// } /// ``` /// /// ![A view containing a VStack with two rectangles, one with an angular /// gradient fill in which the end and start angles make a complete /// circle and the other in which the total angle is greater than a circle; /// this results in both squares fading from yellow to red to blue to /// purple, one starting at the center and the other at the bottom right corner.](89BED914-29DA-4009-9EA1-96E1849E55F0.png) /// /// ## End Angle - Start Angle < 2π /// /// This is the case where the total angle is less than a circle. /// The gradient will not make a complete circle, but the missing area between /// the start and end will be evenly colored with the /// first and last color of the gradient. /// /// ``` /// struct AngularGradientView: View { /// let colors: [Color] = [.yellow, .red,.blue, .purple] /// /// var body: some View { /// VStack { /// Rectangle() /// .fill(AngularGradient(gradient: Gradient(colors: colors), center: .center)) /// .frame(width:200, height:200) /// Rectangle() /// .fill(AngularGradient(gradient: Gradient(colors: colors), center: .center,startAngle: .degrees(0), endAngle: .degrees(180))) /// .frame(width:200, height:200) /// } /// } /// } /// ``` /// /// ![A view containing a VStack with two rectangles, one with an angular /// gradient fill in which the end and start angles make a complete /// circle and the other in which the total angle is less than a circle; /// this results in both squares fading from yellow to red to blue to /// purple, one starting at the center and the other at the top center.](94015C67-FC57-44CC-9EA4-F982A47AEB7D.png) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct AngularGradient : ShapeStyle, View { /// Creates an angular gradient from a starting and ending angle. /// /// Gradient behavior acts differently according to whether the end angle - /// start angle is greater than, less than or equal to 2π. /// See ``AngularGradient`` for more information. /// An example, /// /// ``` /// struct AngularGradientView: View { /// let colors: [Color] = [.yellow, .red,.blue, .purple] /// /// var body: some View { /// VStack { /// Rectangle() /// .fill(AngularGradient(gradient: Gradient(colors: colors), center: .center)) /// .frame(width:200, height:200) /// Rectangle() /// .fill(AngularGradient(gradient: Gradient(colors: colors), center: .center,startAngle: .degrees(0), endAngle: .degrees(180))) /// .frame(width:200, height:200) /// } /// } /// } /// ``` /// /// ![A view containing a VStack with two rectangles, one with an angular /// gradient fill in which the end and start angles make a complete /// circle and the other in which the total angle is less than a circle; /// this results in both squares fading from yellow to red to blue to /// purple, one starting at the center and the other at the top center.](angular-gradient-example-3.png) /// /// - Parameters: /// - gradient: The gradient with the colors to use. /// - center: The unit point that is center of the angular gradient. /// - startAngle: The ``Angle`` where the gradient starts. Defaults to zero. /// - endAngle: The ``Angle`` where the gradient ends. Defaults to zero. public init(gradient: Gradient, center: UnitPoint, startAngle: Angle = .zero, endAngle: Angle = .zero) { } /// Creates an angular gradient starting at and angle and going all the way around in a circle. /// /// For example, /// /// ``` /// struct ExampleView: View { /// let colors: [Color] = [.yellow, .red,.blue, .purple] /// /// var body: some View { /// Rectangle() /// .fill(AngularGradient(gradient: Gradient(colors: colors), center: .center)) /// .frame(width:200, height:200) /// } /// } /// ``` /// /// ![A view containing a rectangle with a frame of width and height 200 and an /// angular gradient fill in which the end and start angles make a complete /// circle; this results in a square that fades from yellow to red to blue to /// purple starting at the center and going clockwise.](angular-gradient-example-1.png) /// /// - Parameters: /// - gradient: The gradient with the colors to use. /// - center: The unit point that is center of the angular gradient. /// - angle: The ``Angle`` where the gradient starts. Defaults to zero. public init(gradient: Gradient, center: UnitPoint, angle: Angle = .zero) { } /// The type of view representing the body of this view. /// /// When you create a custom view, Swift infers this type from your /// implementation of the required `body` property. public typealias Body } /// Animate a view when data changes. /// /// ``Animatable`` describes how to animate a view with respect to some change /// in the view's data. /// /// Use `Animatable` when you are unable to achieve the animation you want with /// ``View/animation(_:)`` or ``withAnimation(_:_:)``. /// /// `Animatable` allows fine-grained control over the animation of a SwiftUI /// view's animatable values. It does so by requiring /// `animatableData: AnimatableData', which represents a view's animatable data. /// /// By conforming to ``Animatable``, you are able to effectively **decouple** /// the animation of your view from the concept of *duration*, as you give /// SwiftUI the ability to interpolate arbitrarily between two different values /// for ``Animatable/animatableData-7101d``. This is also the reason why /// ``Animatable/AnimatableData`` must conform to ``VectorArithmetic``, /// which provides the runtime means to add, subtract and scale the animated /// values as necessary to generate data points for each frame of the animation /// over an arbitrary time interval. /// [animatable-modifier ->] /// ### Implementations /// /// #### Using ``AnimatableModifier`` to implement a shake effect /// /// ``Animatable`` is best used via `AnimatableModifier`, which is nothing but /// a simple protocol that combines ``Animatable`` and ``ViewModifier``. This /// allows you to decouple the animation effect from the view you want to /// animate. /// /// For example: /// /// ``` /// struct ExampleView: View { /// @State var numberOfShakes: CGFloat = 0 /// /// var body: some View { /// VStack { /// Text("Banana🍌🍌") /// .font(.largeTitle) /// .modifier(ShakeEffect(shakeNumber: numberOfShakes)) /// .onAppear { /// withAnimation(.easeIn(duration: 2.0)) { /// numberOfShakes = 10 /// } /// } /// } /// } /// } /// /// struct ShakeEffect: AnimatableModifier { /// var shakeNumber: CGFloat = 0 /// /// var animatableData: CGFloat { /// get { /// shakeNumber /// } set { /// shakeNumber = newValue /// } /// } /// /// func body(content: Content) -> some View { /// content /// .offset(x: sin(shakeNumber * .pi * 2) * 10) /// } /// } /// ``` ///![A gif that displays a VStack containing the text "Banana🍌🍌", which has /// been animated to shake side to side / left to right ten times.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/Animatable-example-1.gif) /// /// /// This example demonstrates a horizontal "shake effect", applied on a /// ``Text``. When run, the text animates by shaking 10 times. This is achieved /// by triggering an animation using ``withAnimation(_:_:)``, and modifying the /// `shakeNumber` to go from `0` to `10`. /// /// Note: /// - `shakeNumber` represents the *progress* of the animation. The SwiftUI /// runtime can set this value through ``Animatable/animatableData-7101d``, /// and it can be any value between the initial and the final value (`0.0` /// and `10.0` in this case). /// - `shakeNumber` is a `CGFloat` and not an `Int`. This is because the /// runtime needs to be able to interpolate fractionally between `0.0` and /// `10.0` 'shakes' - and it does so by making use of `CGFloat`'s /// ``VectorArithmetic`` conformance. /// - The exact mathematical function used to interpolate `shakeNumber` is /// determined by what type of ``Animation`` is used in /// ``withAnimation(_:_:)``, to animate the change from `0` shakes to `10` /// shakes. /// /// #### Using ``AnimatableModifier`` to continuously animate a view along a circle /// /// ``AnimatableModifier``, used with /// ``Animation/repeatForever(autoreverses:)`` can also be used to create a /// continuous animation. /// /// ``` /// struct ExampleView: View { /// @State var progress: CGFloat = 0 /// /// var body: some View { /// VStack { /// Text("Banana🍌🍌") /// .font(.largeTitle) /// .modifier(CircleAnimation(radius: 24, progress: progress)) /// .onAppear { /// withAnimation(Animation.easeInOut(duration: 2.0).repeatForever(autoreverses: false)) { /// progress = 1.0 /// } /// } /// } /// } /// } /// /// struct CircleAnimation: AnimatableModifier { /// let radius: CGFloat /// var progress: CGFloat = 0 /// /// var animatableData: CGFloat { /// get { /// progress /// } set { /// progress = newValue /// } /// } /// /// func body(content: Content) -> some View { /// content.offset( /// x: radius * cos(progress * (2 * CGFloat.pi)), /// y: radius * sin(progress * (2 * CGFloat.pi)) /// ) /// } /// } /// ``` /// /// ![A gif that displays a VStack containing the text "Banana🍌🍌", which /// has been animated to endlessly move in a circular motion around the view.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/Animatable-example-2.gif) /// /// In this example, `Text("Banana🍌🍌")` is animated along a circle continuously. /// /// `CircleAnimation` is an implementation of an ``AnimatableModifier`` that /// uses a simple mathematical function to calculate the `x` and `y` offset of /// a view, given a radius and a progress value between `0.0` and `1.0`. /// /// When the view appears, the `CircleAnimation` modifier is animated from a /// progress value of `0.0` to `1.0` using ``withAnimation(_:_:)``. The /// ``Animation`` used in ``withAnimation(_:_:)`` is modified using /// ``Animation/repeatForever(autoreverses:)``, in order to create a loop. /// Note that ``Animation/repeatForever(autoreverses:)`` is explicitly set as /// `false` to prevent the animation from being reversed. /// [<-] /// ### Further notes /// /// - ``Animatable`` along with ``View`` is currently broken on iOS 14, /// please use ``AnimatableModifier`` /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public protocol Animatable { } extension Animatable { /// The type defining the data to animate. associatedtype AnimatableData : VectorArithmetic /// The data to animate. var animatableData: Self.AnimatableData { get /*set*/ } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animatable where Self : VectorArithmetic { /// The data to animate. public var animatableData: Self } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animatable where Self.AnimatableData == EmptyAnimatableData { /// The data to animate. public var animatableData: EmptyAnimatableData } /// A modifier that can create another modifier with animation. /// /// ``AnimatableModifier`` is closely coupled with ``Animatable``. /// /// [[animatable-modifier]] @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public protocol AnimatableModifier : Animatable, ViewModifier { } extension AnimatableModifier : Animatable, ViewModifier { } /// A pair of animatable values, which is itself animatable. @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct AnimatablePair : VectorArithmetic where First : VectorArithmetic, Second : VectorArithmetic { /// The first value. public var first: First /// The second value. public var second: Second /// Creates an animated pair with the provided values. @inlinable public init(_ first: First, _ second: Second) { } /// The zero value. /// /// Zero is the identity element for addition. For any value, /// `x + .zero == x` and `.zero + x == x`. public static var zero: AnimatablePair { get } /// Adds two values and stores the result in the left-hand-side variable. /// /// - Parameters: /// - lhs: The first value to add. /// - rhs: The second value to add. public static func += (lhs: inout AnimatablePair, rhs: AnimatablePair) { } /// Subtracts the second value from the first and stores the difference in the /// left-hand-side variable. /// /// - Parameters: /// - lhs: A numeric value. /// - rhs: The value to subtract from `lhs`. public static func -= (lhs: inout AnimatablePair, rhs: AnimatablePair) { } /// Adds two values and produces their sum. /// /// The addition operator (`+`) calculates the sum of its two arguments. For /// example: /// /// 1 + 2 // 3 /// -10 + 15 // 5 /// -15 + -5 // -20 /// 21.5 + 3.25 // 24.75 /// /// You cannot use `+` with arguments of different types. To add values of /// different types, convert one of the values to the other value's type. /// /// let x: Int8 = 21 /// let y: Int = 1000000 /// Int(x) + y // 1000021 /// /// - Parameters: /// - lhs: The first value to add. /// - rhs: The second value to add. public static func + (lhs: AnimatablePair, rhs: AnimatablePair) -> AnimatablePair { } /// Subtracts one value from another and produces their difference. /// /// The subtraction operator (`-`) calculates the difference of its two /// arguments. For example: /// /// 8 - 3 // 5 /// -10 - 5 // -15 /// 100 - -5 // 105 /// 10.5 - 100.0 // -89.5 /// /// You cannot use `-` with arguments of different types. To subtract values /// of different types, convert one of the values to the other value's type. /// /// let x: UInt8 = 21 /// let y: UInt = 1000000 /// y - UInt(x) // 999979 /// /// - Parameters: /// - lhs: A numeric value. /// - rhs: The value to subtract from `lhs`. public static func - (lhs: AnimatablePair, rhs: AnimatablePair) -> AnimatablePair { } /// Multiplies each component of this value by the given value. public mutating func scale(by rhs: Double) { } /// The dot-product of this animated pair with itself. public var magnitudeSquared: Double { get } /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (a: AnimatablePair, b: AnimatablePair) -> Bool { } } /// Specifies the timing curve of a changing on-screen value. /// /// ### An `Animation` is just a timing curve /// /// Every animation has 3 parts: /// 1. The numerical value in memory that changes over time --- usually /// a `@State` property /// 2. How the ``View`` depends on this numerical value --- often using /// a view modifier /// 3. The timing curve describing how this change happens --- this is the /// ``Animation`` /// /// For example, say I want the screen to be **green** sometimes, but **red** /// at other times. The current color of the screen would be stored as a /// `@State` property. Then, the screen might use the /// ``View/foregroundColor(_:)`` modifier to actually make the screen this /// color. And finally, when I change the screen color, I can specify a /// *timing curve*, or ``Animation``, to describe how it will happen. /// /// ### Types of timing curves /// /// There are many different types of timing curves, or `Animation`s. /// For example, how long does the animation last (**duration**)? Does it move /// at the same speed the whole time (**linear**), or does it **ease in and out**? /// Or maybe it goes so fast at the beginning that it actually overshoots /// the target and has to go back. This is called a **spring** animation. /// /// #### Main types /// /// There are a few main types of timing curves: /// - ``Animation/linear``: The value changes at the same speed the whole time. /// - ``Animation/easeIn``: The value begins by changing slowly, then speeds /// up towards the end. /// - ``Animation/easeOut``: The value begins quickly, and slows down towards /// the end. /// - ``Animation/easeInOut``: The value begins by changing slowly, goes quickly /// in the middle, and ends slowly. /// - ``Animation/spring(response:dampingFraction:blendDuration:)``: The value begins very quickly, then overshoots /// the target and springs back. /// /// #### Modifiers /// /// There are also a few modifiers that can be applied to timing curves: /// - ``Animation/delay(_:)``: Waits a period of time before doing the /// animation. /// - ``Animation/speed(_:)``: Speeds up or slows down the animation. /// - ``Animation/repeatCount(_:autoreverses:)``: Repeats the animation a number of /// times. /// - ``Animation/repeatForever(autoreverses:)``: Repeats the animation /// forever /// /// ### Using an animation /// /// Once you have an animation, there are 3 main ways to use it: /// /// 1. By applying it to a view using ``View/animation(_:)``, /// so any animatable properties of the view change with that /// timing curve. /// 2. Directly when changing a `@State` property, using the /// ``withAnimation(_:_:)`` global function. /// 3. By attaching the timing curve directly to a `@Binding` property, /// using ``Binding/animation(_:)``, so any changes to the binding happen /// with a certain animation. /// /// See each of those respective pages for specifics of how to use each. /// /// ### Putting it all together /// /// Putting all of the sections above together into one example, here /// is what it looks like: /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.easeInOut) /// /// Button("Animate") { /// self.flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing state variable flag and a VStack with /// a rectangle and a button reading "Animate"; when the button is pressed, flag /// is toggled and the properties of the rectangle change, resulting in it /// changing from yellow to red, growing in size, and rotating 90 degrees, all /// in an easeInOut animation timing curve type.](animation-ex.gif) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct Animation : Equatable { /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (lhs: Animation, rhs: Animation) -> Bool { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animation { /// A persistent spring animation. /// /// This is a timing curve where the animation happens very quickly /// in the beginning, then overshoots the target, and returns back /// with a spring effect. /// /// For example: /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.spring()) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle change /// in a fashion where the animation happens very quickly in the beginning, /// then overshoots the target, and returns back with a spring effect.](animation-spring-noparams-ex.gif) /// /// Here, `spring(response:dampingFraction:blendDuration:)`'s parameters /// have been adjusted to pronounce the spring: /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.spring(response: 0.75, dampingFraction: 0.5, blendDuration: 0)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle change /// in a pronounced spring fashion, as defined by the adjusted response, /// dampingFraction, and blendDuration parameters of spring.](animation-spring-pronounced-ex.gif) /// /// When mixed with other ``Animation/spring(response:dampingFraction:blendDuration:)`` /// or ``Animation/interactiveSpring(response:dampingFraction:blendDuration:)`` /// animations on the same property, each /// animation will be replaced by their successor, preserving /// velocity from one animation to the next. Optionally blends the /// response values between springs over a time period. /// /// - Parameters: /// - response: The stiffness of the spring, defined as an /// approximate duration in seconds. A value of zero requests /// an infinitely-stiff spring, suitable for driving /// interactive animations. /// - dampingFraction: The amount of drag applied to the value /// being animated, as a fraction of an estimate of amount /// needed to produce critical damping. /// - blendDuration: The duration in seconds over which to /// interpolate changes to the response value of the spring. /// - Returns: a spring animation. public static func spring(response: Double = 0.55, dampingFraction: Double = 0.825, blendDuration: Double = 0) -> Animation { } /// A convenience for a `spring()` animation with a lower /// `response` value, intended for driving interactive animations. /// /// This is a timing curve where the animation happens very quickly /// in the beginning, then overshoots the target, and returns back /// with a spring effect. /// /// When passed no parameters, the effect does not show, unlike /// ``Animation/spring(response:dampingFraction:blendDuration:)``. /// /// For example: /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.interactiveSpring()) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle change /// in a fashion without the spring effect showing.](animation-interactive-spring-ex.gif) /// /// When passed the same parameters, `interactiveSpring(response:dampingFraction:blendDuration:)` /// and ``Animation/spring(response:dampingFraction:blendDuration:)`` produce the same result: /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.interactiveSpring(response: 0.75, dampingFraction: 0.5, blendDuration: 0)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle change /// in a pronounced spring fashion, as defined by the adjusted response, /// dampingFraction, and blendDuration parameters of interactive spring.](animation-interactive-spring-pronounced-ex.gif) /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.spring(response: 0.75, dampingFraction: 0.5, blendDuration: 0)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle change /// in a pronounced spring fashion, as defined by the adjusted response, /// dampingFraction, and blendDuration parameters of spring.](animation-spring-pronounced-ex.gif) /// public static func interactiveSpring(response: Double = 0.15, dampingFraction: Double = 0.86, blendDuration: Double = 0.25) -> Animation { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animation { /// An identity animation that happens immediately. /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.default) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle change /// immediately, as defined by the default type property.](animation-default-ex.gif) /// public static let `default`: Animation } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animation { /// An animation where the effect starts out slower and ends slower, while /// moving most quickly in the middle. /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.easeInOut(duration: 3.0)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change over three seconds, as defined by the duration parameter, /// in a fashion where the effect starts out slower and ends slower, while /// moving most quickly in the middle.](animation-easeinout-ex.gif) /// /// - Parameter duration: How long the effect should last. public static func easeInOut(duration: Double) -> Animation { } /// An animation where the effect starts out slower and ends slower, while /// moving most quickly in the middle. /// /// Uses the default timing of 1 second. /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.easeInOut) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change in a fashion where the effect starts out slower and ends slower, /// while moving most quickly in the middle.](animation-ease-in-out-ex.gif) /// public static var easeInOut: Animation { get } /// An animation where the effect starts out slower and then ends more quickly. /// /// For example, /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.easeIn(duration: 3.0)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change over three seconds, as defined by the duration parameter, /// in a fashion where the effect starts out slower and then ends more quickly.](animation-ease-in-duration-ex.gif) /// /// - Parameter duration: How long the effect should last. public static func easeIn(duration: Double) -> Animation { } /// An animation where the effect starts out slower and then ends more quickly. /// /// Uses the default timing of 1 second. /// /// For example, /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.easeIn) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change in a fashion where the effect starts out slower and then ends more /// quickly.](animation-ease-in-ex.gif) /// public static var easeIn: Animation { get } /// An animation where the effect starts out more quickly and then slows down. /// /// For example, /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.easeOut(duration: 3.0)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change over three seconds, as defined by the duration parameter, /// in a fashion where the effect starts out more quickly and then slows down.](animation-ease-out-duration-ex.gif) /// /// - Parameter duration: How long the effect should last. public static func easeOut(duration: Double) -> Animation { } /// An animation where the effect starts out more quickly and then slows down. /// /// Uses the default timing of 1 second. /// /// For example, /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.easeOut) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// !A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change in a fashion where the effect starts out more quickly and then /// slows down.](animation-ease-out-ex.gif) /// public static var easeOut: Animation { get } /// An animation where the effect happens at a constant speed throughout. /// /// For example, /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.linear(duration: 3.0)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change over three seconds, as defined by the duration parameter, /// in a fashion where the effect happens at a constant speed throughout.](animation-linear-duration-ex.gif) /// /// - Parameter duration: How long the effect should last. public static func linear(duration: Double) -> Animation { } /// An animation where the effect happens at a constant speed throughout. /// /// Uses the default timing of 1 second. /// /// For example, /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.linear) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change in a fashion where the effect happens at a constant speed /// throughout.](animation-linear-ex.gif) /// public static var linear: Animation { get } /// An animation with a fully customized timing curve. /// /// Use this animation to fully specify a cubic bezier curve for how /// the animation moves over a specified duration. In the model, /// the x-axis is time, specified as a 0-through-1 fraction. /// of the total duration. The y-axis is the 0-through-1 fraction /// that the animated property has progressed from beginning to end. /// /// See [this website](https://cubic-bezier.com/) /// for an interactive chart of how the two control points influence /// the animation curve. /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.timingCurve(0.42, 0, 0.58, 1, duration: 1.0)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing state variable flag and a VStack with /// a rectangle and a button reading "Animate"; when the button is pressed, flag /// is toggled and the properties of the rectangle change, resulting in it /// changing from yellow to red, growing in size, and rotating 90 degrees, /// in a fashion defined by a fully customized timing curve.](animation-timing-curve-ex.gif) /// /// - Parameters: /// - c0x: The x-coordinate of the first control point. /// - c0y: The y-coordinate of the first control point. /// - c1x: The x-coordinate of the second control point. /// - c1y: The y-coordinate of the second control point. /// - duration: How long the effect should last. public static func timingCurve(_ c0x: Double, _ c0y: Double, _ c1x: Double, _ c1y: Double, duration: Double = 0.35) -> Animation { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animation { /// A persistent spring animation, specified using a physics spring model. /// /// An interpolating spring animation that uses a damped spring /// model to produce values in the range [0, 1] that are then used /// to interpolate within the [from, to] range of the animated /// property. Preserves velocity across overlapping animations by /// adding the effects of each animation. /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(.interpolatingSpring(mass: 1, stiffness: 1, damping: 0.5, initialVelocity: 10)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change repeatedly in a persistent spring animation, as specified using a /// physics spring model.](animation-interpolating-ex.gif) /// /// - Parameters: /// - mass: The mass of the object attached to the spring. /// - stiffness: The stiffness of the spring. /// - damping: The spring damping value. /// - initialVelocity: the initial velocity of the spring, as /// a value in the range [0, 1] representing the magnitude of /// the value being animated. /// - Returns: a spring animation. public static func interpolatingSpring(mass: Double = 1.0, stiffness: Double, damping: Double, initialVelocity: Double = 0.0) -> Animation { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animation { /// Adds delay to your animation that runs before it starts. /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(Animation.easeInOut.delay(1)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, there is a one second delay and /// then the properties of the rectangle change in an easeInOut fashion.](animation-delay-ex.gif) /// /// - Parameter delay: How long the animation will wait before starting, in seconds. public func delay(_ delay: Double) -> Animation { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animation { /// Changes the speed of an animation. /// /// Returns an animation that has its speed multiplied by `speed`. For /// example, if you had `oneSecondAnimation.speed(0.25)`, it would be at 25% /// of its normal speed, so you would have an animation that would last 4 /// seconds. /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(Animation.easeInOut.speed(2)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the properties of the rectangle /// change quickly in an easeInOut fashion, as specified by a higher speed.](animation-speed-ex.gif) /// public func speed(_ speed: Double) -> Animation { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animation { /// Adjusts the number of times the animation should repeat itself. /// /// ``` /// struct AnimateView: View { /// @State private var flag = true /// /// var body: some View { /// VStack { /// Rectangle() /// .foregroundColor(flag ? .yellow : .red) /// .frame(width: flag ? 50 : 100, height: flag ? 50 : 100) /// .rotationEffect(.degrees(flag ? 90 : 0)) /// .animation(Animation.easeInOut.repeatCount(2, autoreverses: false)) /// /// Button("Animate") { /// flag.toggle() /// } /// } /// } /// } /// ``` /// /// ![A gif displaying a view with a yellow rectangle and a button reading /// "Animate"; when the button is pressed, the animation of the rectangles /// spinning and changing color occurs twice, as as defined by the /// repeatCount instance method.](animation-rep-count-ex.gif) /// /// - Parameters: /// - repeatCount: The number of times the animation should repeat. /// - autoreverses: Whether the animation should reverse when repeating. public func repeatCount(_ repeatCount: Int, autoreverses: Bool = true) -> Animation { } /// Adjusts whether the animation repeats forever. /// /// ``` /// struct ExampleView: View { /// @State var progress: CGFloat = 0 /// /// var body: some View { /// VStack { /// Text("Banana🍌🍌") /// .font(.largeTitle) /// .modifier(CircleAnimation(radius: 24, progress: progress)) /// .onAppear { /// withAnimation(Animation.easeInOut(duration: 2.0).repeatForever(autoreverses: false)) { /// progress = 1.0 /// } /// } /// } /// } /// } /// /// struct CircleAnimation: AnimatableModifier { /// let radius: CGFloat /// var progress: CGFloat = 0 /// /// var animatableData: CGFloat { /// get { /// progress /// } set { /// progress = newValue /// } /// } /// /// func body(content: Content) -> some View { /// content.offset( /// x: radius * cos(progress * (2 * CGFloat.pi)), /// y: radius * sin(progress * (2 * CGFloat.pi)) /// ) /// } /// } /// ``` /// /// ![A gif showing the animation of the text "Banana🍌🍌" moving in a small /// clockwise oval around the center of the page repeatedly, forever.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/Animatable-example-2.gif) /// /// - Parameter autoreverses: Whether the animation should reverse when repeating. public func repeatForever(autoreverses: Bool = true) -> Animation { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Animation : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable { /// A textual representation of this instance. /// /// Calling this property directly is discouraged. Instead, convert an /// instance of any type to a string by using the `String(describing:)` /// initializer. This initializer works with any type, and uses the custom /// `description` property for types that conform to /// `CustomStringConvertible`: /// /// struct Point: CustomStringConvertible { /// let x: Int, y: Int /// /// var description: String { /// return "(\(x), \(y))" /// } /// } /// /// let p = Point(x: 21, y: 30) /// let s = String(describing: p) /// print(s) /// // Prints "(21, 30)" /// /// The conversion of `p` to a string in the assignment to `s` uses the /// `Point` type's `description` property. public var description: String { get } /// A textual representation of this instance, suitable for debugging. /// /// Calling this property directly is discouraged. Instead, convert an /// instance of any type to a string by using the `String(reflecting:)` /// initializer. This initializer works with any type, and uses the custom /// `debugDescription` property for types that conform to /// `CustomDebugStringConvertible`: /// /// struct Point: CustomDebugStringConvertible { /// let x: Int, y: Int /// /// var debugDescription: String { /// return "(\(x), \(y))" /// } /// } /// /// let p = Point(x: 21, y: 30) /// let s = String(reflecting: p) /// print(s) /// // Prints "(21, 30)" /// /// The conversion of `p` to a string in the assignment to `s` uses the /// `Point` type's `debugDescription` property. public var debugDescription: String { get } /// The custom mirror for this instance. /// /// If this type has value semantics, the mirror should be unaffected by /// subsequent mutations of the instance. public var customMirror: Mirror { get } } /// A type-erased gesture. /// /// See ``Gesture`` for information on the gesture protocol. @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct AnyGesture : Gesture { /// Creates an instance from another gesture. /// /// - Parameter gesture: A gesture that you use to create a new gesture. public init(_ gesture: T) where Value == T.Value, T : Gesture { } /// The type of gesture representing the body of `Self`. public typealias Body = Never } /// A transition to use for animating a view on and off the screen. /// /// Use this structure along with the ``View/transition(_:)`` /// view modifier to animate the way a ``View`` comes onto and leaves the /// screen. /// /// Examples of transitions include: /// - ``AnyTransition/scale`` /// - ``AnyTransition/opacity`` (default) /// - ``AnyTransition/slide`` /// - etc. /// /// A transition is only one half of animating a view. You also must specify /// a timing curve, (somewhat confusingly) called an "animation." /// See ``Animation`` for more info on creating one of these timing curves. /// /// ### Creating a transition /// /// The easiest way to creat a transition is using one of /// the many pre-made static members available in `AnyTransition`. /// See the sliding banana example at the bottom of this page. /// /// You can also create your own static members by extending this /// struct. /// /// ``` /// extension AnyTransition { /// static var slideAndFade: AnyTransition { /// return AnyTransition.slide.combined(with: .opacity) /// } /// } /// ``` /// /// ### Using a transition /// /// Transitions are most often used by attaching them to views that have /// "if" statements on them. /// /// As long as a timing curve (``Animation``) is specified, whenever the /// view is added to or removed from the screen, it will do so with /// the specified transition. /// /// There are many ways to add an animation to the transition: /// - Using ``withAnimation(_:_:)`` /// - Using `AnyTransition`'s own ``AnyTransition/animation(_:)`` modifier. /// - Using ``View``'s ``View/animation(_:)`` modifier. /// /// The following example applies the ``AnyTransition/slide`` transition: /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Slide the banana ➡️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.slide) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Slide the banana /// ➡️" that triggers the slide transition of the text view "🍌" when pressed; /// the "🍌" slides down from beneath the button, displacing it until it slides /// up again on the other side.](any-transition-using-ex.gif) /// /// - Note: By default, views transition using ``AnyTransition/opacity``. @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct AnyTransition { } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// A transition that moves a view from its current place on screen to another place using a CGSize. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Offset the banana ↘️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.offset(CGSize(width: 100, height: 100))) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Offset the banana ↘️" /// that triggers the offset transition of the text view "🍌" when pressed; /// the "🍌" moves from its current place under the banana to the outside of the /// frame down and to the right, as defined by a CGSize.](any-transition-offset-ex.gif) /// /// - Parameter offset: The amount you want to move the view during the transition. public static func offset(_ offset: CGSize) -> AnyTransition { } /// A transition that moves a view from its current place on screen to another place using x and y offsets. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Offset the banana ↘️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.offset(x: 100, y: 100)) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Offset the banana ↘️" /// that triggers the offset transition of the text view "🍌" when pressed; /// the "🍌" moves from its current place under the banana to the outside of the /// frame down and to the right, as defined by the x and y offsets.](any-transition-offset-xy-ex.gif) /// /// - Parameters: /// - x: The number of points you want to move the view to the right. Negative means move left. Defaults to 0. /// - y: The number of points you want to move the view down. Negative means move up. Defaults to 0. public static func offset(x: CGFloat = 0, y: CGFloat = 0) -> AnyTransition { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// A transition that scales a view from its current size down to zero size. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Scale the banana ⤵️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.scale) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Scale the banana ⤵️" /// that triggers the scale down of the text view "🍌" when pressed; /// the "🍌" shrinks to nothing, disappearing under the button.](any-transition-scale-ex.gif) /// public static var scale: AnyTransition { get } /// A transition that scales a view from its current size to a new size. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("SCALE THE BANANA ⤴️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.scale(scale: 100, anchor: .center)) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "SCALE THE BANANA ⤴️" /// that triggers the scale up of the text view "🍌" when pressed; the "🍌", /// anchored at the center, becomes so big that it can't fit in the frame.](any-transition-scale-anchor-ex.gif) /// /// - Parameters: /// - scale: The amount you want to scale the view. /// - anchor: The unit point to have the view scale from. public static func scale(scale: CGFloat, anchor: UnitPoint = .center) -> AnyTransition { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// A transition from transparent to opaque on insertion, and from opaque to /// transparent on removal. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// - Note: This is the default transition when a view's transition isn't /// specified. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Fade the banana 🎚") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.opacity) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Fade the banana 🎚" /// that triggers a transition of the text view "🍌" from transparent to /// opaque on first click, and from opaque to transparent on second click; the "🍌", /// appears from under the button and then fades back into oblivion.](any-transition-opacity-ex.gif) /// public static let opacity: AnyTransition } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// A transition that inserts by moving in from the leading edge, and /// removes by moving out towards the trailing edge. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Slide the banana ➡️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.slide) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Slide the banana /// ➡️" that triggers the slide transition of the text view "🍌" when pressed; /// the "🍌" slides down from beneath the button, displacing it until it slides /// up again on the other side.](any-transition-slide-ex.gif) /// /// - SeeAlso: ``AnyTransition/move(edge:)`` public static var slide: AnyTransition { get } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// Combines this transition with another, returning a new transition that /// is the result of both transitions being applied. /// /// Use this transition to combine multiple transitions at once. /// /// For example, below we combine ``AnyTransition/opacity`` with /// ``AnyTransition/slide`` for a new transition that both /// slides and fades. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Slide AND fade the banana ➡️🎚") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(AnyTransition.opacity.combined(with: .slide)) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Slide AND fade /// the banana ➡️🎚" that triggers both the slide and fade transitions of /// the text view "🍌" when pressed; the "🍌" appears and slides down from /// beneath the button, displacing it until it slides up again on the other /// side while fading into oblivion.](any-transition-combined-ex.gif) /// public func combined(with other: AnyTransition) -> AnyTransition { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// Returns a transition defined between an active modifier and an identity /// modifier. /// /// Use this transition for maximum customization. It allows you to /// pass in any two ``ViewModifier``s and create your own custom /// transition from them. /// /// The first view modifier, `active`, is what you want to apply to the /// view at the very moment it is removed from the screne. The second /// view modifier, `identity`, is what you want to apply right as the /// transition has finished. /// /// See ``ViewModifier`` for more on how to create your own modifiers. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// The following simple example just recreates the /// ``AnyTransition/opacity`` transition. /// /// ``` /// struct OpacityModifier: ViewModifier { /// let opacity: Double /// /// func body(content: Content) -> some View { /// content.opacity(opacity) /// } /// } /// /// extension AnyTransition { /// static var opOpacity: AnyTransition { /// .modifier(active: OpacityModifier(opacity: 0), /// identity: OpacityModifier(opacity: 1)) /// } /// } /// /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("OP fade the banana 🎚❗️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.opOpacity) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "OP fade the /// banana 🎚❗️" that triggers the transition of the text view "🍌" when /// pressed; the custom transition acts the same as the opacity transition, /// as defined by and an active OpacityModifier of value 0 and identity /// OpacityModifier of value 1.](any-transition-modifier-ex.gif) /// public static func modifier(active: E, identity: E) -> AnyTransition where E : ViewModifier { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// Attaches an animation to this transition. /// /// Use this modifier to control the timing curve /// directly on the transition itself. /// /// For some reason, this method only works on some of the transitions. /// /// Transitions where this works: /// - ``AnyTransition/scale`` /// - ``AnyTransition/opacity`` /// /// Transition where this doesn't work: /// - ``AnyTransition/offset(x:y:)`` /// - ``AnyTransition/slide`` /// - ``AnyTransition/move(edge:)`` /// /// Compare the following two examples that do the same thing. /// The second one uses this modifier; the first one does not. /// /// ``` /// struct FirstBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Scale the banana ⤴️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(AnyTransition.scale) /// } /// } /// } /// ``` /// /// ``` /// struct SecondBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Scale the banana ⤴️") { /// showBanana.toggle() /// } /// if showBanana { /// Text("🍌") /// .transition(AnyTransition.scale.animation(.easeInOut)) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Scale the banana ⤴️" /// that triggers the scale up of the text view "🍌" when pressed; the examples /// show that the same result occurs using the animation modifier or not.](any-transition-anim-ex.gif) /// public func animation(_ animation: Animation?) -> AnyTransition { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// A transition that does nothing. /// /// Since the default transition is ``AnyTransition/opacity``, /// use this modifier to specify a transition that does nothing. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// ``` /// struct IdentityBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Apparate the banana.") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.identity) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Apparate the banana." /// that triggers the transitioning of the text view "🍌" with no effects when pressed; /// the view simply disappears behind the button.](any-transition-identity-ex.gif) /// public static let identity: AnyTransition } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// Returns a transition that moves the view away, towards the specified /// edge of the view. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Move the banana ➡️") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.move(edge: .trailing)) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Move the banana ➡️" /// that triggers the moving transition of the text view "🍌" when pressed; /// the view slides up the the trailing edge of the button and disappears, as /// defined by the edge parameter.](any-transition-move-edge-ex.gif) /// /// See ``AnyTransition`` for more on how to use this transition. public static func move(edge: Edge) -> AnyTransition { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension AnyTransition { /// Provides a composite transition that uses a different transition for /// insertion versus removal. /// /// See ``AnyTransition`` for more on how to use this transition. /// /// ``` /// struct TransitioningBananaView: View { /// @State var showBanana = true /// /// var body: some View { /// Button("Slide the banana in ➡️, fade banana out 🎚") { /// withAnimation { showBanana.toggle() } /// } /// if showBanana { /// Text("🍌") /// .transition(.asymmetric(insertion: .slide, removal: .opacity)) /// } /// } /// } /// ``` /// /// ![A gif displaying a view containing a button that reads "Slide the banana in ➡️, /// fade banana out 🎚" that triggers composite transition of the text view "🍌" /// when pressed; the "🍌" slides into view from the left and then fades out /// of view in the center, as defined by the insertion anf removal parameters /// of the asymmetrical transition.](any-transition-asymmetric-ex.gif) /// /// See ``AnyTransition`` for more on how to use this transition. public static func asymmetric(insertion: AnyTransition, removal: AnyTransition) -> AnyTransition { } } /// A view that provides type-erasure for views of other types. /// /// An `AnyView` hides the type of the ``View`` value passed to it (similar /// to how `AnyHashable` hides the type of `Hashable` value passed to it). /// /// To type-erase your view, pass it to ``AnyView/init(_:)`` like this: /// /// ``` /// struct ExampleView: View { /// var body: some View { /// AnyView(Text("Hello, world!")) /// } /// } /// ``` /// /// ![A white AnyView displaying the text "Hello,world!"](17C757BC-E76E-4E17-9513-6C5AB3A80796.png) /// /// Changing the type of view using with `AnyView` destroys the view hierarchy /// for the old type and creates a new hierarchy for the new type. In the /// following example, ``Text`` is destroyed and ``Color`` is created when /// `foo` is set to `false`: /// /// ``` /// struct ExampleView: View { /// let foo: Bool = false /// /// var body: some View { /// if foo { /// AnyView(Text("Hello, world!")) /// } else { /// AnyView(Color.red) /// } /// } /// } /// ``` /// /// ![A blank red AnyView.](5AFA4383-AD4C-4AC6-9C25-5E3F154E395D.png) /// /// Avoid frequently changing the underlying type of view being erased, /// especially for complex views, as poor performance may result. /// `AnyView` is best suited for use in the deepest part of your view /// hierarchy, such as a list's row content in /// ``List/init(_:id:selection:rowContent:)``. It is also suited for use in /// different layers of your view hierarchy, via either /// ``View/overlay(_:alignment:)`` or ``View/background(_:alignment:)``. /// /// Consider whether the usage of `AnyView` is appropriate, or even necessary. /// A common mistake is to use `AnyView` like this: /// /// ``` /// func makeHelperView() -> some View { /// if foo { /// return AnyView(Text("Hello, world!")) /// } else { /// return AnyView(Color.red) /// } /// } /// ``` /// /// Wherein adding a ``ViewBuilder`` would be more appropriate: /// /// ``` /// @ViewBuilder /// func makeHelperView() -> some View { /// if foo { /// Text("Hello, world!") /// } else { /// Color.red /// } /// } /// ``` /// /// ![A blank red AnyView.](5AFA4383-AD4C-4AC6-9C25-5E3F154E395D.png) /// /// The latter example performs better as the SwiftUI runtime is given a /// more explicit type hierarchy, where the switch between `foo` being `true` /// or `false` can only result in a ``Text`` or a ``Color``. The former /// example erases that information, forcing the SwiftUI runtime to evaluate /// the actual view type lazily, and thus requires more work to compute and /// render. /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct AnyView : View { /// Create an instance that type-erases ``View``. /// /// See ``AnyView`` for the uses and dangers of using this structure. /// /// ``` /// struct ExampleView: View { /// var body: some View { /// AnyView(Text("Hello, world!")) /// } /// } /// ``` /// /// ![An AnyView containing the text view "Hello, world!", resulting in the /// type erasure of the view.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/anyview-example-1.png) /// public init(_ view: V) where V : View { } /// Creates an instance that type-erases the parameter. /// /// See ``AnyView`` for the uses and dangers of using this structure. /// /// ``` /// struct ExampleView: View { /// var body: some View { /// AnyView(erasing: Text("Hello, world!")) /// } /// } /// ``` /// /// ![An AnyView containing the text view "Hello, world!" in an erasing instance, /// resulting in type erasure of the parameter.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/anyview-example-1.png) /// public init(erasing view: V) where V : View { } /// The type of view representing the body of this view. /// /// When you create a custom view, Swift infers this type from your /// implementation of the required `body` property. public typealias Body = Never } /// A type that represents the structure and behavior of an app. /// /// Create an app by declaring a structure that conforms to the ``App`` protocol. /// Implement the required ``App/body-swift.variable`` computed property /// to define the app's content: /// /// @main /// struct MyApp: App { /// var body: some Scene { /// WindowGroup { /// Text("Hello, world! 🌍🙋") /// .font(.title) /// } /// } /// } /// /// ![An app containing a window group with a title font text view reading /// "Hello, world! 🌍🙋".](app.png) /// /// Precede the structure's declaration with the /// [`@main`](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#ID626) /// attribute to indicate that your custom ``App`` protocol conformer provides the /// entry point into your app. The protocol provides a default implementation of /// the ``App/main()`` method that the system calls to launch your app. /// You can have exactly one entry point among all of your app's files. /// /// Compose the app's ``App/body-swift.variable`` from instances that conform to the ``Scene`` /// protocol. Each scene contains the root view of a view hierarchy and has a /// life cycle managed by the system. SwiftUI provides some concrete scene types /// to handle common scenarios, like for displaying documents or settings. You /// can also create custom scenes. /// /// @main /// struct Mail: App { /// var body: some Scene { /// WindowGroup { /// MailViewer() /// } /// } /// } /// /// Then `MailViewer` would be the root view of the app: /// /// struct MailViewer: View { /// var body: some View { /// // Implement here /// Text("Turn me into a mail app! 📨") /// } /// } /// /// You can declare state in your app to share across all of its scenes. For /// example, you can use the ``StateObject`` attribute to initialize a /// data model, and then provide that model on a view input as an /// ``ObservedObject`` or through the environment as an /// ``EnvironmentObject`` to scenes in the app: /// /// @main /// struct Mail: App { /// @StateObject private var model = MailModel() /// /// var body: some Scene { /// WindowGroup { /// MailViewer() /// .environmentObject(model) //Passed through the environment. /// } /// #if os(iOS) /// Settings { /// SettingsView(model: model) //Passed as an observed object. /// } /// #endif /// } /// } /// /// struct MailViewer: View { /// @EnvironmentObject var model: MailModel /// var body: some View { Text("Implement me! 📬") } /// } /// /// struct SettingsView: View { /// @ObservedObject var mdoel: MailModel /// var body: some View { Text("Implement me! ⚙️") } /// } /// /// class MailModel: ObservableObject { /* implement here */ } /// @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) public protocol App { } extension App { /// The type of scene representing the content of the app. /// /// When you create a custom app, Swift infers this type from your /// implementation of the required `App/body-swift.property` /// property. associatedtype Body : Scene /// The content and behavior of the app. /// /// For any app that you create, provide a computed `body` property that /// defines your app's scenes, which are instances that conform to the /// ``Scene`` protocol. For example, you can create a simple app /// with a single scene containing a single view: /// /// @main /// struct MyApp: App { /// var body: some Scene { /// WindowGroup { /// Text("Hello, world!") /// } /// } /// } /// /// Swift infers the app's `App/Body-swift.associatedtype` /// associated type based on the scene provided by the `body` property. @SceneBuilder var body: Self.Body { get } /// Creates an instance of the app using the body that you define for its /// content. /// /// **Don't use this function directly**. /// Swift synthesizes a default initializer for structures that don't /// provide one. You typically rely on the default initializer for /// your app. /// /// See ``App`` for details /// and examples of how to use this protocol. init() { } } @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) extension App { /// Initializes and runs the app. /// /// **Don't use this function directly.** See ``App`` for details /// and examples of how to use this protocol. /// /// If you precede your ``App`` conformer's declaration with the /// [`@main`](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#ID626) /// attribute, the system calls the conformer's `main()` method to launch /// the app. SwiftUI provides a /// default implementation of the method that manages the launch process in /// a platform-appropriate way. public static func main() { } } /// A property wrapper type that reads from and writes to the device's storage. /// /// Use this property wrapper to read to and write from permanent storage /// on the user's device, also known as "UserDefaults". /// /// Check out ``Scene/defaultAppStorage(_:)`` for ``Scene``s and /// ``View/defaultAppStorage(_:)`` for ``View``s to learn more about /// setting the default app storage location for a view. /// /// /// Below shows a simple example using a [`String`](https://developer.apple.com/documentation/swift/string). /// /// struct ContentView: View { /// @AppStorage("name") var name: String = "Kanye" /// /// var body: some View { /// Text("Stored string: \(name)") /// TextField(name, text: $name) /// } /// } /// /// ![A gif displaying a view containing a textview reading "Stored string: \(name)" /// and a textfield with default text "Kanye" and an input bound to the appstorage /// string variable "name."; when the textfield input is changed to "John", so is /// the stored string variable, as shown in the textview.](app-storage-ex.gif) /// @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) @frozen @propertyWrapper public struct AppStorage : DynamicProperty { /// The user default value for the given key. /// /// This is rarely used directly. Instead, you normally use the property wrapper syntax: /// /// struct ContentView: View { /// @AppStorage("name") var name: String = "Kanye" /// /// var body: some View { /// TextField(name, text: $name) /// } /// } public var wrappedValue: Value { get /*nonmutating set*/ } /// Provides a binding for the wrapped value. /// /// You can access this using the `$` prefix: /// /// struct ContentView: View { /// @AppStorage("name") var name: String = "Kanye" /// /// var body: some View { /// TextField(name, text: $name) /// } /// } /// /// ![A gif displaying a textfield with default contents and text input /// bound to an AppStorage variable assigned the string "Kanye"; the text is /// deleted and "JOhn" is typed, which will now be stored even when the app /// is reloaded.](appstorage-projected-val-ex.gif) /// public var projectedValue: Binding { get } } @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) extension AppStorage { /// Creates a property that can read and write to a boolean user default. /// /// struct ContentView: View { /// @AppStorage("airplane-mode") var on: Bool = false /// /// var body: some View { /// Toggle("Airplane Mode", isOn: $on) /// } /// } /// /// ![A view containing a toggle named "Airplane mode" where the isOn /// input is bound to the appstorage boolean variable "airplane-mode."](16.40.39.png) /// /// - Parameters: /// - wrappedValue: The default value if a boolean value is not specified /// for the given key. /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) where Value == Bool { } /// Creates a property that can read and write to an integer user default. /// /// struct ContentView: View { /// @AppStorage("donuts") var count: Int = 0 /// /// var body: some View { /// Stepper("🍩 count: \(count)", value: $count) /// } /// } /// /// ![A view containing a stepper called "🍩 count: \(count)" where the value /// input is bound to the appstorage Int variable "count".]16.42.01.png) /// /// - Parameters: /// - wrappedValue: The default value if an integer value is not specified /// for the given key. /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) where Value == Int { } /// Creates a property that can read and write to a double user default. /// /// struct ContentView: View { /// @AppStorage("brightness") var level: Double = 0 /// /// var body: some View { /// Text("🔆 \(level)") /// Slider(value: $level) /// } /// } /// /// ![A view containing a text view reading "🔆 \(level)" and a slider where the value /// input is bound to the appstorage Double variable "level".](16.42.46.png) /// /// - Parameters: /// - wrappedValue: The default value if a double value is not specified /// for the given key. /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) where Value == Double { } /// Creates a property that can read and write to a string user default. /// /// struct ContentView: View { /// @AppStorage("name") var name: String = "Kanye" /// /// var body: some View { /// TextField(name, text: $name) /// } /// } /// /// ![A view containing a textfield where the text input is bound to /// the appstorage Double variable "name".](16.34.17.png) /// /// - Parameters: /// - wrappedValue: The default value if a string value is not specified /// for the given key. /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) where Value == String { } /// Creates a property that can read and write to a url user default. /// /// struct ContentView: View { /// @AppStorage("site") var url = URL(string: "https://swiftontap.com")! /// /// var body: some View { /// Text("Check out \(url)") /// } /// } /// /// ![A view containing a textview "Check out \(url)" where the text url is /// bound to the appstorage url variable "url".](16.44.14.png) /// /// - Parameters: /// - wrappedValue: The default value if a url value is not specified for /// the given key. /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) where Value == URL { } /// Creates a property that can read and write to a user default as data. /// /// Avoid storing large data blobs in user defaults, such as image data, /// as it can negatively affect performance of your app. On tvOS, a /// `NSUserDefaultsSizeLimitExceededNotification` notification is posted /// if the total user default size reaches 512kB. /// /// struct Human: Codable { /// var name: String /// var age: Int /// } /// /// struct ContentView: View { /// @AppStorage("goat") var person = Data() /// /// var body: some View { /// Button("Make Aaron the 🐐") { /// let aaron = Human(name: "Aaron", age: 21) /// let aaronData = try! JSONEncoder().encode(aaron) /// /// person = aaronData /// print("success.") /// } /// } /// } /// /// ![A view containing a button "Make Aaron the 🐐" where the name and age /// inputs are bound to the appstorage variables "name" and "age".](16.47.01.png) /// /// - Parameters: /// - wrappedValue: The default value if a data value is not specified for /// the given key. /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) where Value == Data { } /// Creates a property that can read and write to an integer user default, /// transforming that to `RawRepresentable` data type. /// /// A common usage is with enumerations: /// /// enum MyEnum: Int { /// case a /// case b /// case c /// } /// struct MyView: View { /// @AppStorage("MyEnumValue") private var value = MyEnum.a /// /// var body: some View { /// Picker("Choose!", selection: $value) { /// Text("a").tag(MyEnum.a) /// Text("b").tag(MyEnum.b) /// Text("c").tag(MyEnum.c) /// } /// } /// } /// /// ![A view containing a picker titled whose text options "a", "b", and /// "c", are tagged to an enum bound to the appstorage variable "value", /// which is in turn used to populate the selection input of the picker.](16.58.02.png) /// /// - Parameters: /// - wrappedValue: The default value if an integer value /// is not specified for the given key. /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) where Value : RawRepresentable, Value.RawValue == Int { } /// Creates a property that can read and write to a string user default, /// transforming that to `RawRepresentable` data type. /// /// A common usage is with enumerations: /// /// enum MyEnum: String { /// case a /// case b /// case c /// } /// struct MyView: View { /// @AppStorage("MyEnumValue") private var value = MyEnum.a /// var body: some View { /// Picker("Choose!", selection: $value) { /// Text("a").tag(MyEnum.a) /// Text("b").tag(MyEnum.b) /// Text("c").tag(MyEnum.c) /// } /// } /// } /// /// ![A view containing a picker titled whose text options "a", "b", and /// "c", are tagged to an enum which is referenced by the appstorage variable "value", /// which is in turn used to populate the selection input of the picker.](16.58.02.png) /// /// - Parameters: /// - wrappedValue: The default value if a string value /// is not specified for the given key. /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) where Value : RawRepresentable, Value.RawValue == String { } } @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) extension AppStorage where Value : ExpressibleByNilLiteral { /// Creates a property that can read and write an Optional boolean user /// default. /// /// Defaults to `nil` if there is no restored value. /// /// struct ContentView: View { /// @AppStorage("airplane-mode") var on: Bool? /// /// var body: some View { /// Button("on") { on = true } /// Button("off") { on = false } /// } /// } /// /// ![A view containing two buttons, "on" and "off"; the appstorage boolean /// variable "airplane-mode" defaults to nil as there is no restored value.](17.15.34.png) /// /// - Parameters: /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(_ key: String, store: UserDefaults? = nil) where Value == Bool? { } /// Creates a property that can read and write an Optional integer user /// default. /// /// Defaults to nil if there is no restored value. /// /// struct ContentView: View { /// @AppStorage("donuts") var count: Int? /// /// var body: some View { /// Button("none ☹️") { count = 0 } /// Button("LOTS 🍩") { count = 100 } /// } /// } /// /// ![A view containing two buttons, "none ☹️" and "LOTS 🍩"; the appstorage /// Int optional variable "count" defaults to nil as there is no restored value.](17.16.17.png) /// /// - Parameters: /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(_ key: String, store: UserDefaults? = nil) where Value == Int? { } /// Creates a property that can read and write an Optional double user /// default. /// /// Defaults to nil if there is no restored value. /// /// struct ContentView: View { /// @AppStorage("brightness") var level: Double? /// /// var body: some View { /// Button("MAX 🔆") { level = 1.0 } /// Button("min 🔅") { level = 0.0 } /// } /// } /// /// ![A view containing two buttons, "MAX 🔆" and "min 🔅"; the appstorage /// Double optional variable "count" defaults to nil as there is no restored value.](17.18.26.png) /// /// - Parameters: /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(_ key: String, store: UserDefaults? = nil) where Value == Double? { } /// Creates a property that can read and write an Optional string user /// default. /// /// struct ContentView: View { /// @AppStorage("name") var name: String? /// /// var body: some View { /// Button("Save 🐐") { name = "Kanye" } /// } /// } /// /// Defaults to nil if there is no restored value. /// /// ![A view containing a button "Save 🐐" with name = "Kanye"; the appstorage /// String optional variable "name" defaults to nil as there is no restored value.](17.19.59.png) /// /// - Parameters: /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(_ key: String, store: UserDefaults? = nil) where Value == String? { } /// Creates a property that can read and write an Optional URL user /// default. /// /// Defaults to nil if there is no restored value. /// /// struct ContentView: View { /// @AppStorage("site") var url: URL? /// /// var body: some View { /// Button("Save the 🍌") { url = URL(string: "https://swiftontap.com") } /// } /// } /// /// ![A view containing a button "Save the 🍌" with the SwiftOnTap website url; the appstorage /// url optional variable "url" defaults to nil as there is no restored value.](17.31.44.png) /// /// - Parameters: /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(_ key: String, store: UserDefaults? = nil) where Value == URL? { } /// Creates a property that can read and write an Optional data user /// default. /// /// Defaults to nil if there is no restored value. /// /// struct Human: Codable { /// var name: String /// var age: Int /// } /// /// struct ContentView: View { /// @AppStorage("goat") var person: Data? /// /// var body: some View { /// Button("Make Aaron the 🐐") { /// let aaron = Human(name: "Aaron", age: 21) /// let aaronData = try! JSONEncoder().encode(aaron) /// /// person = aaronData /// print("success.") /// } /// } /// } /// /// ![A view containing a button "Make Aaron the 🐐" with two static variables /// and a print statement; the appstorage Data optional variable "person" /// defaults to nil as there is no restored value.](17.33.08.png) /// /// - Parameters: /// - key: The key to read and write the value to in the user defaults /// store. /// - store: The user defaults store to read and write to. A value /// of `nil` will use the user default store from the environment. public init(_ key: String, store: UserDefaults? = nil) where Value == Data? { } } /// The horizontal or vertical dimension in a 2D coordinate system. /// /// Use this enumeration with ``ScrollView`` to specify whether the /// view can be scrolled vertically, horizontally, or both. /// /// There are two possible axes: /// 1. ``Axis/horizontal`` /// 2. ``Axis/vertical`` /// /// See ``ScrollView/init(_:showsIndicators:content:)`` for more details /// on using this enumeration in the initializer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ScrollView(Axis.Set.horizontal, showsIndicators: false) { /// VStack { /// Text("Bananas 🍌🍌") /// Text("Apples 🍏🍏") /// Text("Peaches 🍑🍑") /// } /// } /// } /// } /// ``` /// /// ![A gif of a text view displaying three strings stacked on top of each other on the left side of the screen, scrolling side to side.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/ScrollView-example-2.gif) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public enum Axis : Int8, CaseIterable { /// The horizontal dimension. /// /// Use this enumeration case with ``ScrollView`` to specify a /// scrollable view in the horizontal direction. /// /// See ``ScrollView/init(_:showsIndicators:content:)`` for more details /// on using this enumeration in the initializer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ScrollView(.horizontal, showsIndicators: false) { /// VStack { /// Text("Bananas 🍌🍌") /// Text("Apples 🍏🍏") /// Text("Peaches 🍑🍑") /// } /// } /// } /// } /// ``` /// /// ![A gif of a text view displaying three strings stacked on top of each other on the left side of the screen, scrolling side to side.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/ScrollView-example-2.gif) /// case horizontal /// The vertical dimension. /// /// Use this enumeration case with ``ScrollView`` to specify a /// scrollable view in the horizontal direction. /// /// See ``ScrollView/init(_:showsIndicators:content:)`` for more details /// on using this enumeration in the initializer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ScrollView(.vertical, showsIndicators: false) { /// VStack { /// Text("Bananas 🍌🍌") /// Text("Apples 🍏🍏") /// Text("Peaches 🍑🍑") /// } /// } /// } /// } /// ``` /// /// ![A gif of a text view displaying three strings stacked on top of each other at the top of the screen, scrolling up and down.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/ScrollView-example-1.gif) case vertical /// An efficient set of axes. /// /// Use this option set with ``ScrollView`` to specify whether the /// view can be scrolled vertically, horizontally, or both. /// /// This `OptionSet` allows you to easily just pass one option - `.horizontal` - /// or an array of options - `[.horizontal, .vertical]` - into the /// same parameter without worrying about the type. See /// the Apple docs on [OptionSet](https://developer.apple.com/documentation/swift/optionset) /// for more on the protocol. /// /// See ``ScrollView/init(_:showsIndicators:content:)`` for more details /// on using this option set in the initializer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ScrollView([.horizontal, .vertical]) { /// VStack { /// Text("Bananas 🍌🍌") /// Text("Apples 🍏🍏") /// Text("Peaches 🍑🍑") /// } /// } /// } /// } /// ``` /// /// ![A gif of a text view displaying three strings stacked on top of each other in the center of the screen, scrolling both up and down and side to side.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/ScrollView-example-3.gif) /// @frozen public struct Set : OptionSet { /// The element type of the option set. /// /// To inherit all the default implementations from the `OptionSet` protocol, /// the `Element` type must be `Self`, the default. public typealias Element = Axis.Set /// The corresponding value of the raw type. /// /// A new instance initialized with `rawValue` will be equivalent to this /// instance. For example: /// /// enum PaperSize: String { /// case A4, A5, Letter, Legal /// } /// /// let selectedSize = PaperSize.Letter /// print(selectedSize.rawValue) /// // Prints "Letter" /// /// print(selectedSize == PaperSize(rawValue: selectedSize.rawValue)!) /// // Prints "true" public let rawValue: Int8 /// Creates a new option set from the given raw value. /// /// This initializer always succeeds, even if the value passed as `rawValue` /// exceeds the static properties declared as part of the option set. This /// example creates an instance of `ShippingOptions` with a raw value beyond /// the highest element, with a bit mask that effectively contains all the /// declared static members. /// /// let extraOptions = ShippingOptions(rawValue: 255) /// print(extraOptions.isStrictSuperset(of: .all)) /// // Prints "true" /// /// - Parameter rawValue: The raw value of the option set to create. Each bit /// of `rawValue` potentially represents an element of the option set, /// though raw values may include bits that are not defined as distinct /// values of the `OptionSet` type. public init(rawValue: Int8) { } /// The option set corresponding to the horizontal axis. /// /// Use this property with ``ScrollView`` to specify a /// scrollable view in the horizontal direction. /// /// See ``ScrollView/init(_:showsIndicators:content:)`` for more details /// on using this in the initializer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ScrollView(.horizontal, showsIndicators: false) { /// VStack { /// Text("Bananas 🍌🍌") /// Text("Apples 🍏🍏") /// Text("Peaches 🍑🍑") /// } /// } /// } /// } /// ``` /// /// ![A gif of a text view displaying three strings stacked on top of each other on the left side of the screen, scrolling side to side.](horizontal-axis.gif) /// public static let horizontal: Axis.Set /// The option set corresponding to the vertical axis. /// /// Use this property with ``ScrollView`` to specify a /// scrollable view in the horizontal direction. /// /// See ``ScrollView/init(_:showsIndicators:content:)`` for more details /// on using this in the initializer. /// /// ``` /// struct ExampleView: View { /// var body: some View { /// ScrollView(.vertical, showsIndicators: false) { /// VStack { /// Text("Bananas 🍌🍌") /// Text("Apples 🍏🍏") /// Text("Peaches 🍑🍑") /// } /// } /// } /// } /// ``` /// /// ![A gif of a text view displaying three strings stacked on top of each other at the top of the screen, scrolling up and down.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/ScrollView-example-1.gif) /// public static let vertical: Axis.Set /// The type of the elements of an array literal. public typealias ArrayLiteralElement = Axis.Set.Element /// The raw type that can be used to represent all values of the conforming /// type. /// /// Every distinct value of the conforming type has a corresponding unique /// value of the `RawValue` type, but there may be values of the `RawValue` /// type that don't have a corresponding value of the conforming type. public typealias RawValue = Int8 } /// The raw type that can be used to represent all values of the conforming /// type. /// /// Every distinct value of the conforming type has a corresponding unique /// value of the `RawValue` type, but there may be values of the `RawValue` /// type that don't have a corresponding value of the conforming type. public typealias RawValue = Int8 /// The corresponding value of the raw type. /// /// A new instance initialized with `rawValue` will be equivalent to this /// instance. For example: /// /// enum PaperSize: String { /// case A4, A5, Letter, Legal /// } /// /// let selectedSize = PaperSize.Letter /// print(selectedSize.rawValue) /// // Prints "Letter" /// /// print(selectedSize == PaperSize(rawValue: selectedSize.rawValue)!) /// // Prints "true" public var rawValue: Int8 { get } /// Creates a new instance with the specified raw value. /// /// If there is no value of the type that corresponds with the specified raw /// value, this initializer returns `nil`. For example: /// /// enum PaperSize: String { /// case A4, A5, Letter, Legal /// } /// /// print(PaperSize(rawValue: "Legal")) /// // Prints "Optional("PaperSize.Legal")" /// /// print(PaperSize(rawValue: "Tabloid")) /// // Prints "nil" /// /// - Parameter rawValue: The raw value to use for the new instance. public init?(rawValue: Int8) { } /// A type that can represent a collection of all values of this type. public typealias AllCases = [Axis] /// A collection of all values of this type. public static var allCases: [Axis] { get } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Axis : CustomStringConvertible { /// A textual representation of this instance. /// /// Calling this property directly is discouraged. Instead, convert an /// instance of any type to a string by using the `String(describing:)` /// initializer. This initializer works with any type, and uses the custom /// `description` property for types that conform to /// `CustomStringConvertible`: /// /// struct Point: CustomStringConvertible { /// let x: Int, y: Int /// /// var description: String { /// return "(\(x), \(y))" /// } /// } /// /// let p = Point(x: 21, y: 30) /// let s = String(describing: p) /// print(s) /// // Prints "(21, 30)" /// /// The conversion of `p` to a string in the assignment to `s` uses the /// `Point` type's `description` property. public var description: String { get } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Axis : Equatable { } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Axis : Hashable { } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Axis : RawRepresentable { } /// A style that looks solid white in light mode and solid black in dark mode. /// /// Use this ``ShapeStyle`` to intelligently stroke and fill shapes based /// on what color will look good against the current background. /// /// In light mode, this will fill as solid white. In dark mode, it will fill /// as solid black. /// /// In the following example, the top circle is always invisible, since /// it is filled the same color as the background. /// /// ``` /// struct CircleOnButtomView: View { /// var body: some View { /// Circle() /// .fill(BackgroundStyle()) /// Circle() /// } /// } /// ``` /// /// ![A view containing two circles, one filled background style, making it /// invisible, and the other with default black fill.](5D82A564-E230-45DB-8E6F-5D977044ACFC.png) /// @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) @frozen public struct BackgroundStyle { /// Creates a new background style. /// /// Use this to fill or stroke a shape. It will appear as solid white /// in light mode and solid black in dark mode. /// /// In the following example, the top circle is always invisible, since /// it is filled the same color as the background. /// /// ``` /// struct CircleOnButtomView: View { /// var body: some View { /// Circle() /// .fill(BackgroundStyle()) /// Circle() /// } /// } /// ``` /// /// ![A view containing two circles, one filled background style, making it /// invisible, and the other with default black fill.](5D82A564-E230-45DB-8E6F-5D977044ACFC.png) /// @inlinable public init() { } } @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) extension BackgroundStyle : ShapeStyle { } /// This type handles shared values across views. /// /// `Binding` is a property wrapper that creates a connection between stored /// data, and a view that displays and changes that data. It is a **two-way /// connection** to a source of truth. It is used to both read the latest /// value, as well as to set a new value. `Binding` defines a **getter** /// and a **setter** for a value. /// /// ### Structure of a `Binding` /// /// A `Binding` is essentially the following structure: /// /// ``` /// struct Binding { /// let get: () -> Value /// let set: (Value) -> () /// } /// ``` /// /// ### Creating a `Binding` from `@State` /// /// A `Binding` typically represents a reference to a mutable source of /// truth - such as `@State`, `@ObservedObject` or a reference-writable keypath /// of an object. To create a `Binding` from a mutable source of truth, /// prefix the variable name for the source of truth with a dollar sign (`$`). /// /// For example, a ``TextField`` can be bound to a state variable: /// /// ``` /// struct ExampleView: View { /// @State var text: String = "🍌🍌" /// /// var body: some View { /// Text(text) /// TextField("Placeholder", text: $text) /// } /// } /// ``` /// /// ![A gif showing a text field that displays the corresponding placeholder text in the view center until changed.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/Binding-example-1.gif) /// /// In the example above, the source of truth is a `@State` variable, /// named `text`. `text` represents a /// [`String`](https://developer.apple.com/documentation/swift/string), /// whereas `$text` represents /// a `Binding`. ``TextField``'s initializer accepts a placeholder /// [`String`](https://developer.apple.com/documentation/swift/string) and a /// `Binding`. In this example, `TextField` requires a /// ``Binding`` to the source of truth as ``TextField`` must be able to /// *write back* to the `@State` variable (a **mutable** source of truth). /// /// Recall, a `Binding` is a **two-way connection** to a source of truth. /// It is used to both read the latest value, as well as to set a new value. /// In the previous example, the view's initial render will display an /// editable text of "🍌🍌" on the screen - ``TextField`` reads the current /// value of the source of truth ``text`` via the `Binding` `$text`. When /// the user starts editing, ``TextField`` *writes back* new values to the /// source of truth `text` via the `Binding` `$text` once again. /// /// ### Creating a `Binding` from an ``ObservableObject`` /// /// In this example, the source of truth is an observable object /// `ExampleModel` - stored in a `@StateObject` owned by `ExampleView`: /// /// ``` /// struct ExampleView: View { /// @StateObject var viewModel = ExampleModel() /// /// var text: String { /// viewModel.isEnabled ? "Enabled" : "Disabled" /// } /// /// var body: some View { /// Toggle(text, isOn: $viewModel.isEnabled) /// } /// } /// /// class ExampleModel: ObservableObject { /// @Published var isEnabled: Bool = false /// } /// ``` /// /// ![A gif showing a view with the text "Disabled", which is replaced by "Enabled" when the corresponding toggle on the right side of the frame is clicked.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/Binding-example-2.gif) /// /// The binding between the model's `isEnabled` variable and a toggle is /// established using `$viewModel.isEnabled` within `ExampleView`'s body. /// Note that the dollar sign must prefix the **root** variable, even in the /// case where a child member is being referenced. `$viewModel.isEnabled` /// and `viewModel.$isEnabled` are **not** equivalent. The former creates a /// ``Binding`` to `isEnabled`, whereas the latter unwraps the projected /// value of the `@Published` property wrapper wrapping `isEnabled`. /// /// ### Animating Updates via a ``Binding`` /// /// Since a `Binding` is capable of updating a view's state, the state /// update can be made to animate with ``Binding/animation(_:)``. /// Usage looks as follows: /// /// ``` /// $myVariable.animation(.default) /// ``` /// /// ### Creating a ``Binding`` from a constant /// /// At times, you may want to pass a fixed value as a `Binding`. This is /// possible via ``Binding/constant(_:)``, which creates a `Binding` /// to a fixed value, ignoring any updates from the consumer of the binding. /// /// Consider ``EnvironmentValues/editMode``, for example. A ``List`` can be /// forced into active editing by passing a binding to `EditMode.active`. /// /// ``` /// struct ExampleView: View { /// @State var fruits = ["🍌", "🍏", "🍑"] /// /// var body: some View { /// List { /// ForEach(fruits, id: \.self) { fruit in /// Text(fruit) /// } /// .onDelete { offets in /// fruits.remove(atOffsets: offets) /// } /// } /// .environment(\.editMode, .constant(.active)) /// } /// } /// ``` /// /// ![A gif displaying a view containing a list with three members; the gif /// shows two of the items being deleted from the list.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/Binding-example-3.gif) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen @propertyWrapper @dynamicMemberLookup public struct Binding { /// The binding's transaction. /// /// The transaction captures the information needed to update the view when /// the binding value changes. public var transaction: Transaction /// Creates a binding with closures that read and write the binding value. /// /// - Parameters: /// - get: A closure that retrieves the binding value. The closure has no /// parameters, and returns a value. /// - set: A closure that sets the binding value. The closure has the /// following parameter: /// - newValue: The new value of the binding value. public init(get: @escaping () -> Value, set: @escaping (Value) -> Void) { } /// Creates a binding with a closure that reads from the binding value, and /// a closure that applies a transaction when writing to the binding value. /// /// - Parameters: /// - get: A closure to retrieve the binding value. The closure has no /// parameters, and returns a value. /// - set: A closure to set the binding value. The closure has the /// following parameters: /// - newValue: The new value of the binding value. /// - transaction: The transaction to apply when setting a new value. public init(get: @escaping () -> Value, set: @escaping (Value, Transaction) -> Void) { } /// Creates a binding with an immutable value. /// /// Use this method to create a binding to a value that cannot change. /// This can be useful when using a ``PreviewProvider`` to see how a view /// represents different values. /// /// // Example of binding to an immutable value. /// PlayButton(isPlaying: Binding.constant(true)) /// /// Another use case is for prototyping. For example: /// /// ``` /// struct ContentView: View { /// var body: some View { /// Toggle("Banana On", isOn: .constant(true)) /// } /// } /// ``` /// /// - Parameter value: An immutable value. public static func constant(_ value: Value) -> Binding { } /// The underlying value referenced by the binding variable. /// /// This property provides primary access to the value's data. However, you /// don't access `wrappedValue` directly. Instead, you use the property /// variable created with the `@Binding` attribute. For instance, in the /// following code example the binding variable `isPlaying` returns the /// value of `wrappedValue`: /// /// struct PlayButton: View { /// @Binding var isPlaying: Bool /// /// var body: some View { /// Button(action: { /// self.isPlaying.toggle() /// }) { /// Image(systemName: isPlaying ? "pause.circle" : "play.circle") /// } /// } /// } /// /// When a mutable binding value changes, the new value is immediately /// available. However, updates to a view displaying the value happens /// asynchronously, so the view may not show the change immediately. public var wrappedValue: Value { get /*nonmutating set*/ } /// A projection of the binding value that returns a binding. /// /// Use the projected value to pass a binding value down a view hierarchy. /// To get the `projectedValue`, prefix the property variable with `$`. For /// example, in the following code example `PlayerView` projects a binding /// of the state property `isPlaying` to the `PlayButton` view using /// `$isPlaying`. /// /// struct PlayerView: View { /// var episode: Episode /// @State private var isPlaying: Bool = false /// /// var body: some View { /// VStack { /// Text(episode.title) /// Text(episode.showTitle) /// PlayButton(isPlaying: $isPlaying) /// } /// } /// } public var projectedValue: Binding { get } /// Returns a binding to the resulting value of a given key path. /// /// - Parameter keyPath: A key path to a specific resulting value. /// /// - Returns: A new binding. public subscript(dynamicMember keyPath: WritableKeyPath) -> Binding { get } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Binding { /// Creates a binding by projecting the base value to an optional value. /// /// - Parameter base: A value to project to an optional value. public init(_ base: Binding) where Value == V? { } /// Creates a binding by projecting the base value to an unwrapped value. /// /// - Parameter base: A value to project to an unwrapped value. /// /// - Returns: A new binding or `nil` when `base` is `nil`. public init?(_ base: Binding) { } /// Creates a binding by projecting the base value to a hashable value. /// /// - Parameters: /// - base: A `Hashable` value to project to an `AnyHashable` value. public init(_ base: Binding) where Value == AnyHashable, V : Hashable { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Binding { /// Specifies a transaction for the binding. /// /// - Parameter transaction : An instance of a ``Transaction``. /// /// - Returns: A new binding. public func transaction(_ transaction: Transaction) -> Binding { } /// Specifies an animation to perform when the binding value changes. /// /// - Parameter animation: An animation sequence performed when the binding /// value changes. /// /// - Returns: A new binding. public func animation(_ animation: Animation? = .default) -> Binding { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Binding : DynamicProperty { } /// Modes for compositing a view with overlapping content. /// /// There are 21 different types of blend modes. To use the following example, /// drag in the following two photos and label them "ocean" and "space". /// /// ![Image of the ocean](ocean.jpg) /// /// ![Image of space](space.jpg) /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(BlendMode.softLight) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a blended image of the ocean and space.](blendmode-softLight.png) @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public enum BlendMode { /// Regular overlapping, with opacity taken into account. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.normal) /// } /// } /// } /// ``` /// /// ![A screenshot displaying the space image on top of the ocean image, /// with the normal blendmode rendering as a regular stack, so only the space /// image is visible.](blendmode-normal.png) /// case normal /// Multiplies the RGB channel numbers (0.0 - 1.0) of each pixel. /// /// The result is always a darker picture. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.multiply) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a dark blend between the ocean and space images.](blendmode-multiply.png) /// case multiply /// Each RGB pixel value is inverted (subtracted from 1), multiplied together, /// and then inverted back. /// /// The result is the opposite effect of multiply, and always a lighter /// picture. The results are also symmetric, so changing which layer is on /// top does not change the final picture. /// /// The formula for screen is this: /// /// func screen(a: Double, b: Double) { /// return 1 - (1 - a) * (1 - b) /// } /// /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.screen) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a light blend between the ocean and space images.](blendmode-screen.png) /// case screen /// The parts where the bottom layer is light become lighter, and dark /// becomes darker. /// /// Overlay is a combo of ``BlendMode/multiply`` and ``BlendMode/screen``. /// The formula is this: /// /// func overlay(a: Double, b: Double) -> Double { /// if a > 0.5 { /// return 2 * a * b /// } else { /// return 1 - 2 * (1 - a) * (1 - b) /// } /// } /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.overlay) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a blend between the ocean and space images /// in which the darks of the ocean appear darker, and the lights of the /// sand and space appear lighter.](blendmode-overlay.png) /// case overlay /// Takes the darker of the top and bottom picture pixels. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.darken) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a dark blend between space and the ocean, taking /// the darker of the top and bottom pixels.](blendmode-darken.png) /// case darken /// Takes the lighter of the top and bottom picture pixels. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.lighten) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a light blend between space and the ocean, taking /// the lighter of the top and bottom pixels.](blendmode-lighten.png) /// case lighten /// Divides the bottom layer by the inversion of the top layer. /// /// Color dodge is inspired by dodging in a darkroom. The bottom layer is /// lightened by an amount determined by the top layer - a brighter top /// layer results in a more brightened bottom layer. /// /// Blending any pixel with white will result in a white pixel. Blending any /// color with black will result in an unchanged pixel. /// /// This operation is not invertible. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.colorDodge) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a bright blend between space and the ocean.](blendmode-colorDodge.png) /// case colorDodge /// Divides the inverted bottom layer by the top layer, then inverts the result. /// /// The top layer is darkened by an amount determined by the bottom layer. /// /// Blending any pixel by white results in no change. /// /// This operation is not invertible. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.colorBurn) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a very dark blend between space and the ocean, /// in which nearly all pixels which are not very light turn to black.](blendmode-colorBurn.png) case colorBurn /// Basically, every light color gets a little lighter, and every dark color gets darker. /// /// The actual formula for the operation is this: /// /// func softLight(a: Double, b: Double) -> Double { /// if b < 0.5 { /// return 2*a*b + a*a*(1 - 2*b) /// } else { /// return 2*a*(1 - b) + sqrt(a)*(2*b - 1) /// } /// } /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.softLight) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a light blend between space and the ocean, /// in which the light colors appear lighter and the dark colors appear slightly darker.](blendmode-overlay.png) /// case softLight /// A combination of multiply and screen are applied. /// /// Hard light affects the bottom layer the way that overlay affects the top /// layer, and vice-versa. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.hardLight) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a blend between space and the ocean that mostly /// appears as space, the bottom layer.](blendmode-hardLight.png) /// case hardLight /// Subtracts the bottom layer from the top layer, and then makes the result positive. /// /// If either layer is black, nothing changes. Blending with white inverts /// the picture. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.difference) /// } /// } /// } /// ``` /// /// ![A colorful blend between space and the ocean.](blendmode-difference.png) /// case difference /// Subtracts the bottom layer from the top layer, and then makes the result positive. /// /// The difference between difference and exclusion is that blending with /// 50% gray will produce 50% gray. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.exclusion) /// } /// } /// } /// ``` /// /// ![A light and colorful blend between space and the ocean.](blendmode-exclusion.png) /// case exclusion /// Keeps the brightness and saturation of the bottom layer, while taking the hue of the top layer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.hue) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a blend between space and the ocean that maintains most features of /// the ocean image, while appearing to take the hue of the space image.](blendmode-hue.png) /// case hue /// Keeps the brightness and hue of the bottom layer, while taking the saturation of the top layer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.saturation) /// } /// } /// } /// ``` /// /// ![A screenshot displaying a blend between the ocean and space that appears /// to keep the brightness and hue of the ocean while taking the saturation of space.](blendmode-saturation.png) /// case saturation /// Keeps the brightness of the bottom layer, while taking the hue and saturation of the top layer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.color) /// } /// } /// } /// ``` /// /// ![A screenshot with an image in the center of the screen where the ocean is visible with a pinkish hue.](blendmode-color.png) /// case color /// Keeps the hue and saturation of the bottom layer, while taking the brightness of the top layer. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.luminosity) /// } /// } /// } /// ``` /// /// ![A screenshot with an image in the center of the screen that appears as a fairly even blend between space and ocean.](blendmode-luminosity.png) /// case luminosity /// Shows the bottom layer fully, with the top layer drawn only where it /// intersect the bottom. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.sourceAtop) /// } /// } /// } /// ``` /// /// ![A screenshot with an image in the center of the screen where only the space image is visible.](blendmode-sourceAtop.png) /// case sourceAtop /// The bottom is drawn over the top, and the top is only visible where the /// bottom is transparent. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.destinationOver) /// } /// } /// } /// ``` /// /// ![A screenshot with an image in the center of the screen where only the ocean image is visible.](blendmode-destinationOver.png) /// case destinationOver /// Displays only the bottom layer, and only where the top is transparent. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.destinationOut) /// } /// } /// } /// ``` /// /// ![A screenshot with an image in the center of the screen where the entire image is dark.](blendmode-destinationOut.png) /// case destinationOut /// Adds the top layer pixels to the bottom layer. /// /// Displays white where the addition is greater than `1.0`. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.plusDarker) /// } /// } /// } /// ``` /// /// ![A screenshot with an image in the center of the screen where the left half of the image is significantly darker than the right.](blendmode-plusDarker.png) /// case plusDarker /// Adds the top layer pixels to the bottom layer, than subtracts the result from 1. /// /// Displays black where the result is less than `0.0`. /// /// ``` /// struct ContentView: View { /// var body: some View { /// ZStack { /// Image("ocean") /// .resizable() /// .scaledToFit() /// /// Image("space") /// .resizable() /// .scaledToFit() /// .blendMode(.plusLighter) /// } /// } /// } /// ``` /// /// ![A screenshot with an image in the center of the screen where the right half of the image is significantly brighter than the left.](blendmode-plusLighter.png) /// case plusLighter /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. public static func == (a: BlendMode, b: BlendMode) -> Bool { } /// The hash value. /// /// Hash values are not guaranteed to be equal across different executions of /// your program. Do not save hash values to use during a future execution. /// /// - Important: `hashValue` is deprecated as a `Hashable` requirement. To /// conform to `Hashable`, implement the `hash(into:)` requirement instead. public var hashValue: Int { get } /// Hashes the essential components of this value by feeding them into the /// given hasher. /// /// Implement this method to conform to the `Hashable` protocol. The /// components used for hashing must be the same as the components compared /// in your type's `==` operator implementation. Call `hasher.combine(_:)` /// with each of these components. /// /// - Important: Never call `finalize()` on `hasher`. Doing so may become a /// compile-time error in the future. /// /// - Parameter hasher: The hasher to use when combining the components /// of this instance. public func hash(into hasher: inout Hasher) { } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension BlendMode : Equatable { } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension BlendMode : Hashable { } /// A menu style that displays a borderless button that toggles the display of /// the menu's contents when pressed. /// /// On macOS, the button optionally displays an arrow indicating that it presents /// a menu. /// /// Pressing and then dragging into the contents triggers the chosen action on /// release. /// /// For example: /// /// ``` /// struct BorderlessButtonMenuView: View { /// var body: some View { /// Menu("PDF") { /// Button("Open in Preview", action: { }) /// Button("Save as PDF", action: { }) /// } /// .menuStyle(BorderlessButtonMenuStyle()) /// } /// } /// ``` /// /// ![A gif displaying a view containing a borderless button style menu "PDF" that once clicked displays /// two buttons, "Open in Preview" and "Save as PDF", each with no action attached.](default-menu-example.gif) /// @available(iOS 14.0, macOS 11.0, *) @available(tvOS, unavailable) @available(watchOS, unavailable) public struct BorderlessButtonMenuStyle : MenuStyle { /// Creates a borderless button menu style. /// /// By default, the borderless style displays a visual indicator that it /// represents a menu. /// /// For example: /// /// ``` /// struct BorderlessButtonMenuView: View { /// var body: some View { /// Menu("PDF") { /// Button("Open in Preview", action: { }) /// Button("Save as PDF", action: { }) /// } /// .menuStyle(BorderlessButtonMenuStyle()) /// } /// } /// ``` /// /// ![A gif displaying a view containing a borderless button style menu "PDF" that once clicked displays /// two buttons, "Open in Preview" and "Save as PDF", each with no action attached.](default-menu-example.gif) /// public init() { } /// Creates a view that represents the body of a menu. /// /// - Parameter configuration: The properties of the menu. /// /// The system calls this method for each ``Menu`` instance in a view /// hierarchy where this style is the current menu style. public func makeBody(configuration: BorderlessButtonMenuStyle.Configuration) -> some View { } /// A view that represents the body of a menu. public typealias Body = some View } /// A button style that doesn't apply a border. /// /// struct ContentView: View { /// var body: some View { /// VStack { /// Button("Plain Banana🍌🍌", action: tap) /// .buttonStyle(PlainButtonStyle()) /// Button("Borderless Banana🍌🍌", action: tap) /// .buttonStyle(BorderlessButtonStyle()) /// Button("Default Banana🍌🍌", action: tap) /// .buttonStyle(DefaultButtonStyle()) /// } /// .font(.title2) /// } /// /// func tap() { /* implement here */ } /// } /// /// ![A view containing a VStack with three buttons; the first button is plain, /// the second is borderless, and the last is the default style.](https://bananadocs-documentation-assets.s3-us-west-2.amazonaws.com/buttonstyle-plain-border-default-example-1.png) /// /// To apply this style to a button, or to a view that contains buttons, use the /// ``View/buttonStyle(_:)-ea21b`` modifier. @available(iOS 13.0, macOS 10.15, *) @available(tvOS, unavailable) @available(watchOS, unavailable) public struct BorderlessButtonStyle : PrimitiveButtonStyle { /// Creates a borderless button style. public init() { } /// Creates a view that represents the body of a button. /// /// The system calls this method for each ``Button`` instance in a view /// hierarchy where this style is the current button style. /// /// - Parameter configuration : The properties of the button. public func makeBody(configuration: BorderlessButtonStyle.Configuration) -> some View { } /// A view that represents the body of a button. public typealias Body = some View } /// A control that performs an action when triggered. /// /// You create a button by providing an action and a label. The action is either /// a method or closure property that does something when a user clicks or taps /// the button. The label is a view that describes the button's action, for /// example, by showing text such as Cancel or an icon such as a back arrow. /// /// /// struct SignInView: View { /// var body: some View { /// Button(action: { /*sign the user in*/ }) { /// Text("Sign In") /// } /// } /// } /// /// ![Button with text reading "Sign in".](button-signin.png) /// /// For the common case of text-only labels, you can use the convenience /// initializer that takes a title string (or localized string key) as its first /// parameter, instead of a trailing closure: /// /// struct EasySignInView: View { /// var body: some View { /// Button("Sign In", action: { /*sign the user in*/ }) /// } /// } /// /// ![Button with text reading "Sign in".](button-signin.png) /// /// The method of triggering the button varies by platform: /// - In iOS and watchOS, the user triggers a standard button by tapping on it. /// - In macOS, the user triggers a standard button by clicking on it. /// - In tvOS, the user triggers a standard button by pressing "select" on an /// external remote, like the Siri Remote, while focusing on the button. /// /// ### Adding Buttons to Containers /// /// Use buttons for any user interface element that triggers actions on press. /// Buttons automatically adapt their visual style to match the expected style /// within these different containers and contexts. For example, to create a /// list cell that triggers an action when selected by the user, add a button to /// the list's content. For example: /// /// struct Item: Identifiable { /// let id = UUID() /// let title: String /// } /// /// struct ListView: View { /// let items = [Item(title: "🍌"), Item(title: "🍑")] /// var body: some View { /// // A list of items, where the last row, when triggered, /// // opens a UI for adding a new item. /// List { /// ForEach(items) { item in /// Text(item.title) /// } /// Button("Add Item", action: { /* add item */ } ) /// } /// } /// } /// /// ![A list with three items, the last of which is a button reading "Add Item".](AddItem.png) /// /// Similarly, to create a context menu item that triggers an action, add a /// button to the menu's content: /// /// struct ContextMenuView: View { /// var body: some View { /// Text("Press and hold for copy-paste options") /// .contextMenu { /// Button("Cut", action: { /* cut */ } ) /// Button("Copy", action: { /* copy */ } ) /// Button("Paste", action: { /* paste */ } ) /// } /// } /// } /// ///![A gif showing a view containing a button reading "Press and hold for copy-past options"; once the button is clicked, a pop-up containing three buttons, reading "Cut," "Copy," and "Paste", appears.](button-menu-content-ex.gif) /// /// This pattern extends to most other container views in SwiftUI that have /// customizable, interactive content, like forms (instances of ``Form``). /// /// ### Styling Buttons /// /// You can customize a button's appearance and interaction behavior. To add a /// custom appearance with standard interaction behavior, create a style that /// conforms to the ``ButtonStyle`` protocol. To customize both appearance and /// interaction behavior, create a style that conforms to the /// ``PrimitiveButtonStyle`` protocol. To set a specific style for all button /// instances within a view, use the ``View/buttonStyle(_:)-3c92f`` modifier: /// /// struct ButtonView: View { /// var body: some View { /// HStack { /// Button("Sign In", action: { /* sign in */ } ) /// Button("Register", action: { /* register */ } ) /// } /// .buttonStyle(PlainButtonStyle()) /// } /// } /// ///![A view containing an HStack with two plain text buttons, "Sign In" and "Register".](Plain-Button.png) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct Button