Cannot see my second collectionView on viewController - ios

So I have my program where I have two collection views on the same ViewController. However when I run the app I can only see one. I have set the constraints on the image the same way on both.
the arrays productsImages and StoresImages are names of images I have in my assets folder. Firthermore pillImage and compStoreImage I have as outlet on my ColectionViewCell files.
HomeViewController.swift
import UIKit
class HomeViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource{
#IBOutlet weak var productCollectionView: UICollectionView!
#IBOutlet weak var storesCollectionView: UICollectionView!
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if(collectionView == storesCollectionView) {
return storesImages.count
}
return productsImages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = productCollectionView.dequeueReusableCell(withReuseIdentifier: "productsCell", for: indexPath) as! productCollectionViewCell
cell.pillImage.image = UIImage(named: productsImages[indexPath.row])
if(collectionView == storesCollectionView) {
let cell2 = storesCollectionView.dequeueReusableCell(withReuseIdentifier: "storesCell", for: indexPath) as! StoreCollectionViewCell
cell2.compstoreImage.image = UIImage(named: storesImages[indexPath.row])
return cell2
}
return cell
}
var productsImages:[String] = ["pillImage", "pillyImage", "pillsImage"]
var storesImages:[String] = ["compstoreImage", "compeImage", "compeStore"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
StoreCollectionViewCell.swift
import UIKit
class StoreCollectionViewCell: UICollectionViewCell {
#IBOutlet var compstoreImage: UIImageView!
}
productCollectionViewCell.swift
import UIKit
class productCollectionViewCell: UICollectionViewCell {
#IBOutlet var pillImage: UIImageView!
}
Screenshot

Related

Can't understand how to perform Segue from my custom Cell (in UICollectionView) to Player (ViewController) [duplicate]

This question already has answers here:
passing tapped cell data to another view via segue in Swift
(2 answers)
Pass data through segue
(3 answers)
Closed 8 months ago.
Hi dear professionals.
I have main ViewController, where I put Three horizontal CollectionView with cells into (but I hope at least solve problem with 1 of these).
One of this named - FirstPlaylistCollectionView
Cells also custom - FirstPlaylistCollectionViewCell
On tap on cell with specific video it needed pass Video object to the Player (PlayerViewController).
I cant figure it out how, in my case, make this Segue (pass Video object with necessary data) from CollectionView by code !
I almost don't use Storyboard in this project.
Maybe with help of Delegate, but I'm also couldn't understand how to use them for my case.
Method didSelectItemAt - works and get Video object, but i don't understand how to pass it correctly.
Will be very grateful for answer. I couldn't apply for now any solution from Stack, help please.
FirstPlaylistCollectionView code
import UIKit
protocol FirstPlaylistCollectionViewDelegate: AnyObject {
func playVideo()
}
class FirstPlaylistCollectionView: UICollectionView, UICollectionViewDelegate, UICollectionViewDataSource, ModelDelegate {
var playlistsModel = PlaylistsModel()
private var firstPlaylist: [Video] = []
weak var delegate2: FirstPlaylistCollectionViewDelegate?
// MARK: - Data Source
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return firstPlaylist.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = dequeueReusableCell(withReuseIdentifier: FirstPlaylistCollectionViewCell.reuseId, for: indexPath) as! FirstPlaylistCollectionViewCell
let video = self.firstPlaylist[indexPath.row]
cell.setCell(video)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.delegate2?.playVideo()
print("selected video \(firstPlaylist[indexPath.row]) with \(collectionView)! DONE!")
}
FirstPlaylistCollectionViewCell code
class FirstPlaylistCollectionViewCell: UICollectionViewCell {
static let reuseId = "FirstPlaylistCollectionViewCell"
var video: Video?
PlayerViewController code
import UIKit
import WebKit
class PlayerViewController: UIViewController {
#IBOutlet weak var handleArea: UIView!
#IBOutlet weak var openCloseArrow: UIImageView!
var video: Video?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("I'm here!!!")
let vc2 = segue.destination as! PlayerViewController
if let cell = sender as? Video {
self.video = cell
vc2.titleOfVideoLabel.text = video?.title
}
}
}
extension PlayerViewController: FirstPlaylistCollectionViewDelegate {
func playVideo() {
performSegue(withIdentifier: "homeToPlayer", sender: self)
}
}
Answering this by assuming some of the things, I hope you want to navigate to PlayerViewController from ViewController through a segue. Keeping that in my mind, I have assumed your FirstPlaylistCollectionView is in your ViewController class as mentioned below.
class ViewController: UIViewController {
var firstPlaylistCollectionView: FirstPlaylistCollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// First try to get notified from your collection list to here
// and then from here to your player
firstPlaylistCollectionView.listDelegate = self
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if let id = segue.identifier, id == "playerSegue",
let lVideo = sender as? Video,
let destination = segue.destination as? PlayerViewController{
destination.video = lVideo
}
}
}
extension ViewController: FirstPlaylistCollectionViewDelegate {
func firstPlaylistCollectionView(_ listView: FirstPlaylistCollectionView, didSlect video: Video) {
self.performSegue(withIdentifier: "playerSegue", sender: video)
}
}
And below is the update for the collection view
class FirstPlaylistCollectionView: UICollectionView {
var playlistsModel = PlaylistsModel()
private var firstPlaylist: [Video] = []
weak var listDelegate: FirstPlaylistCollectionViewDelegate?
}
extension FirstPlaylistCollectionView: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return firstPlaylist.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = dequeueReusableCell(withReuseIdentifier: FirstPlaylistCollectionViewCell.reuseId, for: indexPath) as! FirstPlaylistCollectionViewCell
/* Here it goes your cell configuration
.
.
*/
return cell
}
}
extension FirstPlaylistCollectionView: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
listDelegate?.firstPlaylistCollectionView(self, didSlect: firstPlaylist[indexPath.row])
}
}
And finally verify that the playerViewController has received the data or not
class PlayerViewController: UIViewController {
#IBOutlet weak var handleArea: UIView!
#IBOutlet weak var openCloseArrow: UIImageView!
var video: Video?
override func viewDidLoad() {
super.viewDidLoad()
print("Video object from player vc :: \(video)")
}
}
Added protocol is
protocol FirstPlaylistCollectionViewDelegate: AnyObject {
func firstPlaylistCollectionView(_ listView: FirstPlaylistCollectionView, didSlect video: Video) ->Void
}
you can use Prepare for segue or Did Select Row method try these out.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedProgram = programy[indexPath.row]
let destinationVC = PlayerTableViewController()
destinationVC.programVar = selectedProgram
destinationVC.performSegueWithIdentifier("playerSegue", sender: self)
}

