使用两种类型的单元格实现MVVC以向下钻取UITableview

时间:2017-12-20 11:15:46

标签: ios swift uitableview mvvm model

我有一个tableview,它有两种类型的单元格。一个与图像和其他通常只有文本。当用户选中其中一行时,tableview向下钻取并打开一个新的tableview(就像iOS上的设置一样)。我有以下数据模型,但它只适用于一页。如何使用MVVC实现嵌套的。我搜索了很多MVVC教程,但无法弄清楚我的情况。我的意思是例如一行称为“文档”,当我选择文档时,我想列出所有文档,如“First Doc”,“Second Doc”等,这个过程对所有行都是相同的。

Model Picture

protocol SameCell{
    var type: CellType { get }
}
struct LeftMenuSimpleCellData: SameCell{
    let cellText: String
    let haveIndicator: Bool
    let sub: subTable?
    let type: CellType
}
struct LeftMenuCarCellData: SameCell{
    let carImage: String
    let plateText: String
    let modelText: String
    let haveIndicator: Bool
    let sub: subTable?
    let type: CellType

}
struct subTable{
    let cellText: String
    let haveIndicator: Bool
}
enum CellType{
    case LeftMenuSimpleCellData
    case LeftMenuCarCellData
}
class LeftMenuDataModel{

    var optionsData: [SameCell] = []

    let carData: [LeftMenuCarCellData] =  []

    init(){

    }

func populateOptionsData(){
   optionsData.append(LeftMenuCarCellData(carImage: "icon", plateText: "Car", modelText: "Model Name", haveIndicator: true,sub: nil, type: .LeftMenuCarCellData))
    optionsData.append(LeftMenuSimpleCellData(cellText: "Hello", haveIndicator: false, sub: nil,type: .LeftMenuSimpleCellData))
    optionsData.append(LeftMenuSimpleCellData(cellText: "Hello", haveIndicator: true, sub: nil,type: .LeftMenuSimpleCellData))
    optionsData.append(LeftMenuSimpleCellData(cellText: "Hello", haveIndicator: true, sub: nil,type: .LeftMenuSimpleCellData))
    optionsData.append(LeftMenuSimpleCellData(cellText: "HEllo", haveIndicator: true, sub: nil,type: .LeftMenuSimpleCellData))
    optionsData.append(LeftMenuSimpleCellData(cellText: "Hello", haveIndicator: true, sub: nil,type: .LeftMenuSimpleCellData))
    optionsData.append(LeftMenuSimpleCellData(cellText: "Hello", haveIndicator: true, sub: nil,type: .LeftMenuSimpleCellData))
    optionsData.append(LeftMenuSimpleCellData(cellText: "Hello", haveIndicator: false, sub: nil,type: .LeftMenuSimpleCellData))
    optionsData.append(LeftMenuSimpleCellData(cellText: "Exit", haveIndicator: false, sub: nil,type: .LeftMenuSimpleCellData))
}

编辑:当我搜索时,“Key:Value”数组可以正常工作。但是在代码下方,“LeftMenuSimpleCellData”不符合协议“Hashable”错误。

var optionsData: [LeftMenuSimpleCellData: [LeftMenuSimpleCellData] ]?

编辑2:我可以将结构改为递归吗?

struct LeftMenuSimpleCellData{
let cellText: String
let haveIndicator: Bool
let subMenu: LeftMenuSimpleCellData
}

编辑3:我编辑了我的代码。它现在特别有效。但我还没有实现第二个子菜单。

1 个答案:

答案 0 :(得分:0)

所以根据你的问题和你的意见,这是我最后修改的答案,我创建了一个虚拟的ViewModel结构。请参考此参考并尝试制作您自己的ViewModel。 所以我们走了......

    class LeftMenuSimpleCellData{
    let cellText: String
    let haveIndicator: Bool
    var nextVM : ViewModel?
    init(_ text : String , indicator : Bool = true ) {
        self.cellText = text
        self.haveIndicator = indicator

    }
}
class ViewModel : NSObject
{


    private override init() {
    }
    init(data : [LeftMenuSimpleCellData])
    {

        self.cellData = data
    }
    private var cellData = [LeftMenuSimpleCellData]()

    var count : Int {return cellData.count}



    func cellData(at index : Int) -> LeftMenuSimpleCellData {
        return cellData[index]
    }

}

现在获得RootNode ViewModel,我已经写了这个函数

func getVM(for detail : [[String : Any]]) -> ViewModel {
        let leftCellMenu = detail.map {[weak self] (det) -> LeftMenuSimpleCellData in

            let leftCellData = LeftMenuSimpleCellData.init(det["name"] as! String)
            if let arr = det["Sub Menu"] as? [[String : Any]] , !arr.isEmpty {
                leftCellData.nextVM = self?.getVM(for: arr)
            }
            else
            {
                leftCellData.nextVM = nil
            }
            return leftCellData
        }

        return ViewModel(data: leftCellMenu)
    }

以下是 detail : [[String : Any]]

的虚假数据
[
  {
    "name" : "Wi Fi",
    "Sub Menu" : [
      {
        "name" : "Wi Fi1",
        "Sub Menu" : [

        ]
      },
      {
        "name" : "Wi Fi2",
        "Sub Menu" : [

        ]
      }
    ]
  },
  {
    "name" : "Blutooth",
    "Sub Menu" : [
      {
        "name" : "Blutooth1",
        "Sub Menu" : [

        ]
      },
      {
        "name" : "Blutooth2",
        "Sub Menu" : [

        ]
      }
    ]
  },
  {
    "name" : "General",
    "Sub Menu" : [
      {
        "name" : "About",
        "Sub Menu" : [
          {
            "name" : "Name",
            "Sub Menu" : [

            ]
          },
          {
            "name" : "Network",
            "Sub Menu" : [

            ]
          }
        ]
      },
      {
        "name" : "Accessibility",
        "Sub Menu" : [
          {
            "name" : "VoiceOver",
            "Sub Menu" : [

            ]
          },
          {
            "name" : "Speech",
            "Sub Menu" : [
              {
                "name" : "Speech Selection",
                "Sub Menu" : [

                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

这将为mainViewController提供rootVM。

现在mainViewController tableView数据源方法

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

        let subMenu = vm.cellData(at: indexPath.row)
        cell.textLabel?.text = subMenu.cellText
        cell.accessoryType = subMenu.nextVM == nil ? .none : .disclosureIndicator
        return cell
    }

对于tableView委托方法

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
     let subMenu = vm.cellData(at: indexPath.row)
        guard subMenu.nextVM != nil else {
            return
        }
        let mainVC = self.storyboard?.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController
        mainVC.vm = subMenu.nextVM!
        navigationController?.pushViewController(mainVC, animated: true)
    }

我希望现在这会帮助你实现你想要的。如果您有任何疑问,请发表评论。