无法将struct变量设为可变类型

时间:2019-11-22 23:35:43

标签: ios struct expression immutability swift5

我面临着“无法分配给'布尔'类型的不可变表达式”的问题。请看下面的代码。我在viewForHeaderInSection中遇到错误。实际上,我应该在哪里进行修改以使其正常工作?。

struct VenueDetail {
        var isVeg: Bool
}

struct VenueDetailDTOMapper {

    static func map(_ dto: DetailDataDTO) -> VenueDetail {
     return VenueDetail(isVeg: dto.isVeg)
    }
}

在API管理器中,我从api中获取了数据,并按照以下说明使用上述结构

let venueDetail = VenueDetailDTOMapper.map(getDetail)

ViewModel:

enum VenueDetailVMTypes {
    case veueInfoInfo
}

protocol VenueDetailVMItems {
 var type: VenueDetailVMTypes { get }
}

struct VenueInfoViewModel: VenueDetailVMItems {
        var type: VenueDetailVMTypes {
            return .veueInfoInfo
            }
        var headerSection: VenueDetail
}

func cretaDataSource() {

    if let getVenueDetails = self.venueDetails {
        let vmType = VenueInfoViewModel(headerSection: getVenueDetails)
        arrayDataSource.append(vmType)
    }
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

       let headerView = UIView()

       let venueDetailVMItems = viewModel.arrayDataSource[section]
       switch venueDetailVMItems.type {
       case .veueInfoInfo:
           let headerCell = tableView.dequeueReusableCell(withIdentifier: kCellIdentifierVenueHeader) as! VenueHeaderTVCell
           headerCell.updateCellData(detail: (venueDetailVMItems as! VenueInfoViewModel).headerSection)

           headerCell.foodTypeHandler = { [weak self] (isOn) in
               guard let strongSelf = self else {
                   return
               }                
            strongSelf.viewModel.showOnlyVegMenu(shouldShowVeg: isOn)
            (venueDetailVMItems as! VenueInfoViewModel).headerSection.isVeg = isOn.  //Cannot assign to immutable expression of type 'Bool'
            strongSelf.tableView.reloadData()
           }
           headerView.addSubview(headerCell)
           break
       }
       return headerView
}

3 个答案:

答案 0 :(得分:1)

结构是字段的集合;如果特定结构实例是可变的,则其字段将是可变的;如果实例是不可变的,则其字段将是不可变的。因此,必须准备一种结构类型,以使任何特定实例的字段都是可变或不变的。

请检查this

因此,请尝试将 let 更改为 var

确保arrayDataSource是可变用户 var ,而不是 let

var arrayDataSource = [VenueInfoViewModel]()

答案 1 :(得分:1)

结构是值类型,因此每次分配结构时,它都会创建一个副本。您将其视为参考类型。剥离所有as!的投射,您要做的是:

let value = array[index]
value.someBool = true
reloadData()

即使值是可变的(可能是可变的),也不会做任何事情。 valuearray[index]副本,而不是对其的引用。如果希望将其用作引用,则需要将其设为引用类型(一个类)。

您已经使用了协议和“类型”标识符,我认为您真正想要的是带有关联数据的枚举:

enum VenueDetail {
    case veueInfoInfo(VenueInfoViewModel)
}

有了这个,您就摆脱了所有危险而复杂的as!投射。

但是所有这些并不能真正改变您所描述的问题。无论哪种方式(使用协议或枚举),您都需要做的是:

var value = array[index]
// change value the ways you want; set the bool, etc.
array[index] = value

答案 2 :(得分:-1)

在苦苦挣扎之后,我只是在viewModel中创建了一个方法,该方法删除了类型为.venueInfo的数组中的对象并重新加载,我知道它的种类,但是暂时没有选择。万一有人发现更好的方法,真的很感激

 func changeHeaderSwitch(isVeg: Bool) {

    arrayDataSource.removeAll { (venueDetailVMItems) -> Bool in
        return venueDetailVMItems.type == .veueInfoInfo
    }

    if var getVenueDetails = self.venueDetails {
        getVenueDetails.isVeg = isVeg
        let vmType = VenueInfoViewModel(headerSection: getVenueDetails, arrayMenuInfo: [])
        arrayDataSource.append(vmType)
    }
}