【问题标题】:Calling UIAlertController inside a UITableViewCell在 UITableViewCell 中调用 UIAlertController
【发布时间】:2018-03-09 18:08:19
【问题描述】:

当我的函数被调用时,我试图从我的UITtableViewCell 中调用UIAlertController。它给了我一个错误,说礼物不可用。我知道它不在ViewController 内。我正在寻找一种访问它的方法。

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code

    let tapGestureShareImageView = UITapGestureRecognizer(target: self, action: #selector(self.shareImageTouchUpInside))
    shareImageView.addGestureRecognizer(tapGestureShareImageView)
    shareImageView.isUserInteractionEnabled = true
}

@objc func shareImageTouchUpInside() {
    showAction()
}

func showAction() {
    let alertController = UIAlertController(title: "Action Sheet", message: "What do you like to do", preferredStyle: .alert)

    let okButton = UIAlertAction(title: "Done", style: .default, handler: { (action) -> Void in
        print("Ok button tapped")
    })

    let deleteButton = UIAlertAction(title: "Skip", style: .destructive, handler: { (action) -> Void in
        print("Delete button tapped")
    })

    alertController.addAction(okButton)
    alertController.addAction(deleteButton)

    present(alertController, animated: true, completion: nil)
}

【问题讨论】:

  • 理想情况下,不要从单元格中显示视图控制器。相反,创建一个委托或回调函数并将事件传递给视图控制器并从那里显示警报。

标签: ios swift uitableview uialertcontroller


【解决方案1】:

你可以尝试使用委托

protocol AlertShower{
    func showAlert(TableCustomCell)
}

class TableCustomCell: UITableViewCell {
    var delegate: AlertShower?

    @IBAction func showClicked(_ sender: UIButton) {
        self.delegate?.alertShower(sender:self)
    }
}

在VC中

class viewController: UIViewController, AlertShower {

    override func viewDidLoad() {
        super.viewDidLoad()

    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

         let cell = areaSettTable.dequeueReusableCell(withIdentifier:CellIdentifier1) as! TableCustomCell

         cell.delegate = self

         return cell
    }

    func showAlert(sender:TableCustomCell) {

      // show alert here

    }
}

【讨论】:

  • 1.协议名称(如类名称)应以大写字母开头。 2. 将单元格作为参数传递给委托方法会很有用。然后代理知道哪个节目触发了请求,并可能使用该信息从其数据模型中获取数据。
  • 是的,我将在其中传递 postID ..我只是在访问 UIAlertController 时一片空白
  • 顺便说一下,使用回调,例如var onShare: (() -> Void)? 可能是一个更好的主意,因为它可以更好地组织代码。
  • @Sulthan 您的var onShare: (() -> Void)? 解决方案看起来如何?我想在加载单元格内容失败时显示警报,但我不确定您的意思。
【解决方案2】:

Present 仅适用于 ViewController。您将不得不将触摸事件重定向到您的视图控制器。最常见的方法是在 UITableViewCell 中使用委托属性。

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276

【讨论】:

    【解决方案3】:

    在从子类 UIView 创建自定义活动指示器时,我自己也遇到了类似的问题。我所做的是创建“显示”函数(在子类中)并传入 UIViewController 参数,如下所示:

    public func play(inView view: UIViewController) {
    //Perform action here
    view.present(alertController, animated: true, completion: nil)
    }
    

    像这样在视图控制器中调用它:

    CustomClass.play(inView: self)
    

    希望这会有所帮助!

    【讨论】:

    • 这是一个非常糟糕的解决这个问题的方法。演示是 UIViewController 的职责,而不是子视图的职责。在子视图中将 ViewController 作为参数传递的最大问题是它可能会创建具有内存泄漏的循环依赖关系,这很难调试。委托模式虽然比较麻烦,但对于 iOS 环境来说更加安全和原生(虽然我个人会使用响应式框架)。
    • 嗯..感谢您的信息/见解。我还没有看到任何内存泄漏,但我肯定会重新做我的方法并像建议的那样使用委托模式。谢谢!
    • 一般来说,从责任的角度来思考是好的,即谁对什么负责。 UIViewControllers 负责某些事情,UIViews 负责其他事情等。如果职责重叠,请尝试在您的代码中创建明确定义的限制(就每个类负责的内容而言)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多