【问题标题】:Swift delegate and protocol method not calling in iOSSwift 委托和协议方法不在 iOS 中调用
【发布时间】:2018-10-07 13:42:55
【问题描述】:

我已经使用 MVC 模式解析了UITableView 中的JSON 值,为此,我还创建了一个单独的UITableView swift 类、Model 类和UIViewController 类。

我可以将 JSON 值解析到表格视图中。但问题是我无法使用委托方法将选定的 tableView 单元格值传递给我的控制器

这是我的代码

UIVIewController:

class ViewController: UIViewController,contactSelectionDelegate {
var contactArray = [Address]()
@IBOutlet weak var userTable: UserTable!
let user = UserTable()


override func viewDidLoad() {
    super.viewDidLoad()

    user.userdelegate? = self
    if Connectivity.isConnectedToInternet() {
        print("Yes! Network connection is available")
        APIManager.sharedInstance.fetchUserDetails(urlString: FETCH_USER_DETAIL_URL, userCount: ["offset":1]) { connectionResult in

            switch connectionResult {
            case .success(let data):
                do {
                    self.contactArray = try JSONDecoder().decode([Address].self, from: data)

                    print(self.contactArray.count)
                    print(self.contactArray[0].Name)

                    DispatchQueue.main.async {
                        print(self.contactArray)
                        self.userTable.dataSourceArray=self.contactArray
                        self.userTable.reloadData()
                    }
                }
                catch let errorValue {
                    print(errorValue)
                }
            case .failure(let error):
                print(error)
            }
        }
    }
    else{
        print("No network connection")
    }
}

func selectedUserContact(name: String, email: String, phone: String) {
    print("Delegate Called")
    let userdetailVC = storyboard?.instantiateViewController(withIdentifier: "UserContactDetailPage") as! UserContactDetailPage
    userdetailVC.name = name
    userdetailVC.email = email
    userdetailVC.phone = phone
    self.navigationController?.pushViewController(userdetailVC, animated: true)
} }

UITableView:

protocol contactSelectionDelegate: class{
func selectedUserContact(name: String ,email: String ,phone: String)
}

class UserTable: UITableView ,UITableViewDelegate ,UITableViewDataSource  {


var dataSourceArray  =   [Address]()
weak var userdelegate: contactSelectionDelegate?

override init(frame: CGRect, style: UITableViewStyle) {
    super.init(frame: frame, style: style)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func awakeFromNib() {
    super.awakeFromNib()
    self.delegate=self
    self.dataSource=self
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1;
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.dataSourceArray.count
}

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

    let cell:UserCell   =   tableView.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath) as! UserCell
    if self.dataSourceArray.count>0 {
        let myUser  =   self.dataSourceArray[indexPath.row]
        cell.nameLbl.text  =   myUser.Name
        cell.emailLbl.text  =   myUser.Email
        cell.phoneLbl.text =   myUser.Phone
    }
    return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 200
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let myUser  =   self.dataSourceArray[indexPath.row]
    print(myUser.Name)
    print(myUser.Email)
    print(myUser.Phone)
     userdelegate?.selectedUserContact(name: myUser.Name, email: myUser.Email, phone: myUser.Phone)
}}

在这里,当我单击 tableView 单元格上的表格时,didSelectRowAtIndexPath 方法被调用但 selectedUserContact 未被调用。

