**Updated** How to pass data/value from View To View Controller?

I have a collection view (Calendar) and I have my modal view and I want the modal view to display what is in the cell when its selected.

Im not sure how do I go about doing this?


So far I changed the color of the cells background when selected.

How do I call and animate the child view controller?

and then display that cells content?


// Reuseable Cell

setupViews()
       
        myCollectionView.delegate=self
        myCollectionView.dataSource=self
        myCollectionView.register(dateCVCell.self, forCellWithReuseIdentifier: "Cell")
    }
// cell selected BG color change

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell=collectionView.cellForItem(at: indexPath)
cell?.backgroundColor=Colors.blue
let lbl = cell?.subviews[1] as! UILabel
lbl.textColor=UIColor.white
}

Replies

I want the modal view to display what is in the cell when its selected.


How is defined this modalView ? Is it another viewController or a view inside the same viewController as the tableView.


I suppose it is the first case and that I understand correctly what you want to do.


Then, you should

- define a segue from the VC (that contains the tableView)

- give it an ID, such as segueToDetailModal

- compelment didSelect to segue:


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
     let cell=collectionView.cellForItem(at: indexPath)
     cell?.backgroundColor=Colors.blue
     let lbl = cell?.subviews[1] as! UILabel
     lbl.textColor=UIColor.white
     performSegue(withIdentifier: "segueToDetailModal", sender: nil)
}

in prepare, pass the necessary data to the destination

Im not sure if that helps... I have zero programming experience / self taught.

I am trying to programmatically create a modal view appear half screen when a cell is longpressed.


so far I have:


privatefunc collectionView(_ collectionView: UITapGestureRecognizer, didSelectItemAt indexPath: IndexPath) {
        func longPressed(sender: UILongPressGestureRecognizer)
        {
           let longPressed = UITapGestureRecognizer(target: self, action: "longPressed:")
        }
    }



along with the intial code:

// Reuseable Cell 
 
setupViews() 
        
        myCollectionView.delegate=self 
        myCollectionView.dataSource=self 
        myCollectionView.register(dateCVCell.self, forCellWithReuseIdentifier: "Cell") 
    } 



// cell selected BG color change 
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
let cell=collectionView.cellForItem(at: indexPath) 
cell?.backgroundColor=Colors.blue 
let lbl = cell?.subviews[1] as! UILabel 
lbl.textColor=UIColor.white 
}

and it seems as if Im missing something but I dont know what.

If you want to use longPress, a good way is to use preview

Read this

h ttps://medium.com/@darjeelingsteve/supporting-3d-touch-peek-and-pop-ee80d2a4bd69


You can also do it more simply (but not as good IMHO):

- create a view in IB, with the content you want to display

- declare this view as hidden

- on longpress, just unhide the view.

- provide a way to hide again (a specific button, or a tap outside the view).

the artical is interesting but not what im looking..


But your opinion is exactly what Im looking to create. Thanks a million!

"IB" Im assuming an IB outlet?


Im going to be all over it now like butter on toast. Thanks for the help!

IB meant Interface Builder.

And yes, connect it to an IBOutlet.


Sorry for using acronym (we use too much of them) !

So I think I know why I am having the problem but Im not sure.


I am trying to pass true/false value from a UIView to a UIViewController is there a way to work around this?

Is it my code or something else that is making the two not communicate?



Below I created a gesture button that will "unhide" a view that is in another VC.


mySwiftFile1.swift


import UIKit
import SwiftUI


class SeasonsView: UIView, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, SeasonViewDelegate  {



@objc func handleLongPress(gesture: UILongPressGestureRecognizer) {


            if gesture.state == UIGestureRecognizer.State.began {

               ModalCalViewController.view.isHidden = false

            print("Long press is working")         

          }
    }


This is my child viewcontroller with a button to make it hidden again.


mySwiftFile2.swift


import UIKit

class ModalCalViewController: UIViewController {

        @IBAction func hideChildControllerBtn(_ sender: Any) {
// Button to set view back to hidden        
        view.isHidden = true
    }
    override func viewDidLoad() {
        super.viewDidLoad()

// Default view is set to hidden.
        view.isHidden = true

        view.backgroundColor = UIColor.red
        view.isOpaque = false
    }

}




How can I have mySwiftFile1 set the child controller in mySwiftFile2 to "unhidden"?

To show a view controller, you need to instatiate it and use the instance.

I cannot find any code to instantiate a view controller, how are you doing it?


And you usually do not modify `isHidden` property of a view controller's view when showing a modal view.

Better learn a usual way and you can utilize many techniques found on the web.


When you need to pass some value to another view controller, you usually prepare a property to receive it:

class ModalCalViewController: UIViewController {
    
    //Create a property to receive the value you want to pass
    var passedValue: Bool = false
    
    @IBAction func hideChildControllerBtn(_ sender: Any) {
        // Button to set view back to hidden
        dismiss(animated: true, completion: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .red
    }
    
    //And use the passed value in `viewWillAppear(_:)`
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        //Use passedValue here...
        //For example:
        if passedValue {
            view.backgroundColor = .blue
        }
    }
}


And instatiate and show the view controller like this:

    @objc func handleLongPress(gesture: UILongPressGestureRecognizer) {
        guard gesture.state == .began else {return}
        let position = gesture.location(in: collectionView)
        if let indexPath = collectionView.indexPathForItem(at: position) {
            guard let modalCalVC = self.storyboard?.instantiateViewController(identifier: "ModalCalViewController") as? ModalCalViewController else {
                print("ModalCalViewController cannot be instantiated")
                return
            }
            let value = true //Get the value you want to pass from `indexPath`
            modalCalVC.passedValue = value
            present(modalCalVC, animated: true, completion: nil)
        } else {
            print("Long press not on a cell")
        }
    }

I assume you have set up the UILongPressGestureRecognizer successfully, and have a property named `collectionView`.

And you need to give a Storyboard ID "ModalCalViewController" on the view controller in your storyboard.

Thank you OOPer


Im getting the errors:


Use of unresolved identifier 'present'

present(modalCalVC, animated: true, completion: nil)


and


Cannot use optional chaining on non-optional value of type 'Any'

guardlet modalCalVC = self.storyboard?.instantiateViewController(identifier:


I believe its because my collectionView class is a UIView and not a UIViewController.

How can I get around this problem?

Sorry, I was missing your declaration of `SeasonsView` which was a subclass of `UIView`.


Then many things depend on how you are showing your `SeasonsView`.

There must be a view controller which is displaying your SeasonsView. You may need to request the view controller to open a modal window.