类型 '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,因为它在上面被声明为一个。 NSArrays 可以被下标以获取给定索引处的值,就像您对 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 来说极为罕见)。

cellDescriptorscellsToDisplay 转换为适当的 Array 类型而不是 NSMutableArray。 "Appropriate" 意味着 "an array of whatever is actually in it." 这意味着 [Any] 不是合适的类型。如果 cellsToDisplay 包含一堆 Cell 个对象,那么它应该是 [Cell].