【问题讨论】:

    标签: ios swift uitableview model-view-controller


    【解决方案1】:

    根据这一行,您在情节提要中有一个表格视图,并在视图控制器中取得了出口。

    @IBOutlet weak var userTable: UserTable!
    

    所以你不需要这样做:

    let user = UserTable()
    

    你必须像这样给委托:

    userTable.userdelegate? = self
    

    【讨论】:

    • 感谢您的回复。我试过了,就像你说它不起作用
    【解决方案2】:

    对于我来说,它适用于以下场景。请检查那个。

    用户表

    @objc protocol contactSelectionDelegate: class {
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    }
    
    weak var userdelegate: contactSelectionDelegate?
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            delegate?.tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    }
    

    视图控制器

    class ViewController: UIViewController {
    
    }
    
    extension ViewController: contactSelectionDelegate {
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // YOU CAN GET THE ALL THE STUFFS WHICH IS USER SELECTED IN THE TABLE VIEW
        }
    }
    

    【讨论】:

    • 在这一行委托中出现错误?.tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    【解决方案3】:

    看起来您正在从情节提要中实例化表格视图,因此您没有在正确的 UserTable 实例上设置委托(并且委托方法永远不会被调用,因为委托为 nil)。

    在视图控制器中改变

    user.userdelegate? = self
    

    到

    userTable.userdelegate? = self
    

    【讨论】:

    • 我喜欢这个,但没有运气
    【解决方案4】:

    您误解了在这里委派的目的。这个想法是你的表格视图只负责绘制一个表格,它不应该负责维护它显示的任何数据。这使您可以使用模型-视图-控制器 (MVC) 范例清晰地设计您的代码。委托允许您的控制器将模型信息传递给视图,而不会破坏 MVC。

    在您的示例中:Address 是模型,表视图是视图,您的视图控制器是控制器。因此,您希望您的控制器符合表格视图的委托/数据源协议,以便它可以正确地将数据提供给它。

    class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
        var contactArray = [Address]()
        @IBOutlet weak var userTable: UserTable!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            if Connectivity.isConnectedToInternet() {
                print("Yes! Network connection is available")
                APIManager.sharedInstance.fetchUserDetails(urlString: FETCH_USER_DETAIL_URL, userCount: ["offset":1]) { connectionResult in
    
                    switch connectionResult {
                    case .success(let data):
                        do {
                            self.contactArray = try JSONDecoder().decode([Address].self, from: data)
    
                            print(self.contactArray.count)
                            print(self.contactArray[0].Name)
    
                            DispatchQueue.main.async {
                                print(self.contactArray)
                                self.userTable.reloadData()
                            }
                        }
                        catch let errorValue {
                            print(errorValue)
                        }
                    case .failure(let error):
                        print(error)
                    }
                }
            }
            else{
                print("No network connection")
            }
        }
    
        // MARK: - UITableViewDataSource
    
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1;
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.contactArray.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell: UserCell = tableView.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath) as! UserCell
            let myUser = self.contactArray[indexPath.row]
            cell.nameLbl.text = myUser.Name
            cell.emailLbl.text = myUser.Email
            cell.phoneLbl.text = myUser.Phone
            return cell
        }
    
        // MARK: - UITableViewDelegate
    
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return 200
        }
    
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            let myUser = self.contactArray[indexPath.row]
            print(myUser.Name)
            print(myUser.Email)
            print(myUser.Phone)
            selectedUserContact(name: myUser.Name, email: myUser.Email, phone: myUser.Phone)
        }
    
        // MARK: -
    
        func selectedUserContact(name: String, email: String, phone: String) {
            print("Delegate Called")
            let userdetailVC = storyboard?.instantiateViewController(withIdentifier: "UserContactDetailPage") as! UserContactDetailPage
            userdetailVC.name = name
            userdetailVC.email = email
            userdetailVC.phone = phone
            self.navigationController?.pushViewController(userdetailVC, animated: true)
        }
    }
    

    编辑:我只想补充一点,您需要确保在情节提要中将ViewController 设置为表格视图的delegate 和dataSource。然后您可以删除您在UserTable 类中编写的所有代码。如果你根本不需要它,你的表格视图可以是一个简单的UITableView。我几乎从不创建它的子类,因为您通常可以通过委托和UITableViewCell 子类完成所有操作。

    【讨论】:

    • 非常感谢您的回复,是否可以使用委托协议在视图之间将值传递给控制器​​?
    • 当然,如果你愿意的话。
    • 这就是我试图将选择值传递给我的视图控制器的原因
    • 您的解决方案绝对正确,它会起作用。但我试过这种方式我不知道它是否正确?
    • 检查您在情节提要中连接了表格视图的delegate 和dataSource 属性。如果是这样,在ViewController 的viewDidLoad 函数中,您应该能够检查userTable.delegate == self。 userTable.dataSource 也一样。
    猜你喜欢
    • 1970-01-01
    • 2021-03-14
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多