类型 'Any' 没有下标成员 - NSMutableArray
Type 'Any' has no subscript members - NSMutableArray
我们导入了一个过时的项目,它提示我们将其转换为 Swift 3. 作为对 Swift 了解不多的人,我们很难修复错误。
import Foundation
class CellDescriptorHelper {
let itemKey = "Items"
let isExpandableKey = "isExpandable"
let isExpandedKey = "isExpanded"
let isVisibleKey = "isVisible"
let titleKey = "title"
let locationKey = "location"
let descriptionKey = "description"
let imageURLKey = "imageURL"
let typeKey = "type"
let cellIdentifierKey = "cellIdentifier"
let additionalRowsKey = "additionalRows"
fileprivate var cellDescriptors: NSMutableArray!
fileprivate var cellsToDisplay: NSMutableArray!
func getCellDescriptors(_ type: String) -> NSMutableArray {
loadCellDescriptors(type)
return cellDescriptors;
}
func loadCellDescriptors(_ type: String) {
cellDescriptors = PlistManager.sharedInstance.getValueForKey(itemKey)! as! NSMutableArray
for i in 0..<(cellDescriptors[0] as AnyObject).count-1 {
let cellType = cellDescriptors[0][i][typeKey] as! String //creates error
if(cellType != type) {
cellDescriptors[0][i].setValue(false, forKey: isVisibleKey) //creates error
}
}
}
}
NSMutableArray 真的不能说明什么...避免强制解包并尝试考虑数组应该首先是哪种类型。起初,根据下标,数组应该包含在下一个数组中......所以尝试 OverType 它而不是 NSMutableArray 来键入:[[Any]] 但这个选项真的一点都不安全!
请提供有关 itemKey 值应该是什么的更多信息...但总的来说,我最好的建议是:
func loadCellDescriptors(_ type: String) {
guard let cellDescriptors = PlistManager.sharedInstance.getValueForKey(itemKey)? as? [[String: Any]], let firstDescriptor = cellDescriptors[0]
else { return }
for someKeyInDict in 0..<cellDescriptor.count{
if let cellType = cellDescriptor[i][typeKey] as? String{
if(cellType != type) {
cellDescriptors[0][i].setValue(false, forKey: isVisibleKey)
}
}
}
这不会 100% 工作,但会让你更接近,我只是提示你搜索的值是字典...
您收到此错误的原因是数组中的对象类型对编译器而言不明确。
这是因为 NSArray
没有具体输入。
NSArray
基本上是 Array<Any>
或 [Any]
的 Objective-C 桥梁。
让我来介绍一下您的代码...
let cellType = cellDescriptors[0][i][typeKey] as! String
编译器知道 cellDescriptors
是一个 NSArray
,因为它在上面被声明为一个。 NSArray
s 可以被下标以获取给定索引处的值,就像您对 cellDescriptors[0]
所做的那样。如上所述,它给出的值是 Any
类型,因此当您尝试使用 cellDescriptors[0][i]
再次下标时,您会收到错误消息。碰巧的是,您可能会将 Any
对象转换为数组,然后您将能够执行下标,如下所示:
if let newArr = (cellDescriptors[0] as? [Any])[i] { }
但是,这确实不是一个好的方法,您最终会处理大量讨厌的可选值。
更好的方法是具体化 cellDescriptors
的声明。我不知道您的类型结构如何,但从外观上看,它是字典数组的数组(糟糕)。因此,在原始形式中,您的声明应该是 var cellDescriptors = [[[AnyHashable:Any]]]()
以便像现在这样下标。
这就是说,您现有的代码很混乱,我会考虑更改您对对象建模的方式以使其更有用。
这些行有两个问题:
fileprivate var cellDescriptors: NSMutableArray!
fileprivate var cellsToDisplay: NSMutableArray!
首先,它们是 !
类型(隐式解包可选或 IUO)。它们永远不应该是 !
类型,但在 Swift 3 中它们的工作方式与在 Swift 2 中不同,这可能会让你崩溃。摆脱 !
并将它们分配给一个空数组以开始。很少有 !
类型仍然有用的地方(@IBOutlet
是 !
类型可能适用的最后保留之一,至少作为一个意见。)
另一个问题是 NSMutableArray
是一种草率的类型,它在 Swift 中造成了很多麻烦。它应该只在非常罕见的情况下使用,即 Objective-C 的桥梁需要它(这对于 NSMutableArray
来说极为罕见)。
将 cellDescriptors
和 cellsToDisplay
转换为适当的 Array
类型而不是 NSMutableArray
。 "Appropriate" 意味着 "an array of whatever is actually in it." 这意味着 [Any]
不是合适的类型。如果 cellsToDisplay
包含一堆 Cell
个对象,那么它应该是 [Cell]
.
我们导入了一个过时的项目,它提示我们将其转换为 Swift 3. 作为对 Swift 了解不多的人,我们很难修复错误。
import Foundation
class CellDescriptorHelper {
let itemKey = "Items"
let isExpandableKey = "isExpandable"
let isExpandedKey = "isExpanded"
let isVisibleKey = "isVisible"
let titleKey = "title"
let locationKey = "location"
let descriptionKey = "description"
let imageURLKey = "imageURL"
let typeKey = "type"
let cellIdentifierKey = "cellIdentifier"
let additionalRowsKey = "additionalRows"
fileprivate var cellDescriptors: NSMutableArray!
fileprivate var cellsToDisplay: NSMutableArray!
func getCellDescriptors(_ type: String) -> NSMutableArray {
loadCellDescriptors(type)
return cellDescriptors;
}
func loadCellDescriptors(_ type: String) {
cellDescriptors = PlistManager.sharedInstance.getValueForKey(itemKey)! as! NSMutableArray
for i in 0..<(cellDescriptors[0] as AnyObject).count-1 {
let cellType = cellDescriptors[0][i][typeKey] as! String //creates error
if(cellType != type) {
cellDescriptors[0][i].setValue(false, forKey: isVisibleKey) //creates error
}
}
}
}
NSMutableArray 真的不能说明什么...避免强制解包并尝试考虑数组应该首先是哪种类型。起初,根据下标,数组应该包含在下一个数组中......所以尝试 OverType 它而不是 NSMutableArray 来键入:[[Any]] 但这个选项真的一点都不安全!
请提供有关 itemKey 值应该是什么的更多信息...但总的来说,我最好的建议是:
func loadCellDescriptors(_ type: String) {
guard let cellDescriptors = PlistManager.sharedInstance.getValueForKey(itemKey)? as? [[String: Any]], let firstDescriptor = cellDescriptors[0]
else { return }
for someKeyInDict in 0..<cellDescriptor.count{
if let cellType = cellDescriptor[i][typeKey] as? String{
if(cellType != type) {
cellDescriptors[0][i].setValue(false, forKey: isVisibleKey)
}
}
}
这不会 100% 工作,但会让你更接近,我只是提示你搜索的值是字典...
您收到此错误的原因是数组中的对象类型对编译器而言不明确。
这是因为 NSArray
没有具体输入。
NSArray
基本上是 Array<Any>
或 [Any]
的 Objective-C 桥梁。
让我来介绍一下您的代码...
let cellType = cellDescriptors[0][i][typeKey] as! String
编译器知道 cellDescriptors
是一个 NSArray
,因为它在上面被声明为一个。 NSArray
s 可以被下标以获取给定索引处的值,就像您对 cellDescriptors[0]
所做的那样。如上所述,它给出的值是 Any
类型,因此当您尝试使用 cellDescriptors[0][i]
再次下标时,您会收到错误消息。碰巧的是,您可能会将 Any
对象转换为数组,然后您将能够执行下标,如下所示:
if let newArr = (cellDescriptors[0] as? [Any])[i] { }
但是,这确实不是一个好的方法,您最终会处理大量讨厌的可选值。
更好的方法是具体化 cellDescriptors
的声明。我不知道您的类型结构如何,但从外观上看,它是字典数组的数组(糟糕)。因此,在原始形式中,您的声明应该是 var cellDescriptors = [[[AnyHashable:Any]]]()
以便像现在这样下标。
这就是说,您现有的代码很混乱,我会考虑更改您对对象建模的方式以使其更有用。
这些行有两个问题:
fileprivate var cellDescriptors: NSMutableArray!
fileprivate var cellsToDisplay: NSMutableArray!
首先,它们是 !
类型(隐式解包可选或 IUO)。它们永远不应该是 !
类型,但在 Swift 3 中它们的工作方式与在 Swift 2 中不同,这可能会让你崩溃。摆脱 !
并将它们分配给一个空数组以开始。很少有 !
类型仍然有用的地方(@IBOutlet
是 !
类型可能适用的最后保留之一,至少作为一个意见。)
另一个问题是 NSMutableArray
是一种草率的类型,它在 Swift 中造成了很多麻烦。它应该只在非常罕见的情况下使用,即 Objective-C 的桥梁需要它(这对于 NSMutableArray
来说极为罕见)。
将 cellDescriptors
和 cellsToDisplay
转换为适当的 Array
类型而不是 NSMutableArray
。 "Appropriate" 意味着 "an array of whatever is actually in it." 这意味着 [Any]
不是合适的类型。如果 cellsToDisplay
包含一堆 Cell
个对象,那么它应该是 [Cell]
.