简体   繁体   English

Swift委托和协议方法未在iOS中调用

[英]Swift delegate and protocol method not calling in iOS

I have parsing the JSON values in UITableView using MVC pattern, For that, I have created a separate UITableView swift class, Model class, and UIViewController class as well. 我已经使用MVC模式解析了UITableViewJSON值。为此,我还创建了一个单独的UITableView swift类,Model类和UIViewController类。

I can able to parse the JSON values into the table view. 我可以将JSON值解析为表格视图。 But the problem is I can't able to pass the selected tableView cell values to my controller using the delegate method 但是问题是我无法使用委托方法将选定的tableView单元格值传递给控制器

Here my code is 这是我的代码

UIVIewController : 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 : 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)
}}

Here when I click table on the tableView cell didSelectRowAtIndexPath method called but selectedUserContact not getting called. 在这里,当我在tableView单元格上单击表时,调用了didSelectRowAtIndexPath方法,但未调用selectedUserContact

You've misunderstood the purpose of delegating here. 您误解了在这里委派的目的。 The idea is that your table view is only responsible for drawing a table, it shouldn't be responsible for maintaining any of the data that it's displaying. 这个想法是,您的表格视图仅负责绘制表格,而不应负责维护其显示的任何数据。 This allows you to cleanly design your code using the Model-View-Controller (MVC) paradigm. 这使您可以使用“模型-视图-控制器”(MVC)范例来干净地设计代码。 Delegation allows your controllers to pass model information to the views without breaking MVC. 委派允许您的控制器将模型信息传递给视图而不会破坏MVC。

In your example: Address is the model, the table view is the view, and your view controller is the controller. 在您的示例中: Address是模型,表视图是视图,而视图控制器是控制器。 So you want your controller to conform to the table view's delegate/data source protocols so that it can feed the data to it correctly. 因此,您希望控制器遵守表视图的委托/数据源协议,以便它可以将数据正确地馈送到它。

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)
    }
}

EDIT: I just want to add that you need to make sure in your storyboard that you set ViewController as the delegate and dataSource of the table view. 编辑:我只想补充一点,您需要确保在情节ViewController中将ViewController设置为表视图的delegatedataSource Then you can remove all the code that you've written in the UserTable class. 然后,您可以删除在UserTable类中编写的所有代码。 If anything you don't need it at all and your table view can be a simple UITableView . 如果您根本不需要它,则表视图可以是一个简单的UITableView I almost never create subclasses of it, since you can normally do everything through the delegation and UITableViewCell subclasses. 我几乎从不创建它的子类,因为您通常可以通过委托和UITableViewCell子类来完成所有操作。

According to this line, Your have a table view in the storyboard and taken outlet in viewcontroller. 根据此行,您在情节提要中有一个表格视图,并已在viewcontroller中取出。

@IBOutlet weak var userTable: UserTable!

So you don't need to do this like that: 因此,您不需要这样做:

let user = UserTable()

You have to give delegate like this: 您必须像这样给代表:

userTable.userdelegate? = self

Looks like you're instantiating the table view from a storyboard, so you're not setting the delegate on the correct instance of UserTable (and the delegate method is never called because the delegate is nil). 看起来您是从情节提要中实例化表格视图,因此您没有在UserTable的正确实例上设置委托(并且永远不会调用委托方法,因为委托为nil)。

In the view controller change 在视图控制器中更改

user.userdelegate? = self

to

userTable.userdelegate? = self

For mine it is working fine with the below scenario. 对于我来说,在以下情况下可以正常工作。 Kindly check with that one. 请检查那个。

UserTable 用户表

@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)
}

ViewController ViewController

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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM