循环中的 AlertController

AlertController in a loop

我有一个功能可以显示最多列出 5 个项目(收藏夹)的警报,以允许用户 select 一个并使用它。我的代码有效,但看起来又长又乱,我试图在循环中简化它,但用户 selected 的项目总是 returns 循环值的结束。我的代码如下。它显示了我试图开始工作的循环逻辑(请注意,警报返回的索引始终是循环结束时 counter 的值(即无论点击哪个元素,useFavourite(5)被调用。我也提供了有效的代码(但对我来说感觉很乱)。有没有更好的方法来实现简单性?

    func showFavouritesAlert() -> Void {
    //either shows a list of favourites or message stating no favourites
    if userData.noFavourites {
        let message = "You have no stored favourites.  You can add to favourites by selecting the \u{2605} button."
        let alertController = UIAlertController(title: "UK Tides", message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default))
        self.present(alertController, animated: true, completion: nil)

    } else { //favourites are present so show them
        let message = "Select one of your Tide Station favourites."
        let alertController = UIAlertController(title: "UK Tides", message: message, preferredStyle: .alert)
        //the loop below shows the correct alert but always executes useFavourites(5)
        var counter = 0
        for entry in userData.currentSelection.favourites {
            alertController.addAction(UIAlertAction(title: entry.name, style: .default, handler: {(action) in
                    self.useFavourite(counter)
            }))
            counter += 1
        }
        //the code below works but feels long winded
        let favourites = userData.currentSelection.favourites
        let favCount = favourites.count
        alertController.addAction(UIAlertAction(title: favourites[0].name, style: .default, handler: {(action) in
                self.useFavourite(0)
            }))
        if favCount > 1 {
            alertController.addAction(UIAlertAction(title: favourites[1].name, style: .default, handler: {(action) in
            self.useFavourite(1)
            }))
        }
        if favCount > 2 {
            alertController.addAction(UIAlertAction(title: favourites[2].name, style: .default, handler: {(action) in
            self.useFavourite(2)
            }))
        }
        if favCount > 3 {
            alertController.addAction(UIAlertAction(title: favourites[3].name, style: .default, handler: {(action) in
            self.useFavourite(3)
            }))
        }
        if favCount > 4 {
            alertController.addAction(UIAlertAction(title: favourites[4].name, style: .default, handler: {(action) in
            self.useFavourite(4)
            }))
        }
        //the code above works


        alertController.addAction(UIAlertAction(title: "Cancel", style: .default))

        self.present(alertController, animated: true, completion: nil)
    }
    return
} 

当然有更好的方法来做到这一点(例如使用 .enumerated() 而不是手动计数器),但要回答您的问题,您的闭包必须捕获 value 而不是捕获 reference(这是局部变量的默认值)。

var counter = 0
for entry in userData.currentSelection.favourites {
    let action = UIAlertAction(title: entry.name, style: .default) { [counter] _ in
        self.useFavourite(counter)
    }
    alertController.addAction(action)
    counter += 1
}

Capture Lists

以及没有局部变量的版本:

for (offset, entry) in userData.currentSelection.favourites.enumerated() {
    let action = UIAlertAction(title: entry.name, style: .default) { _ in
        self.useFavourite(offset)
    }
    alertController.addAction(action)
}