Xcode报错:Value of type ‘Any’ has no subscripts
Xcode报错:Value of type ‘Any’ has no subscripts

Xcode报错:Value of type ‘Any’ has no subscripts

问题描述

在Xcode代码中,尝试使用print输出相关信息报错。

代码内容

print("2、inputRadius:\(filter.attributes["inputRadius"]?["CIAttributeDefault"] ?? 0)")

报错内容

Value of type 'Any' has no subscripts

报错原因

open class CIFilter : NSObject, NSSecureCoding, NSCopying {
    ...
    open var attributes: [String : Any] { get }
}

因为 filter.attributes[“inputRadius”] 返回的是一个 Any? 类型的值,而 Swift 不允许直接对 Any 类型进行下标操作。为了访问其中嵌套的键值对,需要先将它强制转换为适当的类型,比如 [String: Any]。

解决方案

解决代码

if let inputRadiusAttributes = filter.attributes["inputRadius"] as? [String: Any] {
    let defaultValue = inputRadiusAttributes["CIAttributeDefault"] ?? "nil"
    print("2、inputRadius: \(defaultValue)")
} else {
    print("2、inputRadius: nil")
}

问题分析

上面的问题主要涉及返回值类型的转换,filter.attributes 本身是 [String: Any] 类型, 但是当通过键访问字典时,比如:

filter.attributes["inputRadius"]    // return Any?

Swift 返回的是 Any?因为:

1、键值对中的值可以是任何类型。

2、键可能不存在,返回值因此是可选的。

为了安全地操作 filter.attributes[“inputRadius”] 的内容,我们需要将其从 Any? 转换为 [String: Any] 类型。

为什么需要 as? [String: Any]

filter.attributes[“inputRadius”] 返回的值是 Any?,我们需要确认它是否是一个 [String: Any] 类型的字典并安全地解包,以便进一步访问内部的键值。通过 as? [String: Any],我们可以:

1、确认类型

如果值确实是 [String: Any],转换成功并返回对应的字典。

let inputRadiusAttributes = filter.attributes["inputRadius"] as? [String: Any]

2、避免运行时错误

如果值不是 [String: Any] 类型,as? 返回 nil,代码不会崩溃。

if let inputRadiusAttributes = filter.attributes["inputRadius"] as? [String: Any] {
    // 安全访问字典内容
} else {
    // 无法转换,安全处理
}

3、为什么不能直接当作 [String: Any] 使用?

因为编译器不知道 filter.attributes[“inputRadius”] 的类型就是 [String: Any],即使已经“知道”它的类型也不能直接使用。Swift 类型系统是严格的,要求开发者明确声明和检查类型以避免潜在的类型错误。

直接转换问题

如果尝试直接转换代码:

filter.attributes["inputRadius"]["CIAttributeDefault"] as? [String: Any][String]

就会遇到如下报错:

Array types are now written with the brackets around the element type
Replace '[String: Any][' with '[[String: Any]'
Value of type 'Any?' has no subscripts

原因为:filter.attributes[“inputRadius”] 返回的是 Any?,不能直接用 [“CIAttributeDefault”] 访问其内部值。Swift 不允许对 Any? 类型直接进行下标操作。

此外,as? [String: Any][String] 是非法语法。在 Swift 中,as? 后面必须是一个合法的单一类型。[String: Any][String] 并不是一个合法的类型声明。所以应该拆成两步:

1、将 filter.attributes[“inputRadius”] 转换为 [String: Any]。

2、从 [String: Any] 中访问 CIAttributeDefault 的值。

对下标嵌套的误用
filter.attributes["inputRadius"]["CIAttributeDefault"]

filter.attributes[“inputRadius”] 直接使用下标访问 [“CIAttributeDefault”]。但 filter.attributes[“inputRadius”] 是 Any? 类型,无法直接下标操作,必须显式解包和类型转换。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注