Swift - 如何从 UIActionSheet 更新自定义单元格标签

Swift - How to update custom cell label from UIActionSheet

我有一个带有标题标签的自定义 collection 视图单元格子类。我想将单元格的标题标签更改为操作 sheet 中所选操作的标题。我尝试在处理程序中执行此操作,但无法通过处理程序访问单元格标签。

这是操作的代码sheet

func dailyInjuryIllnessActionSheet() {
        let alert = UIAlertController(title: "Title", message: "Select an Option", preferredStyle: .actionSheet)
        //alert.addAction(UIAlertAction(title: "Available for Full Participation", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: "Available for Full Participation", style: .default, handler: { (action) in
            /// Change the cell text - Get the `UILabel`, and replace the text with `action.title`
            

        }))
        alert.addAction(UIAlertAction(title: "Available for Limited Participation", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: "Not Available For Participation", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: "Close Injury / Illness", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: "Cancel", style: .destructive, handler: nil))
        present(alert, animated: true, completion: nil)
    }

这里是单元格的代码:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: DIISDetailCell.reuseIdentifier, for: indexPath) as? DIISDetailCell else { return UICollectionViewCell() }
        if let entries = player?.entries {
            for entry in entries {
                cell.eventName.text = entry.injuryIllnessName
                cell.eventDate.text = entry.statusDate.formatted()
                cell.eventType.text = entry.status
                cell.modifiedBy.text = entry.modifiedBy ?? "Modified By Goes Here"
                
            }
        }
        return cell
    }

我整个星期都在坚持这个。

我在哪里调用代码:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        dailyInjuryIllnessActionSheet()
    }

一旦用户从警报中做出选择,您需要更新模型数据(以及随后的单元格标签)。警报选择异步。您可以使用几种常见的方法。一是代表团。另一种是传递完成处理程序闭包。第二个更 Swifty 并且是我将要使用的。

首先,您的 cellForItemAt 中有一个错误 - 每个单元格都会被调用,因此您不应该有一个 for 循环 - 您需要根据以下条件访问所需的元素IndexPath.item。这是一个您通常会使用强制向下转型和强制展开的功能,因为单元格 class 需要注册并且您的 numberOfItems 函数应该 return 0 如果您没有条目(或者没有 player) -

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: DIISDetailCell.reuseIdentifier, for: indexPath) as! DIISDetailCell
    let entry = player!.entries[indexPath.item]
    cell.eventName.text = entry.injuryIllnessName
    cell.eventDate.text = entry.statusDate.formatted()
    cell.eventType.text = entry.status
    cell.modifiedBy.text = entry.modifiedBy ?? "Modified By Goes Here"
               
    return cell
}

您可以通过为选项使用数组来稍微简化 dailyInjuryIllnessActionSheet 代码。为了简单起见,我在函数中声明了数组,但它可能应该是从其他信息源传入的。

向此函数添加一个 completion 处理程序参数以将选定的选项传递回调用方:

func dailyInjuryIllnessActionSheet(completion:((String?)->Void)?=nil) {
    
    let options = ["Available for Full Participation",
                   "Available for Limited Participation",
                   "Not Available For Participation",
                   "Close Injury / Illness"
    ]
    let alert = UIAlertController(title: "Title", message: "Select an Option", preferredStyle: .actionSheet)
    
    for option in options {
        alert.addAction(UIAlertAction(title: option, style: .default, handler: { action in 
            completion?(option)
        }))
    }
    alert.addAction(UIAlertAction(title: "Cancel", style: .destructive, handler: { action in
        completion?(nil)
    }))
    present(alert, animated: true, completion: nil)
}

现在您可以在调用 dailyInjuryIllnessActionSheet 更新模型并重新加载项目时传递完成处理程序:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    dailyInjuryIllnessActionSheet() { selectedOption in {
        guard let selectedOption = selectedOption else {
            return
        }
        player!.entries[indexPath.item].status = selectedOption
        collectionView.reloadItems(at:[indexPath])
    }
  
}