How to parse data from a UIViewController having 2 CollectionViews with swift - ios

How do I parse data from a UIViewController having 2 different UICollectionViews?
I have 2 UICollectionViews in on UIViewController I have been able to pull the data from the server to the views and its displayed but i'm having trouble parsing it to the next screens.
I have tired this using didSelectItemAt and performSegue but it can't parse the data to the other screen
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == self.categoryView {
let categoryViewController = self.storyboard?.instantiateViewController(withIdentifier: "CategoryListViewController") as! CategoryListViewController
categoryViewController.self.selectedC = self.category[indexPath.row]
self.navigationController?.pushViewController(categoryViewController, animated: true)
} else if collectionView == self.featuredView {
self.selectedPro = self.property[indexPath.row]
self.performSegue(withIdentifier: "showDet", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showCat"{
let categoryController = segue.destination as! CategoryListViewController
categoryController.selectedC = self.selectedC
}
else {
let detailViewController = segue.destination as! DetailsViewController
detailViewController.selectedPro = self.selectedPro
}
}
I'm expected to parse data to the second screen

Why are you using two different collection views? Why don't you just create two different cells? That way you can easily do an if let in the didSelect which type of cell has been tapped and pass the data on?

This Is the Solution
#IBOutlet weak var categoryView: UICollectionView!
let collectionViewAIdentifier = "catCell"
var category = [Category]()
#IBOutlet weak var featuredView: UICollectionView!
let collectionViewBIdentifier = "feaCell"
var property = [Property]()
override func viewDidLoad() {
super.viewDidLoad()
SVProgressHUD.show(withStatus: "Loading...")
categoryView.delegate = self
categoryView.dataSource = self
self.view.addSubview(categoryView)
featuredView.delegate = self
featuredView.dataSource = self
self.view.addSubview(featuredView)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
var count:Int?
// Category Collection View
if collectionView == self.categoryView {count = category.count}
//Property Collection View
if collectionView == self.featuredView {count = property.count}
return count!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// Category Collection View
if collectionView == self.categoryView {
let cellA = collectionView.dequeueReusableCell(withReuseIdentifier: collectionViewAIdentifier, for: indexPath) as! HomeCollectionViewCell
let cat: Category
cat = category[indexPath.row]
cellA.homId.text = cat.idd
cellA.homName.text = cat.name
//idCat = cat.idd!
return cellA
}
//Property Collection View
else {
let cellB = collectionView.dequeueReusableCell(withReuseIdentifier: collectionViewBIdentifier, for: indexPath) as! FeaturedCollectionViewCell
let pro: Property
pro = property[indexPath.row]
cellB.proId.text = pro.idd
cellB.proName.text = pro.name
return cellB
}
}
//Parsing data to next screen
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Category Collection View parsing data
if segue.identifier == "showCat" {
let categoryDetailVC = segue.destination as! CategoryListViewController
let cell = sender as! UICollectionViewCell
let indexPath = self.categoryView.indexPath(for: cell)
let categoryId = category[(indexPath?.row)!].idd
categoryDetailVC.idString = categoryId
}
//Property Collection View parsing data
else if segue.identifier == "showDet" {
let detailVC = segue.destination as! DetailsViewController
let cell = sender as! UICollectionViewCell
let indexPath = self.featuredView.indexPath(for: cell)
let detailId = property[(indexPath?.row)!].idd
detailVC.idProString = detailId
}
}

Related

how to prepare segue can't selected pass label text to text string

I have prepared a segue but when the user selects a cell it is not pass label text to text in detail View
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "viewNumberSegue" {
guard let indexPath = sender as? IndexPath else { return }
let collectionCell = collectionView.cellForItem(at: indexPath) as! ItemCollectionViewCell
let textToPass = collectionCell.ItemLabel.text
let detailVC = segue.destination as? DetailViewController
detailVC?.number = textToPass!
}
}
// MARK: UICollectionViewDelegate
extension GridCollectionViewController {
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "viewNumberSegue", sender: indexPath)
}
}
DetailVC
import UIKit
class DetailViewController: UIViewController {
var number:String = ""
#IBOutlet weak var numberLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
print(number)
numberLabel.text = number
}
}
Instead of passing the indexPath in sender, it's better to directly pass the number as sender.
extension GridCollectionViewController {
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let collectionCell = collectionView.cellForItem(at: indexPath) as! ItemCollectionViewCell
let textToPass = collectionCell.ItemLabel.text
self.performSegue(withIdentifier: "viewNumberSegue", sender: textToPass)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "viewNumberSegue" {
guard let number = sender as? String else { return }
let detailVC = segue.destination as? DetailViewController
detailVC?.number = number
}
}

