美文网首页
Swift Optional 类型

Swift Optional 类型

作者: KAKA_move | 来源:发表于2019-03-17 12:42 被阅读0次

    Optional 是Swift标准库中的类型,

    • 代表一个解包值或者一个缺席值nil
    • 是枚举类型
    • 遵守ExpressibleByNilLiteral协议

    只要使用了可选值就会用到Optional类型,没有出现Optional关键字是因为?座位简写替代之。Int? == Optional<Int>

     let shortForm: Int? = Int("42")
     let longForm: Optional<Int> = Int("42")
    

    Optional是有两个cases的枚举,Optional.none匹配nil,Optional.some(Wrapped)存储解包值。

    ///     let number: Int? = Optional.some(42)
    ///     let noNumber: Int? = Optional.none
    ///     print(noNumber == nil)
    ///     // Prints "true"
    

    很多上下文中,必须解包Optional实例才能使用。Swift推出了几种安全的解包方式实现简洁清晰的代码。

    public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    
        /// The absence of a value.
        ///
        /// In code, the absence of a value is typically written using the `nil`
        /// literal rather than the explicit `.none` enumeration case.
        case none
    
        /// The presence of a value, stored as `Wrapped`.
        case some(Wrapped)
    
        /// Creates an instance that stores the given value.
        public init(_ some: Wrapped)
    
        /// Evaluates the given closure when this `Optional` instance is not `nil`,
        /// passing the unwrapped value as a parameter.
        ///
        /// Use the `map` method with a closure that returns a nonoptional value.
        /// This example performs an arithmetic operation on an
        /// optional integer.
        ///
        ///     let possibleNumber: Int? = Int("42")
        ///     let possibleSquare = possibleNumber.map { $0 * $0 }
        ///     print(possibleSquare)
        ///     // Prints "Optional(1764)"
        ///
        ///     let noNumber: Int? = nil
        ///     let noSquare = noNumber.map { $0 * $0 }
        ///     print(noSquare)
        ///     // Prints "nil"
        ///
        /// - Parameter transform: A closure that takes the unwrapped value
        ///   of the instance.
        /// - Returns: The result of the given closure. If this instance is `nil`,
        ///   returns `nil`.
        public func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?
    
        /// Evaluates the given closure when this `Optional` instance is not `nil`,
        /// passing the unwrapped value as a parameter.
        ///
        /// Use the `flatMap` method with a closure that returns an optional value.
        /// This example performs an arithmetic operation with an optional result on
        /// an optional integer.
        ///
        ///     let possibleNumber: Int? = Int("42")
        ///     let nonOverflowingSquare = possibleNumber.flatMap { x -> Int? in
        ///         let (result, overflowed) = x.multipliedReportingOverflow(by: x)
        ///         return overflowed ? nil : result
        ///     }
        ///     print(nonOverflowingSquare)
        ///     // Prints "Optional(1764)"
        ///
        /// - Parameter transform: A closure that takes the unwrapped value
        ///   of the instance.  
        /// - Returns: The result of the given closure. If this instance is `nil`,
        ///   returns `nil`.
        public func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
    
        /// Creates an instance initialized with `nil`.
        ///
        /// Do not call this initializer directly. It is used by the compiler when you
        /// initialize an `Optional` instance with a `nil` literal. For example:
        ///
        ///     var i: Index? = nil
        ///
        /// In this example, the assignment to the `i` variable calls this
        /// initializer behind the scenes.
        public init(nilLiteral: ())
    
        /// The wrapped value of this instance, unwrapped without checking whether
        /// the instance is `nil`.
        ///
        /// The `unsafelyUnwrapped` property provides the same value as the forced
        /// unwrap operator (postfix `!`). However, in optimized builds (`-O`), no
        /// check is performed to ensure that the current instance actually has a
        /// value. Accessing this property in the case of a `nil` value is a serious
        /// programming error and could lead to undefined behavior or a runtime
        /// error.
        ///
        /// In debug builds (`-Onone`), the `unsafelyUnwrapped` property has the same
        /// behavior as using the postfix `!` operator and triggers a runtime error
        /// if the instance is `nil`.
        ///
        /// The `unsafelyUnwrapped` property is recommended over calling the
        /// `unsafeBitCast(_:)` function because the property is more restrictive
        /// and because accessing the property still performs checking in debug
        /// builds.
        ///
        /// - Warning: This property trades safety for performance.  Use
        ///   `unsafelyUnwrapped` only when you are confident that this instance
        ///   will never be equal to `nil` and only after you've tried using the
        ///   postfix `!` operator.
        public var unsafelyUnwrapped: Wrapped { get }
    
        /// Returns a Boolean value indicating whether an argument matches `nil`.
        ///
        /// You can use the pattern-matching operator (`~=`) to test whether an
        /// optional instance is `nil` even when the wrapped value's type does not
        /// conform to the `Equatable` protocol. The pattern-matching operator is used
        /// internally in `case` statements for pattern matching.
        ///
        /// The following example declares the `stream` variable as an optional
        /// instance of a hypothetical `DataStream` type, and then uses a `switch`
        /// statement to determine whether the stream is `nil` or has a configured
        /// value. When evaluating the `nil` case of the `switch` statement, this
        /// operator is called behind the scenes.
        ///
        ///     var stream: DataStream? = nil
        ///     switch stream {
        ///     case nil:
        ///         print("No data stream is configured.")
        ///     case let x?:
        ///         print("The data stream has \(x.availableBytes) bytes available.")
        ///     }
        ///     // Prints "No data stream is configured."
        ///
        /// - Note: To test whether an instance is `nil` in an `if` statement, use the
        ///   equal-to operator (`==`) instead of the pattern-matching operator. The
        ///   pattern-matching operator is primarily intended to enable `case`
        ///   statement pattern matching.
        ///
        /// - Parameters:
        ///   - lhs: A `nil` literal.
        ///   - rhs: A value to match against `nil`.
        public static func ~= (lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool
    
        /// Returns a Boolean value indicating whether the left-hand-side argument is
        /// `nil`.
        ///
        /// You can use this equal-to operator (`==`) to test whether an optional
        /// instance is `nil` even when the wrapped value's type does not conform to
        /// the `Equatable` protocol.
        ///
        /// The following example declares the `stream` variable as an optional
        /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
        /// an `Equatable` type, this operator allows checking whether `stream` is
        /// `nil`.
        ///
        ///     var stream: DataStream? = nil
        ///     if stream == nil {
        ///         print("No data stream is configured.")
        ///     }
        ///     // Prints "No data stream is configured."
        ///
        /// - Parameters:
        ///   - lhs: A value to compare to `nil`.
        ///   - rhs: A `nil` literal.
        public static func == (lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool
    
        /// Returns a Boolean value indicating whether the left-hand-side argument is
        /// not `nil`.
        ///
        /// You can use this not-equal-to operator (`!=`) to test whether an optional
        /// instance is not `nil` even when the wrapped value's type does not conform
        /// to the `Equatable` protocol.
        ///
        /// The following example declares the `stream` variable as an optional
        /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
        /// an `Equatable` type, this operator allows checking whether `stream` wraps
        /// a value and is therefore not `nil`.
        ///
        ///     var stream: DataStream? = fetchDataStream()
        ///     if stream != nil {
        ///         print("The data stream has been configured.")
        ///     }
        ///     // Prints "The data stream has been configured."
        ///
        /// - Parameters:
        ///   - lhs: A value to compare to `nil`.
        ///   - rhs: A `nil` literal.
        public static func != (lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool
    
        /// Returns a Boolean value indicating whether the right-hand-side argument is
        /// `nil`.
        ///
        /// You can use this equal-to operator (`==`) to test whether an optional
        /// instance is `nil` even when the wrapped value's type does not conform to
        /// the `Equatable` protocol.
        ///
        /// The following example declares the `stream` variable as an optional
        /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
        /// an `Equatable` type, this operator allows checking whether `stream` is
        /// `nil`.
        ///
        ///     var stream: DataStream? = nil
        ///     if nil == stream {
        ///         print("No data stream is configured.")
        ///     }
        ///     // Prints "No data stream is configured."
        ///
        /// - Parameters:
        ///   - lhs: A `nil` literal.
        ///   - rhs: A value to compare to `nil`.
        public static func == (lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool
    
        /// Returns a Boolean value indicating whether the right-hand-side argument is
        /// not `nil`.
        ///
        /// You can use this not-equal-to operator (`!=`) to test whether an optional
        /// instance is not `nil` even when the wrapped value's type does not conform
        /// to the `Equatable` protocol.
        ///
        /// The following example declares the `stream` variable as an optional
        /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
        /// an `Equatable` type, this operator allows checking whether `stream` wraps
        /// a value and is therefore not `nil`.
        ///
        ///     var stream: DataStream? = fetchDataStream()
        ///     if nil != stream {
        ///         print("The data stream has been configured.")
        ///     }
        ///     // Prints "The data stream has been configured."
        ///
        /// - Parameters:
        ///   - lhs: A `nil` literal.
        ///   - rhs: A value to compare to `nil`.
        public static func != (lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool
    }
    
    extension Optional : CustomDebugStringConvertible {
    
        /// A textual representation of this instance, suitable for debugging.
        public var debugDescription: String { get }
    }
    
    extension Optional : CustomReflectable {
    
        /// 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 }
    }
    
    extension Optional {
    
        /// Returns a Boolean value indicating whether two values are not equal.
        ///
        /// Inequality is the inverse of equality. For any values `a` and `b`, `a != b`
        /// implies that `a == b` is `false`.
        ///
        /// This is the default implementation of the not-equal-to operator (`!=`)
        /// for any type that conforms to `Equatable`.
        ///
        /// - Parameters:
        ///   - lhs: A value to compare.
        ///   - rhs: Another value to compare.
        public static func != (lhs: Optional<Wrapped>, rhs: Optional<Wrapped>) -> Bool
    }
    
    extension Optional : Encodable where Wrapped : Encodable {
    
        /// Encodes this optional value into the given encoder.
        ///
        /// This function throws an error if any values are invalid for the given
        /// encoder's format.
        ///
        /// - Parameter encoder: The encoder to write data to.
        public func encode(to encoder: Encoder) throws
    }
    
    extension Optional : Decodable where Wrapped : Decodable {
    
        /// Creates a new instance by decoding from the given decoder.
        ///
        /// This initializer throws an error if reading from the decoder fails, or
        /// if the data read is corrupted or otherwise invalid.
        ///
        /// - Parameter decoder: The decoder to read data from.
        public init(from decoder: Decoder) throws
    }
    
    extension Optional : Hashable where Wrapped : Hashable {
    
        /// Hashes the essential components of this value by feeding them into the
        /// given hasher.
        ///
        /// - Parameter hasher: The hasher to use when combining the components
        ///   of this instance.
        public func hash(into hasher: inout Hasher)
    }
    
    extension Optional : Equatable where Wrapped : Equatable {
    
        /// Returns a Boolean value indicating whether two optional instances are
        /// equal.
        ///
        /// Use this equal-to operator (`==`) to compare any two optional instances of
        /// a type that conforms to the `Equatable` protocol. The comparison returns
        /// `true` if both arguments are `nil` or if the two arguments wrap values
        /// that are equal. Conversely, the comparison returns `false` if only one of
        /// the arguments is `nil` or if the two arguments wrap values that are not
        /// equal.
        ///
        ///     let group1 = [1, 2, 3, 4, 5]
        ///     let group2 = [1, 3, 5, 7, 9]
        ///     if group1.first == group2.first {
        ///         print("The two groups start the same.")
        ///     }
        ///     // Prints "The two groups start the same."
        ///
        /// You can also use this operator to compare a nonoptional value to an
        /// optional that wraps the same type. The nonoptional value is wrapped as an
        /// optional before the comparison is made. In the following example, the
        /// `numberToMatch` constant is wrapped as an optional before comparing to the
        /// optional `numberFromString`:
        ///
        ///     let numberToFind: Int = 23
        ///     let numberFromString: Int? = Int("23")      // Optional(23)
        ///     if numberToFind == numberFromString {
        ///         print("It's a match!")
        ///     }
        ///     // Prints "It's a match!"
        ///
        /// An instance that is expressed as a literal can also be used with this
        /// operator. In the next example, an integer literal is compared with the
        /// optional integer `numberFromString`. The literal `23` is inferred as an
        /// `Int` instance and then wrapped as an optional before the comparison is
        /// performed.
        ///
        ///     if 23 == numberFromString {
        ///         print("It's a match!")
        ///     }
        ///     // Prints "It's a match!"
        ///
        /// - Parameters:
        ///   - lhs: An optional value to compare.
        ///   - rhs: Another optional value to compare.
        public static func == (lhs: Wrapped?, rhs: Wrapped?) -> Bool
    
        /// Returns a Boolean value indicating whether two optional instances are not
        /// equal.
        ///
        /// Use this not-equal-to operator (`!=`) to compare any two optional instances
        /// of a type that conforms to the `Equatable` protocol. The comparison
        /// returns `true` if only one of the arguments is `nil` or if the two
        /// arguments wrap values that are not equal. The comparison returns `false`
        /// if both arguments are `nil` or if the two arguments wrap values that are
        /// equal.
        ///
        ///     let group1 = [2, 4, 6, 8, 10]
        ///     let group2 = [1, 3, 5, 7, 9]
        ///     if group1.first != group2.first {
        ///         print("The two groups start differently.")
        ///     }
        ///     // Prints "The two groups start differently."
        ///
        /// You can also use this operator to compare a nonoptional value to an
        /// optional that wraps the same type. The nonoptional value is wrapped as an
        /// optional before the comparison is made. In this example, the
        /// `numberToMatch` constant is wrapped as an optional before comparing to the
        /// optional `numberFromString`:
        ///
        ///     let numberToFind: Int = 23
        ///     let numberFromString: Int? = Int("not-a-number")      // nil
        ///     if numberToFind != numberFromString {
        ///         print("No match.")
        ///     }
        ///     // Prints "No match."
        ///
        /// - Parameters:
        ///   - lhs: An optional value to compare.
        ///   - rhs: Another optional value to compare.
        public static func != (lhs: Wrapped?, rhs: Wrapped?) -> Bool
    }
    
    /// Performs a nil-coalescing operation, returning the wrapped value of an
    /// `Optional` instance or a default value.
    ///
    /// A nil-coalescing operation unwraps the left-hand side if it has a value, or
    /// it returns the right-hand side as a default. The result of this operation
    /// will have the nonoptional type of the left-hand side's `Wrapped` type.
    ///
    /// This operator uses short-circuit evaluation: `optional` is checked first,
    /// and `defaultValue` is evaluated only if `optional` is `nil`. For example:
    ///
    ///     func getDefault() -> Int {
    ///         print("Calculating default...")
    ///         return 42
    ///     }
    ///
    ///     let goodNumber = Int("100") ?? getDefault()
    ///     // goodNumber == 100
    ///
    ///     let notSoGoodNumber = Int("invalid-input") ?? getDefault()
    ///     // Prints "Calculating default..."
    ///     // notSoGoodNumber == 42
    ///
    /// In this example, `goodNumber` is assigned a value of `100` because
    /// `Int("100")` succeeded in returning a non-`nil` result. When
    /// `notSoGoodNumber` is initialized, `Int("invalid-input")` fails and returns
    /// `nil`, and so the `getDefault()` method is called to supply a default
    /// value.
    ///
    /// - Parameters:
    ///   - optional: An optional value.
    ///   - defaultValue: A value to use as a default. `defaultValue` is the same
    ///     type as the `Wrapped` type of `optional`.
    public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
    
    /// Performs a nil-coalescing operation, returning the wrapped value of an
    /// `Optional` instance or a default `Optional` value.
    ///
    /// A nil-coalescing operation unwraps the left-hand side if it has a value, or
    /// returns the right-hand side as a default. The result of this operation
    /// will be the same type as its arguments.
    ///
    /// This operator uses short-circuit evaluation: `optional` is checked first,
    /// and `defaultValue` is evaluated only if `optional` is `nil`. For example:
    ///
    ///     let goodNumber = Int("100") ?? Int("42")
    ///     print(goodNumber)
    ///     // Prints "Optional(100)"
    ///
    ///     let notSoGoodNumber = Int("invalid-input") ?? Int("42")
    ///     print(notSoGoodNumber)
    ///     // Prints "Optional(42)"
    ///
    /// In this example, `goodNumber` is assigned a value of `100` because
    /// `Int("100")` succeeds in returning a non-`nil` result. When
    /// `notSoGoodNumber` is initialized, `Int("invalid-input")` fails and returns
    /// `nil`, and so `Int("42")` is called to supply a default value.
    ///
    /// Because the result of this nil-coalescing operation is itself an optional
    /// value, you can chain default values by using `??` multiple times. The
    /// first optional value that isn't `nil` stops the chain and becomes the
    /// result of the whole expression. The next example tries to find the correct
    /// text for a greeting in two separate dictionaries before falling back to a
    /// static default.
    ///
    ///     let greeting = userPrefs[greetingKey] ??
    ///         defaults[greetingKey] ?? "Greetings!"
    ///
    /// If `userPrefs[greetingKey]` has a value, that value is assigned to
    /// `greeting`. If not, any value in `defaults[greetingKey]` will succeed, and
    /// if not that, `greeting` will be set to the nonoptional default value,
    /// `"Greetings!"`.
    ///
    /// - Parameters:
    ///   - optional: An optional value.
    ///   - defaultValue: A value to use as a default. `defaultValue` and
    ///     `optional` have the same type.
    public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T?
    
    
    

    网络资料:http://www.cocoachina.com/ios/20161124/18172.html

    相关文章

      网友评论

          本文标题:Swift Optional 类型

          本文链接:https://www.haomeiwen.com/subject/mfoymqtx.html