How do I set auto height on my CollectionViewCell

I've been searching for days these answers and some how I found it but I don't know how to configure properly to my project.
I followed this awesome video iOS Dev 11: CollectionViews | Swift 5, XCode 11
This video works perfectly to me, but when we reach sizeForItemAt method he declares a static value. For my project, width could be static and I was able to fix according the result I want, but I am still facing difficult to adapt the height. I want it to be equal the text size of my label text, I want I result like this: final result
So, I know that I need to to this on sizeForItemAt method but I don't know how, here is how my code looks like:
FactsCollectionViewCell:
class FactsCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var lbFactsText: UILabel!
#IBOutlet weak var lbCategories: UILabel!
func setup(with facts: FactsData?, index: Int) {
let result = facts!.result[index]
lbFactsText.text = result.value
print(result.value)
if let category = result.categories.first {
lbCategories.text = category!.uppercased()
lbCategories.sizeToFit()
} else {
lbCategories.text = "UNCATEGORIZED"
lbCategories.sizeToFit()
}
}
#IBAction func btShare(_ sender: UIButton) {
// still working on this button
}
}
And this is my MainViewController:
class MainViewController: UIViewController {
var facts: FactsData?
var factsManager = FactsManager()
var numberOfCV = 0
var resultValue: String = ""
#IBOutlet weak var cvFacts: UICollectionView!
#IBOutlet weak var sbSearchFacts: UISearchBar!
#IBOutlet weak var nbMainScreen: UINavigationBar!
override func viewDidLoad() {
super.viewDidLoad()
cvFacts.dataSource = self
cvFacts.delegate = self
cvFacts.collectionViewLayout = UICollectionViewFlowLayout()
sbSearchFacts.isHidden = true
}
#IBAction func search(_ sender: UIBarButtonItem) {
sbSearchFacts.resignFirstResponder()
sbSearchFacts.isHidden = !sbSearchFacts.isHidden
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueMainToFact" {
let vc = segue.destination as! FactViewController
vc.receivedValue = resultValue
}
}
}
extension MainViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numberOfCV
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = cvFacts.dequeueReusableCell(withReuseIdentifier: "FactsCollectionViewCell", for: indexPath) as! FactsCollectionViewCell
cell.setup(with: facts, index: indexPath.row)
return cell
}
}
// SearchBar delegate extension for when tap to search button
extension MainViewController: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
sbSearchFacts.isHidden = true
sbSearchFacts.resignFirstResponder()
if let realFact = sbSearchFacts.text {
factsManager.factsRequest(realFact) { (facts) in
self.facts = facts
self.numberOfCV = self.facts!.total
DispatchQueue.main.async {
self.cvFacts.reloadData()
}
} onError: { (error) in
print(error)
}
}
}
}
// Extension to configure cell sizes
extension MainViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = view.frame.size.width
return CGSize(width: width - 40, height: //HERE I NEED TO CALCULATE THE HEIGHT BUT I DONT KNOW HOW)
}
}
// Extension for when you tap the cell
extension MainViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let index = indexPath.row
let result = facts?.result[index]
resultValue = result!.value
}
}
Does anyone has a tip to fix it?