Swift - Issue accessing data from UICollectionView embedded in UITableView

I have a tableView, with a prototype cell containing a UICollectionView. I’ve setup the tableView according to this tutorial (https://medium.com/#stasost/ios-how-to-build-a-table-view-with-multiple-cell-types-2df91a206429), and the UI is working. I can pass data through my tableView and into the collectionView.
View Layout
When a collectionViewCell is selected it segues to another view.
I haven’t figured out how to access the data from the collectionViewCell and pass it to the new view.
The collectionView is initialized within the tableView prototype cell. I've tried didSelectRow -> prepareForSegue (code below), but the commands do not autocomplete, and are not working.
Here's the code for the tableViewCell, where the collectionView is setup.
EDIT: Removed commented code for clarity
import UIKit
class homeFeedTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var feedCollectionView: UICollectionView!
var selectedEvent : Event?
var collectionItems = [CollectionViewModelItem]()
var collectionItem : CollectionViewModelItem?
#IBOutlet weak var sectionHeadingLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
feedCollectionView.delegate = self
feedCollectionView.dataSource = self
print("collection items \(collectionItems.count)")
for item in collectionItems{print("type: \(item.type), title: \(item.eventTitle)")}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
// setup view model
var item: TableViewModelItem? {
didSet {
// if not right class, skip
guard let item = item as? TableViewModelFeed else {
return
}
sectionHeadingLabel.text = item.sectionTitle
}
}
// create reuse identifier property
static var identifier: String {
return String(describing: self)
}
}
import Foundation
import UIKit
extension homeFeedTableViewCell {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// print("dataCount3: \(collectionItems.count) \(collectionItems[collectionItems.count-1].type)")
return collectionItems.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// let cell = UICollectionViewCell()
// return cell
self.collectionItem = collectionItems[indexPath.row]
switch collectionItem!.type {
case .yourEvents:
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier:YourEventsCollectionViewCell.identifier, for: indexPath) as? YourEventsCollectionViewCell{
cell.item = collectionItem
print(cell.item?.type)
print(".yourEvents")
return cell
}
case .feed:
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: mainFeedCollectionViewCell.identifier, for: indexPath) as? mainFeedCollectionViewCell{
cell.item = collectionItem
print(".feed")
return cell
}
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("\(collectionItems[indexPath.row].eventTitle) tapped")
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "yourEventsToEventViewController" || segue.identifier == "feedToEventViewController"{
print("prepare for segue1")
let destinationVC = segue.destination as! EventViewController
if collectionItem != nil{
print("prepare for segue2")
destinationVC.backgroundImageUrl = collectionItem!.backgroundImageUrl
}
}
}
}
}
A UICollectionView keeps track of its selected indexPaths with the property indexPathsForSelectedItems. Since you trigger your segue in collectionView(didSelectItem: atIndexPath:), your selected indexPath is available during prepare(forSegue:). You could try the following:
class MyViewController: UIViewController, UICollectionViewDelegate {
...
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
performSegue(withIdentifier: "mySegue", sender: self)
}
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
guard let destinationVC = segue.destination as! EventViewController,
segue.identifier == "mySegue" else { return }
// In this context, your selected cell is the one who fired the segue
if let selectedIndexPaths = collectionView.indexPathsForSelectedItems,
let firstSelectedIndexPath = selectedIndexPaths.first {
let selectedObject = collectionItems[firstSelectedIndexPath.row]
destinationVC?.backgroundUrl = selectedObject.backgroundUrl
}
}
}
The sequence is:
You select a cell (through user interaction, ie tapping).
didSelect performs a segue named "mySegue" (in this example).
In prepareForSegue, you look for your selected index paths. Assuming you aren't using multi-selection, you want your first and only indexPath. Using that index path, you can retrieve your data in your collectionItems array.

segue when clicking on a uicollectionview cell inside a table view cell

