【问题标题】:What's the proper way to access a delegate via Swift?通过 Swift 访问委托的正确方法是什么?
【发布时间】:2015-01-09 16:43:20
【问题描述】:

我正在尝试模拟使用 Swift 访问对象委托的 Objective-C 模式。通常我会将协议放在两个 UIViewController 之间共享的 .h 中。

目的:调用委托(主机)来关闭(推送的)UIViewController。
问题:无法访问代理的 hello()。

以下代码可以编译,但出现运行时错误:未知委托方法(见下文)。

主机/调用(委托)对象:

import UIKit

class MainViewController: UIViewController, ProtocolNameDelegate {                     
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    // ---------------------------------------------------------------------------------------------------------------
    // Protocol Delegate

    func hello() {
        println("Hello");
    }

    // ---------------------------------------------------------------------------------------------------------------

    @IBAction func greenAction(sender : AnyObject) { 
        let secondViewController = self.storyboard.instantiateViewControllerWithIdentifier("GreenViewController") as GreenViewController
        secondViewController.delegate = self;
        self.presentViewController(secondViewController, animated: true, completion: nil)
    }

    // ---------------------------------------------------------------------------------------------------------------

    @IBAction func exitAction(sender : AnyObject) {
        exit(0)
    }

要关闭的推送(第二个或“绿色”)UIViewController:

import UIKit

@class_protocol protocol ProtocolNameDelegate {
    func hello()
}

class GreenViewController: UIViewController {
    weak var delegate: ProtocolNameDelegate?

    // ---------------------------------------------------------------------------------------------------------------

    @IBAction func returnAction(sender : UIBarButtonItem) {
        println("Inside returnAction")
        delegate?.hello()
    }  
}

修订: 更正了委托访问:delegate?.hello()... 并重新运行应用程序。以下是通过调试器:

(lldb) po delegate
Some
 {
  Some = {
    payload_data_0 = 0x0d110b90 -> 0x00009a78 (void *)0x00009b70: OBJC_METACLASS_$__TtC9RicSwift218MainViewController
    payload_data_1 = 0x0d110b90 -> 0x00009a78 (void *)0x00009b70: OBJC_METACLASS_$__TtC9RicSwift218MainViewController
    payload_data_2 = 0x00000000
    instance_type = 0x00000000
  }
}
(lldb) po delegate.hello()
error: <REPL>:1:1: error: 'ProtocolNameDelegate?' does not have a member named 'hello'
delegate.hello()

(lldb) po delegate?.hello()
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0xb3145b0).
The process has been returned to the state before expression evaluation.

问题:我错过了什么或做错了什么?

【问题讨论】:

    标签: delegates swift


    【解决方案1】:

    这里的问题是委托是一个可选的。所以要访问它,你应该这样做

    delegate?.hello()
    

    这样你就可以解开可选项,如果它不是 nil 就调用 hello

    ProtocolNameDelegate?是与 ProtocolNameDelegate 不同的类型,特别是 Optional。

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题。有人告诉我这是 Swift 中的一个错误(目前存在于 Xcode 6 beta 5 中)。强协议运行良好,但弱协议还没有。解决方法是使用 @objc protocol ProtocolNameDelegate 而不是普通的 protocol ProtocolNameDelegate 将协议声明为 Objective-C 协议。

      【讨论】:

        【解决方案3】:

        由于委托是可选的,你必须解开它,最快的方法是使用可选链:

        delegate?.hello()
        

        您还需要确保将委托协议标记为 @objc(在这种情况下,而不是 @class_protocol)

        【讨论】:

        • 好的...我注意到缺少的 ();是错字,但这并没有解决原来的问题。但是 delegate?.hello() 确实...但是现在我收到了运行时错误:代理的 EXC_BAD_ACCESS (CODE=2,...) 。 (lldb) po delegate.hello() 错误::1:1: 错误:'ProtocolNameDelegate?'没有名为“hello”的成员 delegate.hello()
        • EXC_BAD_ACCESS 没用,只是说某些事情中止了。当您在 repl 中使用它时,您再次省略了“?”
        • 尝试省略@class_protocol
        • 好的...我删除了@class_protocol;但是编译器抱怨委托的弱变量。所以我删除了“弱”……它奏效了。关注:我不需要处理委托链接吗?我需要“软弱”不是吗?
        • 一般来说你不希望它不弱,因为这会导致引用循环。在这种情况下,这不是问题,因为父母没有保留对孩子的引用。不知道为什么它会失败,但它也适合我。
        猜你喜欢
        • 2015-01-20
        • 2017-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-21
        • 2011-02-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多