响应者链但不委托属性将值从容器传递回视图控制器

时间:2015-12-07 16:53:27

标签: ios swift delegates uiresponder

以下代码应显示两种使用Responder Chain OR委托方法将信息从嵌入式控制器(UICollectionView)传递回详细视图控制器的方法。两种方法都使用相同的协议和委托方法。唯一的区别是如果我在didSelectItemAtIndex路径中注释了委托?.method行,则响应者链工作。但是,如果我在didSelectItemAtIndex方法中注释了Responder Chain行,那么这个未知的委托?财产不会调用该方法,并且仍为零。

协议定义并包含在DetailViewController之上。这两种方法都需要。

protocol FeatureImageController: class {
func featureImageSelected(indexPath: NSIndexPath)
}

在自定义UICollectionViewController类中声明的委托属性,仅用于委托方法。

class PhotoCollectionVC: UICollectionViewController
{
   weak var delegate: FeatureImageController?

在DetailViewController中,创建了一个PhotoCollectionVC()实例,并将委托属性设置为self,并将委托协议作为类型。

class DetailViewController: UIViewController, FeatureImageController 
{...
    override func viewDidLoad() {
    super.viewDidLoad()

    let photoCollectionVC = PhotoCollectionVC()
    photoCollectionVC.delegate = self as FeatureImageController

在集合视图控制器的didSelectItemAtIndexPath方法中,通过Responder Chain(已注释掉)或委托给DetailVC中的featureImageSelected方法传回所选的indexPath。

override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
//    if let imageSelector =  targetForAction("featureImageSelected:", withSender: self) as? FeatureImageController {
//       imageSelector.featureImageSelected(indexPath)
//      }
        self.delegate?.featureImageSelected(indexPath)
}

DetailViewController中的elegate方法实例。两者都需要。

func featureImageSelected(indexPath: NSIndexPath) {
    record?.featureImage = record?.images[indexPath.row]
    self.configureView()
}

为什么响应者链方法可行,但代表不是?

没有编译器或运行时错误。在didSelectItemAtIndexPath方法中,委托总是返回nil,并且没有从委托方法打印任何内容。

2 个答案:

答案 0 :(得分:0)

您的响应者代码调用self:

上的featureImageSelected
self.featureImageSelected(indexPath)

但委托代码在委托上调用featureImageSelected:

self.delegate.featureImageSelected(indexPath)

这将是DetailVC的委托,而不是collectionViews委托。我不确定你的代码在做什么,但你可能想要像

这样的东西
collectionView.delegate?.featureImageSelected(IndexPath)

看起来它最终会成为

self.featureImageSelected(indexPath)

答案 1 :(得分:0)

问题中的错误是,在符合的类中,"创建了PhotoCollectionVC()的实例,并将delegate属性设置为self"。在viewDidLoad中,它只是创建了另一个具有永远不会被调用的无关委托属性的实例。实际嵌入式PhotoCollectionVC的委托属性需要分配给自己 - 以便两个VC进行通信。这是在prepareForSegue方法中完成的:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
    ...
        let controller =  (segue.destinationViewController as! PhotoCollectionVC)
        ...
        controller.delegate = self
        }
    }
}

示例代码的其余部分没问题。

以下是从嵌入式容器到其委托VC的委派的一个非常简单的示例。嵌入式容器只是告诉VC按下了一个按钮。故事板只是一个VC,里面有一个容器和一个文本插座。在容器VC中,只有一个按钮。而segue有一个标识符。

委托ViewController中的代码是:

protocol ChangeLabelText: class
{
  func changeText()
}

class ViewController: UIViewController, ChangeLabelText
{
    @IBOutlet weak var myLabel: UILabel!

    override func viewDidLoad()
    {
        super.viewDidLoad()
        myLabel?.text = "Start"
    }

    func changeText()
    {
        myLabel?.text = "End"
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "feelTheBern"
        {
            let secondVC: myViewController = segue.destinationViewController as! myViewController
            secondVC.delegate = self
        }}
}

委托视图控制器myViewController中的代码是:

class myViewController: UIViewController
{
    weak var delegate: ChangeLabelText?

    @IBAction func myButton(sender: AnyObject)
    {
        print("action")
        delegate?.changeText()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}