从 UICollectionViewCell 调用函数以在 UICollectionView 中使用

Posted

技术标签:

【中文标题】从 UICollectionViewCell 调用函数以在 UICollectionView 中使用【英文标题】:Call function from UICollectionViewCell to use in UICollectionView 【发布时间】:2018-02-16 16:49:23 【问题描述】:

我有一个 UICollectionViewCell,它创建一堆文本字段和一个函数 (handleNewJob),它查看在单元格中创建的所有文本字段并将它们写入 firebase。

但是,我想要的是我在 UICollectionView 中创建的按钮从 UICollectionViewCell 调用函数 (handleNewJob)。

这可能吗?我尝试在 UICollectionView 中使用该函数,但似乎无法引用所有 textfields.text?

这是我在 UICollectionViewCell 中的函数(我没有包含所有文本字段生成,因为它很长):

        // HANDLE NEW JOB
        func handleNewJob()
            let newJobBrand = jobBrand.text!
            let newJobName = jobName.text!
            let newDirectorName = directorName.text!
            let newAgencyName = agencyName.text!
            let newProdCoName = prodCoName.text!
            // WHERE TO PUT IN DATABASE
            let reference = Database.database().reference().child("jobInfo")
            let childRef = reference.childByAutoId()
            // REFERENCING DICTIONARY
            let jobBrandValue = ["jobBrand": newJobBrand]
            let jobNameValue = ["jobName": newJobName]
            let jobDirectorValue = ["directorName": newDirectorName]
            let jobAgencyNameValue = ["agencyName": newAgencyName]
            let jobProdCoValue = ["prodCoName": newProdCoName]
            // WRITE TO DATABASE
            childRef.updateChildValues(jobBrandValue)
            childRef.updateChildValues(jobNameValue)
            childRef.updateChildValues(jobDirectorValue)
            childRef.updateChildValues(jobAgencyNameValue)
            childRef.updateChildValues(jobProdCoValue)
        

这是我的 UICollectionView 代码 - 我想调用 handleNext 按钮下的函数:

          import UIKit
      import Firebase

      class page_newJobSwipingController : UICollectionViewController, UICollectionViewDelegateFlowLayout, UIImagePickerControllerDelegate, UINavigationControllerDelegate 

          // VARIABLES
          var ref:DatabaseReference?

              // BOTTOM BUTTONS
          private let previousButton: UIButton = 
              let button = UIButton(type: .system)
              button.setTitle("Previous", for: .normal)
              button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
              button.setTitleColor(.gray, for: .normal)
              button.addTarget(self, action: #selector(handlePrev), for: .touchUpInside)
              button.translatesAutoresizingMaskIntoConstraints = false
              return button
          ()
          private let nextButton: UIButton = 
              let button = UIButton(type: .system)
              button.setTitle("Next", for: .normal)
              button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
              let pinkColour = UIColor(red: 232/255, green: 68/266, blue: 133/255, alpha: 1)
              button.setTitleColor(.mainPink, for: .normal)
              button.translatesAutoresizingMaskIntoConstraints = false
              button.addTarget(self, action: #selector(handleNext), for: .touchUpInside)
              return button
          ()

              // SET UP NEXT AND PREVIOUS BUTTONS TO HAVE A FUNCTION
          @IBAction func handlePrev(sender : UIButton) 
              let prevIndex = max(pageControl.currentPage - 1, 0)
              pageControl.currentPage = prevIndex
              let indexPath = IndexPath(item: prevIndex, section: 0)
              collectionView?.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
          
          @IBAction func handleNext(sender : UIButton) 
              let nextIndex = pageControl.currentPage + 1
              pageControl.currentPage = nextIndex
              if nextIndex == 1 
                  print ("move to page 2")
               else 
                  print ("send alert message")
                  newJobCellGeneral.handleNewJob()
                  storyboardAlert()
              

              let indexPath = IndexPath(item: 1, section: 0)
              collectionView?.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
          

          // HANDLE UPLOAD STORYBOARD OPTIONS
          @IBAction func storyboardAlert() 

              let imagePickerController = UIImagePickerController()
              imagePickerController.delegate = self
              // ACTION SHEET FOR ADDING NEW ATTACHMENT
              let alert = UIAlertController(title: "Job Created", message: "Do you want to upload storyboard cells now?", preferredStyle: .actionSheet)
              alert.addAction(UIAlertAction(title: "Now", style: .default, handler:  (action:UIAlertAction) in
                  let storyboardUpload = page_newJobStoryboardUpload()
                  self.show(storyboardUpload, sender: self)
              ))
              alert.addAction(UIAlertAction(title: "Later", style: .default, handler:  (action:UIAlertAction) in
                  let jobList = page_jobList()
                  self.show(jobList, sender: self)
              ))
              alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
              self.present(alert, animated: true, completion: nil)
          

              // PAGE CONTROL
          private let pageControl: UIPageControl = 
              let pc = UIPageControl()
              pc.numberOfPages = 2
              pc.currentPageIndicatorTintColor = .mainPink
              pc.pageIndicatorTintColor = UIColor(red: 249/255, green: 207/266, blue: 224/255, alpha: 1)
              return pc
          ()
          override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) 
              let x = targetContentOffset.pointee.x
              pageControl.currentPage = Int(x / view.frame.width)
          
              // CONSTRAINTS OF BOTTOM CONTROLS
          fileprivate func setupBottomControls()
              let bottomControlsStackView = UIStackView(arrangedSubviews: [previousButton, pageControl, nextButton])

              bottomControlsStackView.translatesAutoresizingMaskIntoConstraints = false
              bottomControlsStackView.distribution = .fillEqually
              view.addSubview(bottomControlsStackView)

              NSLayoutConstraint.activate([
                  bottomControlsStackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
                  bottomControlsStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                  bottomControlsStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                  bottomControlsStackView.heightAnchor.constraint(equalToConstant: 50)
                  ])
          

          // SUPER VIEW DID LOAD
          override func viewDidLoad() 
              super.viewDidLoad()

              collectionView?.backgroundColor = .white
              collectionView?.register(newJobCellGeneral.self, forCellWithReuseIdentifier: "newJobCellGeneral")
              collectionView?.register(newJobCellTechnical.self, forCellWithReuseIdentifier: "newJobCellTechnical")
              collectionView?.isPagingEnabled = true

              setupBottomControls()

          
          func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat 
              return 0
          
          override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
              return 2
          
          override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

              if indexPath.item == 0 

                  let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "newJobCellGeneral", for: indexPath) as! newJobCellGeneral
                  navigationItem.title = "General Info"
                  return cell
               else 
                  let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "newJobCellTechnical", for: indexPath) as! newJobCellTechnical
                  navigationItem.title = "Technical Specs"
                  return cell
              
          
          func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
              return CGSize(width: view.frame.width, height: view.frame.height)
          
      