Pass data from CollectionView to TabBarController, than to his childs in Swift

I am new to Swift. Unable to find solution for below problem.
Below is a ViewController with CollectionView and When you click on Cell in CollectionView, data from cell(even this who isn't in label and image view, but are in Book array row) must be send to TabBarCollection, than from TabBarCollection I need to send this data to all of child's, like in this image.
Later in childs of TabBar I will set value of Labels in View Controllers from data from choosed Cell.
Book.swift
import UIKit
struct Book {
let title: String
let image: UIImage?
//Here soon will be more "let", and this data will also have to be send to TabBar but it don't will be show I CollectionViewCell
}
extension Book {
static let books: [Book] = [
Book(title: "Antygona", image: UIImage(named: "imgantygona")!),
//etc
]
}
CollectionViewCell.swift
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var bookImageView: UIImageView!
#IBOutlet weak var bookTitle: UILabel!
func setup(with book: Book) {
bookTitle.text = book.title
bookImageView.image = book.image
}
}
ViewController
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
let books = Book.books
override func viewDidLoad() {
super.viewDidLoad()
let fontAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16.0)]
UITabBarItem.appearance().setTitleTextAttributes(fontAttributes, for: .normal)
collectionView.dataSource = self
collectionView.delegate = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return books.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "bookCell", for: indexPath) as! CollectionViewCell
let book = books[indexPath.item]
cell.setup(with: book)
return cell
}
}
I saw many solutions but I can't perfectly adapt it to my problem. :(
Thanks for help !
BookInsideViewController.swift
import UIKit
class BookInsideViewController: UIViewController {
#IBOutlet weak var testImageView: UIImageView!
#IBOutlet weak var testLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
}
You can use collection view DidSelectItemAt function
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "YourtabbarIdentifier") as! UITabBarController
// You should access the `imageController` through your `tabBarController`,
// not instantiate it from storyboard.
if let viewControllers = tabBarController.viewControllers,
let imageController = viewControllers.first as? ImageController {
BookInsideViewController.recivedData1 = Books[indexPath.row]
}
navigationController?.pushViewController(tabBarController, animated: true)
}

how to execute collectionView class from different ViewController

