【问题标题】:present UIAlertController from a cell [duplicate]从单元格中呈现 UIAlertController [重复]
【发布时间】:2021-08-17 08:09:51
【问题描述】:

我想通过点击单元格上的菜单按钮来展示 UIAlertController

class FeedViewCell: UITableViewCell {
// some code...

 lazy var menuButton: UIButton = {
        let btn = UIButton()
        btn.addTarget(self, action: #selector(menuTapped), for: .touchUpInside)
        return btn
    }()

@objc func menuTapped() {
        let actionSheet = UIAlertController(title: "", message: "", preferredStyle: .actionSheet)
        
        actionSheet.addAction(UIAlertAction(title: "Dismiss", style: .cancel, handler: { action in
            print("tap dismiss")
        }))
        
        actionSheet.addAction(UIAlertAction(title: "Follow", style: .default, handler: { action in
            print("tap follow")
        }))

     present(actionSheet, animated: true)
    }
}

这是一个 FeedViewController:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellid", for: indexPath) as! FeedViewCell
        return cell
    }

但是我收到错误“在范围内找不到‘存在’”

我不确定如何使用委托和协议来呈现它。请帮帮我

【问题讨论】:

标签: ios swift uitableview protocols uialertcontroller


【解决方案1】:

Ivan 为 UIViewController 寻找响应者链的方法可行,但我建议采用不同的方法。

修改您的 FeedViewCell 类以具有可选的 viewController 属性:

class FeedViewCell: UITableViewCell {
    // Note that the pointer to the view controller should be weak
    // To avoid a retain cycle, as pointed out by Matt.
    weak var viewController: UIViewController? = nil
    // some code...
}

并修改您的 IBAction 方法:

@IBAction func menuTapped() {
        // Make sure `viewController` is not nil.
        guard let viewController = viewController else {
           print("No view controller found. Exiting.")
           return
        }
        let actionSheet = UIAlertController(title: "", message: "", preferredStyle: .actionSheet)
        
        actionSheet.addAction(UIAlertAction(title: "Dismiss", style: .cancel, handler: { action in
            print("tap dismiss")
        }))
        
        actionSheet.addAction(UIAlertAction(title: "Follow", style: .default, handler: { action in
            print("tap follow")
        }))
     // Change your code to send the `present(_:animated:)` message to 
     // the cell's `viewController`.
     viewController.present(actionSheet, animated: true)
    }
}

然后在配置 FeedViewCell 单元格的视图控制器中,设置单元格的 viewController 属性:

func tableView(_ tableView: UITableView, 
  cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   // Replace with the correct reuse identifier
    guard let cell = tableView.dequeueReusableCell(withIdentifier: yourIdentifier) as? FeedViewCell else {
       return UITableViewCell()
    }
    cell.viewController = self // Or, if the data source is not the main view controller for the window, pass in some other view controller.
}

【讨论】:

  • 在此处保留周期?
  • 确实如此。是的,返回视图控制器的指针应该很弱。
【解决方案2】:

你的整个方法都是错误的;负责查看周围的控制器不是单元格的事情。但是,如果您坚持,请使用此实用程序:

extension UIResponder {
    func next<T:UIResponder>(ofType: T.Type) -> T? {
        let r = self.next
        if let r = r as? T ?? r?.next(ofType: T.self) {
            return r
        } else {
            return nil
        }
    }
}

现在

self.next(ofType: FeedViewController.self)?.present...

【讨论】:

    【解决方案3】:

    对于单元格内的当前警报,您应该获取父控制器。警报控制器只能存在于其他父控制器上。

    让我们去做吧。首先,添加扩展名。它允许获取控制器使用哪个视图:

    public extension UIView {
    
        var viewController: UIViewController? {
            weak var parentResponder: UIResponder? = self
            while parentResponder != nil {
                parentResponder = parentResponder!.next
                if let viewController = parentResponder as? UIViewController {
                    return viewController
                }
            }
            return nil
        }
    }
    

    现在您可以在单元格中获取控制器。让我们做吧:

    @objc func menuTapped() {
       // You added alert here, your code
       guard let parentController = self.viewController else { return }
       parentController.present(actionSheet, animated: true)
    }
    

    就是这样。

    【讨论】:

    • 这种方法通常会奏效,但它很脆弱。如果您的视图控制器层次结构中有多个父视图控制器,您的代码可能会选择错误的一个。最好给单元格一个 viewController 属性并让父视图控制器填充它。
    • 我不同意。它并不脆弱。我们知道所需的课程。
    猜你喜欢
    • 2015-01-13
    • 2020-08-25
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多