令人困惑的错误:地图变量的可选性将其从单个对象更改为数组

mea*_*ers 1 arrays dictionary swift

我有:

private var wrappedObjects: [WrapperClass]?

var objects: [SomeClass]?
{
    didSet
    {
        self.wrappedObjects = objects.map{ WrapperClass($0) }
    }
}
Run Code Online (Sandbox Code Playgroud)

这会导致以下错误:

`Cannot convert value of type '[SomeClass]' to expected argument type 'SomeClass'`
Run Code Online (Sandbox Code Playgroud)

但是当我只改变一行时:

var objects: [SomeClass] = []
Run Code Online (Sandbox Code Playgroud)

错误消失了.

为什么的可选性objects品牌map认为$0是一个单一的SomeClass或数组[SomeClass]分别?

Ham*_*ish 5

这里的问题是有两个map(_:)功能.一个序列:

public protocol Sequence {
    // ...

    /// Returns an array containing the results of mapping the given closure
    /// over the sequence's elements.
    /// 
    /// - Parameter transform: A mapping closure. `transform` accepts an
    ///   element of this sequence as its parameter and returns a transformed
    ///   value of the same or of a different type.
    /// - Returns: An array containing the transformed elements of this
    ///   sequence.
    func map<T>(_ transform: (Iterator.Element) throws -> T) rethrows -> [T]

    // ...
}
Run Code Online (Sandbox Code Playgroud)

一个选项:

public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    // ...

    /// Evaluates the given closure when this `Optional` instance is not `nil`,
    /// passing the unwrapped value as a parameter.
    ///
    /// - 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?

    // ...
}
Run Code Online (Sandbox Code Playgroud)

因此,当您调用mapa时[SomeClass]?,map将使用第二个函数,其中转换函数参数将是类型[SomeClass],map将为您解包,并将给定的转换应用于它.

但是,当你调用mapa时[SomeClass],map将使用第一个函数,其中元素将被迭代 - 将变换函数应用于它们中的每一个.因此,转换函数的参数类型将是SomeClass.

因此,一个有趣的解决方案是使用map两次 - 一次打开,一次将变换应用于元素:

self.wrappedObjects = objects.map{ $0.map{ WrapperClass($0) } }
Run Code Online (Sandbox Code Playgroud)

然而,这绝对是荒谬的,你应该使用Rob建议的可选链接.