代码之家  ›  专栏  ›  技术社区  ›  iamVishal16

改变变量的swift结构不工作?[复制品]

  •  1
  • iamVishal16  · 技术社区  · 6 年前

    这个问题已经有了答案:

    即使使用 mutating func 方法中的关键字?

    所以基本上我用一种非常简单的方式来解决我的问题 Car 有3个变量 id , start modelNo

    之后初始化一个空的汽车模型数组,然后我想显示10辆汽车,创建一个循环范围,循环迭代 1...10 ,初始化汽车模型类并将其附加到原始汽车数组。

    前5辆车的车牌号是0,后5辆车的车牌号是1

    我想要一个过滤器,在这个过滤器中,同一个ID的最后一辆车将启动,所以我创建了一个过滤和修改start变量的方法,但不能修改它。你能帮我一下我做错了什么吗?

    请看我的完整代码并复制粘贴到操场上。

    struct Car {
        var id = 0
        var start = false
        var modelNo: String
    
        init(start: Bool, id: Int, model: String) {
            self.start = start
            self.id = id
            self.modelNo = model
        }
    
        mutating func startCar(status: Bool) {
            start = status
        }
    }
    
    var arrCars:[Car] = [Car]()
    
    for i in 1...10 {
        let md = Car(start: false, id: i <= 5 ? 0 : 1, model: "Model\(i)")
        arrCars.append(md)
    }
    
    private func filtered() {
        for item in arrCars {
            let filteredItems = arrCars.filter { $0.id == item.id }
            if filteredItems.count > 0 {
                if var lastItem = filteredItems.last {
                    print("Will start \(lastItem.modelNo)")
                    lastItem.startCar(status: true)
                }
            }
        }
    
        let cars = arrCars.filter { (car) -> Bool in
            car.start == true
        }
    
        print(cars.count)
    }
    
    filtered()
    

    任何帮助都将不胜感激。

    3 回复  |  直到 6 年前
        1
  •  3
  •   Paulw11    6 年前

    创建一个 mutating 结构上的函数不会更改结构的值语义。一旦结构实例发生变化,就会进行复制。

    你说:

    if var lastItem = filteredItems.last {
        print("Will start \(lastItem.modelNo)")
        lastItem.startCar(status: true)
    }
    

    所以, lastItem 包含要启动的汽车的实例。在封面下面是同一辆车的实例 filteredItems ,与中的实例相同 arrCars . 但是,一旦你变异 Car 在里面 激光扫描 ,复印件,所以 激光扫描 不再具有与中的实例相同的实例 阿尔卡斯 . 过滤项目 阿尔卡斯 仍然包含原始的,未更改的 小型车 实例。

    你可以改变 小型车 成为一个 class 而不是 struct 这样它就有了获取所需行为的引用语义。

    另一种选择是就地修改实例;例如 arrCars[0].startCar(status: true) . 为此,您需要获取一个包含 指示器 你想要启动的汽车,而不是汽车本身:

    private func filtered() {
        for item in arrCars {
            let matchingIndices = arrCars.enumerated().compactMap { (index,car) in
                return car.id == item.id ? index:nil
            }
            if matchingIndices.count > 0 {
                if let lastIndex = matchingIndices.last {
                    print("Will start \(arrCars[lastIndex].modelNo)")
                    arrCars[lastIndex].startCar(status: true)
                }
            }
        }
    
        let cars = arrCars.filter { (car) -> Bool in
            car.start == true
        }
    
        print(cars.count)
    }
    

    但是,如果模型对象需要可变性或有状态性,则结构可能不适合。

        2
  •  1
  •   matt    6 年前

    到目前为止,你得到的答案并不是错的,但它们似乎有点令人困惑。让我们更简单地看一下。问题在于这一行:

    if var lastItem = filteredItems.last
    

    这就产生了一辆汽车 lastItem . 但它是 不一样 车为一体 在里面 这个 filteredItems .

    这是因为结构是 价值阶层 . 转让 副本 结构。因此,你要做什么 激光扫描 对里面的东西没有影响 过滤项目 .

    所以,你是 在转换结构时遇到任何问题。你在变异 激光扫描 很好!问题是 激光扫描 车和车里的东西不一样 过滤项目 .

        3
  •  0
  •   Igor B.    6 年前

    首先试着运行这个代码,如果我们坚持的话,检查它是否解决了问题。 Structure S.然后我会尽力解释为什么这有帮助:

    struct Car {
        var id = 0
        var start = false
        var modelNo: String
    
        init(start: Bool, id: Int, model: String) {
            self.start = start
            self.id = id
            self.modelNo = model
        }
    
        mutating func startCar(status: Bool) {
            start = status
        }
    }
    
    var arrCars: Array<Car> = [Car]()
    
    for i in 1...10 {
        let md = Car(start: false, id: i <= 5 ? 0 : 1, model: "Model\(i)")
        arrCars.append(md)
    }
    
    private func filtered() {
        for item in arrCars {
            let filteredItems = arrCars.filter { $0.id == item.id }
            if filteredItems.count > 0 {
                // solves the problem
                arrCars[filteredItems.count-1].startCar(status: true)
                print("Will start \(arrCars[filteredItems.count-1].modelNo)")
            }
        }
    
        let cars = arrCars.filter { (car) -> Bool in
            car.start == true
        }
    
        print(cars.count)
    }
    
    filtered()