为什么可表达到自身的映射数组会产生错误?

Why does mapping array expressible to itself produce error?

我正在试验这个:

var orientations1: UIInterfaceOrientationMask = [.portrait, .landscapeRight]
var orientations2: UIInterfaceOrientationMask = [.portrait, .landscapeRight].map { [=10=] }

orientations1 工作正常,但 orientation2 产生以下错误:

Type of expression is ambiguous without more context

UIInterfaceOrientationMask 间接符合 ExpressibleByArrayLiteral 协议。 .map { [=19=] } 怎么可能改变数组的内容,我应该怎么做才能让它工作?

更新

好的,这就是我正在尝试做的事情。我正在学习 Swift 并想尝试在运行时更改设备方向。

我有 4 个开关:

@IBOutlet weak var switchPortrait: UISwitch!
@IBOutlet weak var switchLandscapeRight: UISwitch!
@IBOutlet weak var switchPortraitUpsideDown: UISwitch!
@IBOutlet weak var switchLandscapeLeft: UISwitch!

var orientationSwitches = [UISwitch]()
var orientations: UIInterfaceOrientationMask = [.portrait, .landscapeRight, .landscapeLeft, .portrait]

viewDidLoad() 方法中,我这样做:

switchPortrait.tag  = Int(UIInterfaceOrientationMask.portrait.rawValue)
switchLandscapeRight.tag = Int(UIInterfaceOrientationMask.landscapeRight.rawValue)
switchPortraitUpsideDown.tag   = Int(UIInterfaceOrientationMask.portraitUpsideDown.rawValue)
switchLandscapeLeft.tag  = Int(UIInterfaceOrientationMask.landscapeLeft.rawValue)

orientationSwitches = [switchPortrait, switchLandscapeRight, switchPortraitUpsideDown, switchLandscapeLeft]

for switchElement in orientationSwitches {
    switchElement.isOn = orientations.contains(UIInterfaceOrientationMask(rawValue: UInt(switchElement.tag)))
}

所以现在每个开关 UI 元素都将其标签设置为适当的方向掩码的原始值。此外,根据 orientations.

的初始状态,每个开关都会打开或关闭

关于切换操作,我正在尝试像这样更新 orientations

@IBAction func orientationSwitched(_ sender: UISwitch) {
    orientations = orientationSwitches.filter({ [=13=].isOn }).map({ UIInterfaceOrientationMask(rawValue: UInt([=13=].tag)) }) // doesn't work
}

但是没用。我的 supportedInterfaceOrientations 看起来就像这样:

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return orientations
}

我可以通过 insert() 方法为每个 UI 开关元素做到这一点,但我想了解是否可以通过映射以更优雅的方式完成。

Type of expression is ambiguous without more context

因为 Map 函数 returns 一个 array 值作为输出。因此,您需要像这样将推断类型更改为 array 以获得所需的 map 函数输出。

let  orientations2: [UIInterfaceOrientationMask] = [.portrait, .landscapeRight].map { [=10=] }

在 Swift 中,文字是无类型的,它们的类型是根据上下文推断的。

在你的例子中,如果 Swift 推断数组文字的类型为 Array< UIInterfaceOrientationMask>,你可以应用 .map{ [=12=] },但结果也变成 Array<UIInterfaceOrientationMask> 而不能转换为 UIInterfaceOrientationMask。 (见下文。)

如果 Swift 将数组文字的类型推断为 UIInterfaceOrientationMask,则 map 不可用。

因此,Swift 找不到与您的声明匹配的任何类型,这导致 Type of expression is ambiguous without more context.


正如您在另一个线程的评论中所建议的那样,编译器使用 ExpressibleByArrayLiteral 根据上下文解释数组文字。并不意味着数组可以自动转换为符合ExpressibleByArrayLiteral.

的类型

对于更新

如您所见,UIInterfaceOrientationMask 没有采用 Array 的常用初始化程序。所以使用 insert 是一种稳定的方式。稳定的代码比看似聪明但脆弱或难以阅读的代码更优雅。

如果你坚持使用看似聪明的代码,你可以这样写:

@IBAction func orientationSwitched(_ sender: UISwitch) {
    orientations = orientationSwitches
        .filter{[=10=].isOn}
        .map{UIInterfaceOrientationMask(rawValue: UInt([=10=].tag))}
        .reduce([]) {[=10=].union()}
}