【问题标题】:Making table view section expand swift使表格视图部分快速展开
【发布时间】:2017-10-04 16:57:08
【问题描述】:

我正在关注this 扩展和折叠我的表格视图部分的教程。由于这个演示是在 swift 2.2 中完成的,我已经根据 swift 3.0 进行了所有更改。我在 if condition(currentSectionCells[row]["isVisible"]) 处被困在下面的函数中,这给了我“类型'NSFastEnumerationIterator.Element'(又名'Any'没有下标成员)'”的错误。

func getIndicesOfVisibleRows() {
    visibleRowsPerSection.removeAll()

    for currentSectionCells in cellDescriptors {
        var visibleRows = [Int]()

        for row in 0...((currentSectionCells as! [[String: AnyObject]]).count - 1) {
            if currentSectionCells[row]["isVisible"] as! Bool == true {
                visibleRows.append(row)
            }
        }

        visibleRowsPerSection.append(visibleRows)
    }
}

我尝试过如下类型转换

    func getIndicesOfVisibleRows() {
    visibleRowsPerSection.removeAll()

    for currentSectionCells in cellDescriptors {
        var visibleRows = [Int]()

        for row in 0...((((currentSectionCells) as? NSMutableArray)?.count)! - 1) {

            let temp = [currentSectionCells][row] as? NSMutableDictionary
            let temp2 = temp?["isVisible"] as! Bool

            if temp2  == true {
                visibleRows.append(row)
            }
        }

        visibleRowsPerSection.append(visibleRows)
    }
}

但这让我在运行时在“let temp2 = temp?["isVisible"] as!Bool”这一行上崩溃 崩溃显示“EXC_BAD_INSTRUCTION”并且临时显示为 nil。

请帮助大家。 TIA

表视图委托和数据源

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    if cellDescriptors != nil {
        return cellDescriptors.count
    }
    else {
        return 0
    }
}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return visibleRowsPerSection[section].count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath: indexPath as NSIndexPath)
    let cell = tableView.dequeueReusableCell(withIdentifier: currentCellDescriptor["cellIdentifier"] as! String, for: indexPath) as! CustomCell

    if currentCellDescriptor["cellIdentifier"] as! String == "sectionCellIdentifier" {
        if let primaryTitle = currentCellDescriptor["secondaryTitle"]
        {
            cell.sectionTitleLabel.text = primaryTitle as? String
        }
    }
    else if currentCellDescriptor["cellIdentifier"] as! String == "shortAnswerCell" {
        cell.questionTitle.text = currentCellDescriptor["primaryTitle"] as? String
        cell.questionTextView.text = currentCellDescriptor["secondaryTitle"] as? String
        cell.answerTextView.text =  currentCellDescriptor["answerTitle"] as? String

    }

    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]

    let temp = cellDescriptors[indexPath.section] as? NSArray
            let temp2 = temp?[indexOfTappedRow ] as? NSDictionary
            let temp3 = temp2?["isExpandable"] as! Bool

    if temp3 == true {
        var shouldExpandAndShowSubRows = false
        if temp3 == false {
            // In this case the cell should expand.
            shouldExpandAndShowSubRows = true
        }

        temp2?.setValue(shouldExpandAndShowSubRows, forKey: "isExpanded")

        for i in (indexOfTappedRow + 1)...(indexOfTappedRow + (temp2?["additionalRows"] as! Int)) {
            (temp![i] as AnyObject).setValue(shouldExpandAndShowSubRows, forKey: "isVisible")
        }
    }
    getIndicesOfVisibleRows()
    tblExpandable.reloadSections(NSIndexSet(index: indexPath.section) as IndexSet, with: UITableViewRowAnimation.fade)
}