I have the following situation:
ExploreViewController is a table view controller with CategoryTableViewCell (child class of UITableViewCell)
The CategoryTableViewCell has a CollectionView with UICollectionViewCells.
When a user clicks on a UICollectionViewCell, I would like to segue ExploreViewController to BookListViewController based on the uICollectionViewCell data. Each UICollectionViewCell stands for a separated category.
How can I do this using swift? I tried using delegate protocol, but when I call performSegue inside the delegate function inside the ExploreViewController, I get an error.
In CategoryTableViewCell
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("test12")
self.delegate?.didSelectInEmbeddedCollection()
}
}
protocol CategoryTableViewCellDelegate {
func didSelectInEmbeddedCollection()
}
In ExploreViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("test14")
if segue.identifier == "toBookListFeatured",
let destination = segue.destination as? BookListViewController,
let selectedIndexPath = self.tableViewFeaturedCats.indexPathForSelectedRow,
let selectedCell = self.self.tableViewFeaturedCats.cellForRow(at: selectedIndexPath) as? CategoryTableViewCell
{
let collectionView = selectedCell.collectionView
let indexPathC = collectionView?.indexPathsForSelectedItems?.first
let cell = collectionView?.cellForItem(at: indexPathC!) as? CategoryCollectionViewCell
destination.data = cell!.label.text
} else {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
let dc = segue.destination as! BookListViewController
dc.data = self.tableRowData["name"] as! String;
dc.searchByCategory = true
}
}
}
extension ExploreViewController: CategoryTableViewCellDelegate {
func didSelectInEmbeddedCollection() {
performSegue(withIdentifier: "toBookListFeatured", sender: nil)
}
}

Cannot convert value of type 'mainImage.type' to exprected argument type 'String'

How can I pass data in uicollectionview and anther images view single images?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath) as? SelectAnimalViewCell {
let Category = DataService.instance.getCategories()[indexPath.row]
cell.updataView(selecting: Category)
return cell
}
else
{
return SelectAnimalViewCell()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let category = DataService.instance.getCategories()[indexPath.row]
performSegue(withIdentifier: "PuzzlingVC", sender: category)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let puzzlingVC = segue.destination as? PuzzlingViewController {
assert(sender as? Selecting != nil)
puzzlingVC.initPuzzles(category: sender as! Selecting)
}
if let puzzleIngController = segue.destination as? PuzzlingViewController{
assert(sender as? mainImage != nil)
puzzleIngController.meanImageView = mainImage.init(mainImagePuzzle: mainImage)
//cannot convert value of type 'mainImage.type' to exprected argument type 'Strign'
}
// let DestViewController : PuzzlingViewController = segue.destination as! PuzzlingViewController
// DestViewController.mainImage = DataService.instance.getCategories(Selecting.init(imageName: "", mainImageName: mainImage))
}

Segue from CollectionViewCell to Another View Controller Passing IndexPath

I'm trying to pass the indexPath of a cell tapped in a UICollectionView to another view controller. I can't seem to get the indexPath of what was selected and segue it to the next view controller
I get this error: "Could not cast value of type Post to PostCell"
View Controller #1:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let post = posts[indexPath.row]
if let cell = collectionView.dequeueReusableCellWithReuseIdentifier("PostCell", forIndexPath: indexPath) as? PostCell {
cell.configureCell(post)
}
return cell
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let selectedPost: Post!
selectedPost = posts[indexPath.row]
performSegueWithIdentifier("PostDetailVC", sender: selectedPost)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PostDetailVC" {
//Error here: Could not cast value of Post to PostCell
if let selectedIndex = self.collection.indexPathForCell(sender as! PostCell){
print(selectedIndex)
}
if let detailsVC = segue.destinationViewController as? PostDetailVC {
if let selectedPost = sender as? Post {
print(selectedIndex)
detailsVC.post = selectedPost
detailsVC.myId = self.myId!
detailsVC.indexNum = selectedIndex
}
}
}
}
View Controller #2:
var indexNum: NSIndexPath!
override func viewDidLoad() {
super.viewDidLoad()
print(indexNum)
}
You are passing a Post instance which doesn't match the expected PostCell instance.
I recommend to pass the index path
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("PostDetailVC", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PostDetailVC" {
guard let selectedIndexPath = sender as? NSIndexPath,
detailsVC = segue.destinationViewController as? PostDetailVC else { return }
print(selectedIndexPath)
let selectedPost = posts[selectedIndexPath.row]
detailsVC.post = selectedPost
detailsVC.myId = self.myId!
detailsVC.indexNum = selectedIndexPath
}
}
You are passing a Post and not a PostCell as sender. You don't need that anyway, as the collectionView keeps track of selected items.
Try this:
if let selectedIndex = self.collection.indexPathsForSelectedItems()?.first {
print(selectedIndex)
}
It's because you are giving argument which has type of Post and you are trying to cast it as PostCell. Which will not work.

Resources