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

Posted

技术标签:

【中文标题】响应者链但不是委托属性将值从容器传递回视图控制器【英文标题】:Responder Chain but NOT delegate property passes value back to view controller from container 【发布时间】:2015-12-07 16:53:27 【问题描述】:

以下代码应显示两种使用响应者链或委托方法将信息从嵌入式控制器 (UICollectionView) 传递回详细视图控制器的方法。两种方法都使用相同的协议和委托方法。唯一的区别是,如果我在 didSelectItemAtIndex 路径中注释掉 delegate?.method 行,响应者链就会起作用。但是,如果我注释掉 didSelectItemAtIndex 方法中的 Responder Chain 行,未注释的委托? property 不调用该方法,并且保持为 nil。

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

protocol FeatureImageController: class 
func featureImageSelected(indexPath: NSIndexPath)

自定义UICollectionViewController类中声明的Delegate属性,仅在委托方式中需要。

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 方法中,通过响应者链(已注释掉)或委托将选定的 indexPath 传回 DetailVC 中的 featureImageSelected 方法。

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,并且委托方法不打印任何内容。

【问题讨论】:

【参考方案1】:

您的响应者代码在自身上调用 featureImageSelected:

self.featureImageSelected(indexPath)

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

self.delegate.featureImageSelected(indexPath)

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

collectionView.delegate?.featureImageSelected(IndexPath)

看起来它最终会成为

self.featureImageSelected(indexPath)

【讨论】:

self.featureImageSelected(indexPath) 给出编译器错误:“PhotoCollectionVC”类型的值没有成员 featureImageSelected。我看不出 Responder Chain 将 imageController 分配为 FeatureImageController 与委托分配委托之间的区别?作为功​​能控制器。 (当然除了没有调用委托方法,并且属性保持为零) 啊,好吧,如果 self 是 PhotoCollectionVC,你确实想要self.delegate.featureImageSelected。这在您发布的代码中并不明显。如果您的代表为零,那就是问题所在。 The targetForAction 将沿着响应者链上升,直到找到可以实现 featureImageSelected 的东西,这就是它起作用的原因。 知道为什么委托方法不起作用吗?或者如何让它调用委托方法? didSelectitemAtIndexPath 方法中调试您的代码并确定委托是否为零。从那里您需要确保正确设置委托。我看不到您的所有代码,但有些想法是 1)您将委托设置在不同的 PhotoCollectionVC 上,2)您不符合协议,因此它没有正确设置委托。 我用我认为的所有相关代码更新了这个问题。这不是一个复杂的项目,只有一个 PhotoCollectionVC。委托始终为零,并且该方法永远不会被调用。它符合响应者链方法的协议。【参考方案2】:

问题中的错误是,在符合标准的类中,“创建了 PhotoCollectionVC() 的实例,并且委托属性设置为 self”。在 viewDidLoad 中,这只是创建了另一个实例,它具有永远不会被调用的无关委托属性。实际嵌入的 PhotoCollectionVC 的委托属性需要分配给 self - 以便两个 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()
    

【讨论】:

以上是关于响应者链但不是委托属性将值从容器传递回视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

将值从模型传递到 CI 中的视图

IOS 将值从 App Delegate 传递到初始视图控制器并在 viewWillAppear 中使用这些值

将值从视图传递到控制器,我错过了啥?

将值从表视图控制器传递到视图控制器

通过 Laravel 中的 AJAX 发布请求将值从一个视图传递到另一个视图

如何将值从 tableview 传递到 collectionview