【问题讨论】:

    标签: ios xcode uitableview swift3 swift2


    【解决方案1】:

    我也参与了该教程,并在 swift3 中成功完成。您的解决方案在下面给出相应修改。

        class yourClass: UIViewController
    {
    
    
          @IBOutlet weak var profileTableView: UITableView!
        internal var visibleRowsPerSection = [[Int]]()
        internal var cellDescriptors: NSMutableArray!
            // VIEW DID LOAD
        override func viewDidLoad() {
            super.viewDidLoad()
            profileTableView.showsVerticalScrollIndicator = false
            loadProfileControllerData()
            profileTableSetUp()
        // Do any additional setup after loading the view.
        }
    
        func loadProfileControllerData(){
            if let path = Bundle.main.path(forResource: "CellDescriptor", ofType: "plist") {
                cellDescriptors = NSMutableArray(contentsOfFile: path)
            }
            getIndicesOfVisibleRows()
            profileTableView.reloadData()
        }
        // SHOW PARENT VISIBLE ROWS AND SAVE THERE ROW INDEX IN ARRAY
        func getIndicesOfVisibleRows() {
            visibleRowsPerSection.removeAll()
            for currentSectionCells in cellDescriptors.objectEnumerator().allObjects as! [[[String:Any]]]{
                var visibleRows = [Int]()
                for row in 0..<currentSectionCells.count {
                    if currentSectionCells[row]["isVisible"] as! Bool == true {
                        visibleRows.append(row)
                    }
                }
                visibleRowsPerSection.append(visibleRows)
                print(visibleRowsPerSection)
            }
    
        }
        // GET REQUIRED OBJECT OF TYPE [String: Any]
        func getCellDescriptorForIndexPath(indexPath: NSIndexPath) -> [String: Any] {
            let indexOfVisibleRow = visibleRowsPerSection[indexPath.section][indexPath.row]
            let cellDescriptorss = cellDescriptors[indexPath.section] as! NSArray
            let data = cellDescriptorss.object(at: indexOfVisibleRow) as! [String:Any]
            return data
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    }
    
    //----------------------
    
    
    // EXTENSION TO OUR PROFILE CLASS THAT DETERMINE OUR CLASS CONFIRM 2 IMPORTANT DELEGATES
    extension profileViewController : UITableViewDelegate,UITableViewDataSource{
        //MARK-: TABLE VIEW DELEGATE FUNCTIONS
    
        // RETURN NUMBER OF  SECTION IN TABLE VIEW
        public func numberOfSections(in tableView: UITableView) -> Int{
            if cellDescriptors.count != 0{
                return cellDescriptors.count
            }
            else{
                return 0
            }
    
        }
    
        // RETURN NUMBER OF ROWS IN EACH SECTION OF TABLE VIEWS
        public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
            return visibleRowsPerSection[section].count
        }
    
        /* Return object of UITableViewCell that contains table SECTON data and USER profile data */
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
            let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath: indexPath as NSIndexPath)
            let menuCell = tableView.dequeueReusableCell(withIdentifier: currentCellDescriptor["cellIdentifier"] as! String, for: indexPath) as! yourCellClass
    
            if currentCellDescriptor["cellIdentifier"] as! String == "parent"{
    
            }
            else if currentCellDescriptor["cellIdentifier"] as! String == "child"{
                menuCell.backgroundColor = UIColor.clear
    
            }
    
                   return menuCell
        }
    
        public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
    
            let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]
            let cellDescriptorss = cellDescriptors[indexPath.section] as! NSArray
            var data = cellDescriptorss.object(at: indexOfTappedRow) as! [String:Any]
    
            if data["isExpandable"] as! Bool == true{
                var shouldExpandAndShowSubRows = false
                if data["isExpanded"] as! Bool == true{
                    shouldExpandAndShowSubRows = false
                    (cellDescriptorss[indexOfTappedRow] as AnyObject).setValue(shouldExpandAndShowSubRows, forKey: "isExpanded")
                }
    
    
                for i in (indexOfTappedRow + 1)...(indexOfTappedRow + (data["additionalRows"] as! Int)) {
                    (cellDescriptorss[i] as AnyObject).setValue(shouldExpandAndShowSubRows, forKey: "isVisible")
    
                }
            }
            getIndicesOfVisibleRows()
    
            self.profileTableView.reloadSections(NSIndexSet(index: indexPath.section) as IndexSet, with: UITableViewRowAnimation.fade)
    
        }
    

    【讨论】:

    • 非常感谢 Tushar 的工作:)。我还有一个问题。我没有得到适当的部分。只显示第一个,甚至没有展开。
    • @iDeveloper 部分似乎是橡木,应该是可见的。
    • 不,伙计,它还没有工作。它在 for 循环中崩溃了。不知道为什么它不工作,也没有返回正确的部分,我有 2 个部分,而它只显示一个。
    • @iDeveloper 问题出在方法 numberOfSections(in:) 的 Swift 3 签名已更改,请检查我的 stackoverflow.com/a/42664434/6433023 的此答案以获得正确的节数
    • @iDeveloper 提供您完成所需的详细信息检查并确保一切正常。
    【解决方案2】:

    感谢您帮助我,即使在您的帮助下,我也被困在部分没有扩展的地方,所以只是对语法进行了一些更改,因为 Swift 3.0 对类型转换非常具体,因此 didSelectRowAt 不是' t 正常工作。这是完整的 didSelectRowAt 方法。编码愉快。

    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
    
        let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]
        if (cellDescriptors[indexPath.section] as! [[String: AnyObject]])[indexOfTappedRow] ["isExpandable"] as! Bool == true {
            var shouldExpandAndShowSubRows = false
            if (cellDescriptors[indexPath.section] as! [[String: AnyObject]])[indexOfTappedRow]["isExpanded"] as! Bool == false {
                // In this case the cell should expand.
                shouldExpandAndShowSubRows = true
            }
    
            ((cellDescriptors[indexPath.section] as! NSMutableArray)[indexOfTappedRow] as AnyObject).setValue(shouldExpandAndShowSubRows, forKey: "isExpanded")
    
            for i in (indexOfTappedRow + 1)...(indexOfTappedRow + ((cellDescriptors[indexPath.section]  as! [[String: AnyObject]])[indexOfTappedRow]["additionalRows"] as! Int)) {
                ((cellDescriptors[indexPath.section]  as! NSMutableArray)[i] as AnyObject).setValue(shouldExpandAndShowSubRows, forKey: "isVisible")
            }
    
        }
    

    【讨论】:

      【解决方案3】:

      Swift 3/4 不使用基于教程的 NSMutable 数组以及封装在模型中的所有代码。

      class CellsDescriptorModel {
      private var cellDescriptors: [[[String:Any]]]!
      private var visibleRowsPerSection : [[Int]]
      
      var CellDescriptors : [[[String:Any]]] { get { return cellDescriptors }}
      var VisibleRowsPerSection : [[Int]] { get { return visibleRowsPerSection }}
      
      init(plist:String) {
          visibleRowsPerSection = [[Int]]()
      
          if let url = Bundle.main.url(forResource:plist, withExtension: "plist") {
              do {
                  let data = try Data(contentsOf:url)
                  cellDescriptors = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as! [[[String:Any]]]
              } catch {
                  print(error)
              }
          }
          getIndicesOfVisibleRows()
      }
      
      func getCellDescriptorForIndexPath(indexPath: IndexPath) -> [String: Any] {
          let indexOfVisibleRow = visibleRowsPerSection[indexPath.section][indexPath.row]
          return cellDescriptors[indexPath.section][indexOfVisibleRow]
      }
      
      func expandCell(indexPath:IndexPath) {
          let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]
          if cellDescriptors[indexPath.section][indexOfTappedRow] ["isExpandable"] as! Bool == true {
              var shouldExpandAndShowSubRows = false
              if cellDescriptors[indexPath.section][indexOfTappedRow]["isExpanded"] as! Bool == false {
                  shouldExpandAndShowSubRows = true
              }
      
              cellDescriptors[indexPath.section][indexOfTappedRow]["isExpanded"] = shouldExpandAndShowSubRows
      
              for i in (indexOfTappedRow + 1)...(indexOfTappedRow + (cellDescriptors[indexPath.section][indexOfTappedRow]["additionalRows"] as! Int)) {
                  cellDescriptors[indexPath.section][i]["isVisible"] = shouldExpandAndShowSubRows
              }
          }
          else {
                 if cellDescriptors[indexPath.section][indexOfTappedRow]["cellIdentifier"] as! String == "DataPickerTableViewCell" {
                  var indexOfParentCell: Int!
      
                  for index in (0..<indexOfTappedRow).reversed() {
                      if cellDescriptors[indexPath.section][index]["isExpandable"] as! Bool == true {
                          indexOfParentCell = index
                          break
                      }
                  }
      
                  cellDescriptors[indexPath.section][indexOfParentCell]["secondaryTitle"] = ""
                  cellDescriptors[indexPath.section][indexOfParentCell]["isExpanded"] = false
      
                  for i in (indexOfParentCell + 1)...(indexOfParentCell + (cellDescriptors[indexPath.section][indexOfParentCell]["additionalRows"] as! Int)) {
                      cellDescriptors[indexPath.section][i]["isVisible"] = false
                  }
              }
          }
      
          getIndicesOfVisibleRows()
      }
      
      private func getIndicesOfVisibleRows() {
          visibleRowsPerSection.removeAll()
          for currentSectionCells in cellDescriptors {
              var visibleRows = [Int]()
              for row in 0..<currentSectionCells.count {
                  if currentSectionCells[row]["isVisible"] as! Bool == true {
                      visibleRows.append(row)
                  }
              }
              visibleRowsPerSection.append(visibleRows)
          }
      }
      

      }

      【讨论】:

        猜你喜欢
        • 2021-06-06
        • 2016-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-01
        • 2016-06-30
        • 1970-01-01
        相关资源
        最近更新 更多