i have a collectionView class
class LC: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
//in LC
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let VC = segue.destination as? VC2 {
VC.Rpe = Pass
}
}
it's working fine , in VC2 i have a function when executed it should segue to the next cell in the collection view
i'm not sure how or what is the best way to do it (reload VC2 with the next collection view cell details?, or run the collection view functions programmatically )
update
import Foundation
import UIKit
class View2: UIViewController {
#IBOutlet var Q_Pic: UIImageView!
#IBOutlet var Q_que: UILabel!
var SelectedCell: Ques!
override func viewDidLoad() {
super.viewDidLoad()
Q_Pic.image = UIImage(named: SelectedCell.LIMG)
Q_que.text = SelectedCell.Q
}
#IBAction func herewego(_ sender: Any) {
print("when the user press this button it should take him directly to the next cell detail , i don't want the user to go back to collection view and choose the next cell")
}
}
data
let Q_A_TEST_MOH = [
Ques(Q: "Q1? ",LIMG: "1"),
Ques(Q: "Q2? ",LIMG: "2"),
Ques(Q: "Q3?",LIMG: "3"),
Ques(Q: "Q4?",LIMG: "4"),
Ques(Q: "Q5?",LIMG: "5")
]
struct Ques {
var Q : String
var LIMG: String
}
UICollectionViewController
import Foundation
import UIKit
class test:UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
#IBOutlet var CollectionView: UICollectionView!
var Levelssss: [Ques]!
var ToPass: Ques!
var SelectedCategory: String!
var Level: Int!
override func viewDidLoad() {
super.viewDidLoad()
CollectionView.delegate = self
CollectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Q_A_TEST_MOH.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LevelCell2", for: indexPath) as? cell1 {
let r = Q_A_TEST_MOH[indexPath.item]
cell.congigureCell(EditLater: r)
return cell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
ToPass = Q_A_TEST_MOH[indexPath.item]
performSegue(withIdentifier: "To", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let detalsVC = segue.destination as? View2 {
detalsVC.SelectedCell = ToPass
}
}
}
UICollectionViewCell
import UIKit
class cell1: UICollectionViewCell {
#IBOutlet var BB: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
BB.layer.cornerRadius = 10
}
func congigureCell(EditLater: Ques){
BB.setImage(UIImage(named: EditLater.LIMG), for: .normal)
}
}
Download project from here : download the project
Here is the fixed variant: https://www.dropbox.com/s/bc7ktktrbqg9x7t/test%202.zip?dl=0
Logic is simple: pass a whole array of data and index of selected object.
In VC2 on button click you just increment index and update content of your views.
Now you should just check is index not greater then count of element in array.

UICollectionView scrolling/swipe to next item swift

I have a UICollectionView in a view controller. When the user clicks one of the images, it goes to a separate page to open the image. I would like instead of going back to the gallery each time to change pictures, to swipe left or right to get the next or previous picture.
I have seen answers to do "pagingEnabled = true" but where do you put this exactly?
I am new to swift.
Below is my code. Thanks for the help in advance.
ViewController.swift
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate
{
#IBOutlet weak var collectionView: UICollectionView!
let appleProducts = ["iPhone", "Apple Watch", "Mac", "iPad"]
let imageArray = [UIImage(named: "pug"), UIImage(named: "pug2"), UIImage(named: "pug3"), UIImage(named: "pug4")]
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return self.appleProducts.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CollectionViewCell
cell.imageView?.image = self.imageArray[indexPath.row]
cell.titleLabel?.text = self.appleProducts[indexPath.row]
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("showImage", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "showImage"
{
let indexPaths = self.collectionView!.indexPathsForSelectedItems()!
let indexPath = indexPaths[0] as NSIndexPath
let vc = segue.destinationViewController as! NewViewController
vc.image = self.imageArray[indexPath.row]!
vc.title = self.appleProducts[indexPath.row]
}
}
}
CollectionViewCell.swift
import UIKit
class CollectionViewCell: UICollectionViewCell
{
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var titleLabel: UILabel!
}
NewViewController.swift
import UIKit
class NewViewController: UIViewController
{
#IBOutlet weak var imageView: UIImageView!
var image = UIImage()
override func viewDidLoad()
{
super.viewDidLoad()
self.imageView.image = self.image
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
In the view controller that is presented after a tap, you should make a horizontally scrolling UICollectionView. On this collection view, set its pagingEnabled property to true.
The next thing to do is reformat your prepareForSegue method in your parent view controller to pass the entire array of images to the presented view controller as well as the selected index path.
Then, in your presented view controller, you should have the collection view's data source be configured to show all the images but make sure to start at the initial, selected index path that was passed by the parent view controller.

Resources