如何在Swift中设置委托

时间:2018-12-09 12:28:37

标签: ios swift delegates

我想将带有所有用户信息的UserModel从ViewController(ShowUserViewController)发送到具有ViewController的另一个ChatViewControllerdelegate),但是它不起作用。

我的ShowUserViewControllers user中是我想发送到ChatViewController的所有信息。

var user: UserModel?

在我的ChatViewController中,我有以下声明要在其中发送数据:

var currentUser: UserModel?

这是我的协议:

    protocol UserInfoToChatID {
    func observeUserID(user: UserModel)
}

在这里,我准备进行搜索并通过点击按钮设置delegate

} else if segue.identifier == "UserInfoToChatVC" {
        let chatVC = segue.destination as! ChatViewController
        chatVC.currentUser = self.user
    }
}

var delegate: UserInfoToChatID?

@IBAction func chatButtonTapped(_ sender: UIBarButtonItem) {
    delegate?.observeUserID(user: user!)
}

最后,我在delegate中呼叫ChatViewController

    extension ChatViewController: UserInfoToChatID {

    func observeUserID(user: UserModel) {
        self.currentUser = user
        performSegue(withIdentifier: "UserInfoToChatVC", sender: self)
    }
}

3 个答案:

答案 0 :(得分:2)

如果您需要将数据从一个ViewController传递到另一个ViewController,则不必为此使用委托。您可以将此数据作为performSegue方法的发送者参数进行传递:

performSegue(withIdentifier: "UserInfoToChatVC", sender: user!)

然后准备将即将发送的发送者隔离为UserModel并分配目标的currentUser变量

    ...
    } else if segue.identifier == "UserInfoToChatVC" {
        let chatVC = segue.destination as! ChatViewController
        chatVC.currentUser = sender as! UserModel
    }
}

但是在您的情况下,您实际上不必通过user作为发件人。您只需将目标的currentUser变量分配为ShowUserViewController的全局变量user

    ...
    } else if segue.identifier == "UserInfoToChatVC" {
        let chatVC = segue.destination as! ChatViewController
        chatVC.currentUser = user!
    }
}

答案 1 :(得分:2)

2件事: 首先,如果您只想将数据从一个viewController传递到另一个viewController,则不需要使用委托模式,只需在prepare表单segue上将对象传递给下一个viewController。

第二,如果要实现委托模式,则应该有一个viewController而不是调用委托,而另一个要实现函数。

示例:

protocol ExampleDelegate: class {
   func delegateFunction() 
}


class A {
   //have delegate var
   weak var delegate: ExampleDelegate?

   // someWhere in the code when needed call to the delegate function... 
   delegate?.delegateFunction()
}

Class B: ExampleDelegate {
   func delegateFunction() {
      // do some code....
   }

   //when you move to the next viewControoler(to A in that case)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "AClass" {
        if let vc = segue.destination as? A {
            vc.delegate = self
        }
    }
}

答案 2 :(得分:1)

要将UserModel对象从ShowUserViewController传递到ChatViewController,应使用名为Dependency Injection的东西:

因此,您将在ShowUserViewController内执行以下操作:

@IBAction func chatButtonTapped(_ sender: UIBarButtonItem) {
    performSegue(withIdentifier: "UserInfoToChatVC", sender: nil)
}

注意:sender参数应该是发起segue的对象。它可能是自我的,即ShowUserViewController对象,但是我建议不要传递UserModel对象,因为该对象不会启动Segue,并且与导航完全无关。稍后应将其注入Destination Controller内。

在同一文件中,覆盖prepare(for:)方法:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "UserInfoToChatVC" {
        let chatVC = segue.destination as! ChatViewController
        chatVC.currentUser = self.user
    }
}

我相信您大部分情况下都做对了,但是您可能需要从ChatViewController回到ShowUserViewController

在这种情况下,您可以并且应该使用Delegation

ShowUserViewController内创建类似的内容:

protocol ChatViewControllerDelegate: class {
    func didUpdateUser(_ model: UserModel)
}

class ChatViewController: UIViewControler {

    var user: UserModel?

    weak var delegate: ChatViewControllerDelegate?
    /* more code */

    func someEventHappened() {
        delegate?.didUpdateUser(self.user!)
    }
}

最后,在prepare(for:)方法中还添加了一行:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "UserInfoToChatVC" {
        let chatVC = segue.destination as! ChatViewController
        chatVC.currentUser = self.user
        // Add this line...
        chatVC.delegate = self
    }
}

并指定ShowUserViewController实现ChatViewControllerDelegate协议,然后覆盖didUpdateUser(_:)方法:

func didUpdateUser(_ model: UserModel) {
    // Some code here
}