【问题讨论】:

【参考方案1】:

流程是相反的,但是是的,最简单的方法是通过通知 在你的收藏视图中

把它放在你的collectionView按钮按下方法中

NotificationCenter.default.post(name: Notification.Name("handleNewJob"), object: nil)

在您的集合视图单元格中添加观察者(init 或 awakeFromNib 取决于)

NotificationCenter.default.addObserver(self, selector: #selector(handleNewJob, name: NSNotification.Name(rawValue: "handleNewJob"), object: nil)

【讨论】:

添加这两行后,我应该在handleNext 按钮中添加什么来调用函数?我只想在按下按钮时调用该函数。我现在有这个newJobCellGeneral.handleNewJob(),我收到错误 Instance member 'handleNewJob' cannot be used on type 'newJobCellGeneral';您的意思是使用这种类型的值吗? 这段代码有效 - 但是我没有将第一行放入 viewDidLoad 中,而是将其放入我的按钮函数中,因此只有在点击时才会调用它。感谢您的帮助。【参考方案2】:

通知中心是一种解决方案,但更简单的方法是能够直接从单元格调用集合视图控制器上的函数。

为此,您需要能够引用您的父视图控制器。所以添加这个 UIView 扩展:

创建一个名为 UIView.swift 的 swift 文件并粘贴:

import UIKit
extension UIView 
    var parentViewController: UIViewController? 
        var parentResponder: UIResponder? = self
        while parentResponder != nil 
            parentResponder = parentResponder!.next
            if parentResponder is UIViewController 
                return parentResponder as! UIViewController!
            
        
        return nil
    
 

然后从您的单元格中,例如单击按钮时:

@IBAction func someButtonAction(sender : UIButton) 
    let parent = self.parentViewController as! page_newJobSwipingController

    parent.whateverFunction()

【讨论】:

我将第一块代码放在 UICollectionViewController 的底部,将第二块代码放在函数上方的单元格中。但是我在单元格中收到这些错误。对于 let 行 Value of type '(newJobCellGeneral) -> () -> (newJobCellGeneral)' has no member 'parent' 和第二行 Expected declaration。跨度> 创建一个名为 UIViewExtention 的新 swift 文件(但这个名称并不重要)并将第一个代码块放入其中。然后在你的单元格内,你想在父级上调用函数,使用第二个代码块。 我已经创建了新的 UIViewExtension 并复制了第一个块。当我将第二个文本块复制到我的 UIViewCollectionViewCell(类名:newJobCellGeneral)中时,我收到此错误Value of type 'newJobCellGeneral' has no member 'parent' 别担心我已经修复的错误。感谢您的帮助 - 我发现一旦代码放置在正确的位置,@zeck 的答案很容易工作。 因为你可能错过了 let parent = self.parentViewController as! page_newJobSwipingController 在同一个函数中

以上是关于从 UICollectionViewCell 调用函数以在 UICollectionView 中使用的主要内容,如果未能解决你的问题,请参考以下文章

如何确定何时显示 UICollectionViewCell?

以编程方式在特定 UICollectionViewCell 内的 TableView?

- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView cellForItemAtIndexPath 未调用

UICollectionViewCell里面的UIWebView不调用Delegate方法

awakeFromNib() 在滚动开始时在 UICollectionViewCell 子类中调用了两次

未调用 UICollectionViewCell didDeselectItemAtIndexPath