how to pass data from cell to another ViewController - ios

#TusharMordiya Please check this image
I have created a tableView inside a CollectionView.The contents of the view are UIImage and a UILabel.I want to design the cell in which when I click on a cell the image and label must go to another ViewController.
import UIKit
class ExploreTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
#IBOutlet var collectionView: UICollectionView!
var namearr = ["images-1", "images-2", "images-3", "images-4", "images-5"]
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 132, height: 134)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = UIStoryboard(name: "DetailViewController", bundle: nil).instantiateViewController(withIdentifier:"DetailViewController") as? DetailViewController
vc?.name = namearr[indexPath.row]
vc?.img.image = UIImage(named: namearr[indexPath.row])
//self.navigationController?.pushViewController(vc, animated: true)
// showing error in here and while declaring object of viewcontroller
}
}

Please try this.
Add function for get top most view controller
extension UIApplication {
class func topViewController(_ viewController: UIViewController? = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.compactMap({$0 as? UIWindowScene})
.first?.windows
.filter({$0.isKeyWindow}).first?.rootViewController) -> UIViewController? {
if let nav = viewController as? UINavigationController {
return topViewController(nav.visibleViewController)
}
if let tab = viewController as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = viewController?.presentedViewController {
return topViewController(presented)
}
return viewController
}
}
Use this code in your didSelectItemAt method
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
if let vc = storyBoard.instantiateViewController(withIdentifier:"DetailViewController") as? DetailViewController {
vc.name = namearr[indexPath.row]
print("You tapped the cell\(indexPath) with car name \(namearr[indexPath.row]) ")
UIApplication.topViewController()?.navigationController?.pushViewController(vc, animated: true)
}
}
In your Detail Screen
class DetailViewController: UIViewController {
#IBOutlet var lbl: UILabel!
#IBOutlet var img: UIImageView!
var name = ""
override func viewDidLoad() {
super.viewDidLoad()
lbl.text = name
img.image = UIImage(named: name)
}
}

let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier:"DetailViewController") as? DetailViewController
change storyBoard name to Main

Related

want to add a collectionView inside tableView by downloading data from firebase to show . ios App Swift

want to add a UICollectionView inside UITableView by downloading data from firebase to show
Now I'm done with the interface part, but I'm stuck in the problem, can't bring data from firebase to show in the UICollectionView.
I can't run collectionView.reloadData() because the UICollectionView is different in class, how should I fix it?
func showImageRewardData(rewardID:String) {
let databaseRef = Database.database().reference().child("reward").child(rewardID).child("rewardImage")
databaseRef.observe(DataEventType.value, with: { (Snapshot) in
if Snapshot.childrenCount>0{
self.rewardDataArr.removeAll()
for rewardImage in Snapshot.children.allObjects as! [DataSnapshot]{
let rewardObject = rewardImage.value as? [String: AnyObject]
if(rewardObject?["imageURL"] != nil){
let imageUrl = rewardObject?["imageURL"]
let Data = rewardDetailClass(rewardImage: imageUrl as? String)
self.rewardDataArr.insert(Data, at: 0)
}
YOURVIEWCONTROLLER.SWIFT
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let CellIdentifier: String = "Cell_NotesList"
var cell: Cell_NotesList? = (tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as? Cell_NotesList)
if cell == nil {
let topLevelObjects: [Any] = Bundle.main.loadNibNamed("Cell_NotesList", owner: nil, options: nil)!
cell = (topLevelObjects[0] as? Cell_NotesList)
cell?.selectionStyle = .none
}
cell?.reloadCollectionView(arr: arrofofthumbImages)
return cell!
}
YourCell.SWIFT
class Cell_NotesList: UITableViewCell {
var imagesArr = NSMutableArray()
override func awakeFromNib() {
collectionView.register(UINib.init(nibName: "cell_ImageCollection", bundle: nil), forCellWithReuseIdentifier: "cell_ImageCollection")
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension Cell_NotesList : UICollectionViewDataSource {
func reloadCollectionView(arr:NSMutableArray) {
imagesArr = arr
collectionView.reloadData()
self.layoutIfNeeded()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell : cell_ImageCollection? = collectionView.dequeueReusableCell(withReuseIdentifier: "cell_ImageCollection", for: indexPath) as? cell_ImageCollection
//YOUR CODE HERE
return cell!
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
}
extension Cell_NotesList : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 120.0, height: 120.0)
}
}
extension UICollectionViewCell {
var indexPath: IndexPath? {
return (superview as? UICollectionView)?.indexPath(for: self)
}
}
In class that extends UICollectionView, put one setter method like
func setData(data: String){
// Update your cell view here like
Label.text = data
}

didSelectItemAt() is not loading my viewController

First viewController
import UIKit
class photosCollectionViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource {
#IBOutlet weak var photoCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
photoCollectionView.delegate = self
photoCollectionView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
var photosArray = PhotoClass(Name:["Dog","Cat","Lion","Tiger"])
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return photosArray.Name.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let photocell = photoCollectionView.dequeueReusableCell(withReuseIdentifier: "photosCell", for: indexPath) as! photoscollectionCell
//photocell.backgroundColor = UIColor.blue
photocell.cellImage.image = UIImage(named: photosArray.Name[indexPath.row])
photocell.cellLabel.text = photosArray.Name[indexPath.row]
return photocell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Something")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "photosDetails") as! detailsCollectionViewController
// vc.descriptionLabel.text = "Animals"
}
}
didSelectItemAt() is not loading my detailsCollectionViewController,but while i am selecting the cell it's calling .so where am i doing wrong ?
you can write this if you want to push :
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Something")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "photosDetails") as! detailsCollectionViewController
// vc.descriptionLabel.text = "Animals"
self.navigationController?.pushViewController(vc, animated: true)
}
It may helps to you.Thank you
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Something")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "photosDetails") as! detailsCollectionViewController
// vc.descriptionLabel.text = "Animals"
present(vc, animated: true)
}

Manually add delegate & datasource to UICollectionView of xib file

I put the UICollectionView on the UIView in the xib file.
UICollectionView is installed (GUI) in the xib file, and IBOutlet is connected.
In this case, how should we write delegate and dataSource?
(Conjecture: Perhaps, I have to write it manually as a code on my own)
Also, we could not attach Cell to UICollectionView in xib.
Does that mean i do not have to put it?
Collection.swift
//Collection.swift
import UIKit
class Home: UIView, UICollectionViewDelegate, UICollectionViewDataSource{
#IBOutlet weak var propCollectionView: UICollectionView!
let photos = ["sierra"] //Already put to AssetsFolder
//Just instance. plz do not care about this.
class func instance() -> Home {
return UINib(nibName: "Home", bundle: nil).instantiate(withOwner: self, options: nil)[0] as! Home
}
func initValue(){
propCollectionView.register(UINib(nibName: "PropCell", bundle: nil), forCellWithReuseIdentifier: "PropCell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = propCollectionView.dequeueReusableCell(withReuseIdentifier: "PropCell", for: indexPath) as! PropCell
let propImage = cell.contentView.viewWithTag(1) as! UIImageView
let img = UIImage(named: photos[indexPath.row])
propImage.image = img
return cell
}
}
PropCell.swift
//PropCell.swift
//yeah, nothing. plz don't care this too.
import UIKit
class PropCell: UICollectionViewCell {
override func awakeFromNib() {
super.awakeFromNib()
}
}
Xib of CollectionSwift
Xib of PropCell
(If you do not understand the meaning of the question, please comment.)
import UIKit
class Home: UIView, UICollectionViewDelegate, UICollectionViewDataSource{
#IBOutlet weak var propCollectionView: UICollectionView!
let photos = ["sierra"] //Already put to AssetsFolder
//Just instance. plz do not care about this.
class func instance() -> Home {
return UINib(nibName: "Home", bundle: nil).instantiate(withOwner: self, options: nil)[0] as! Home
}
func configureView() {
propCollectionView.delagate = self
propCollectionView.dataSource = self
}
func initValue(){
propCollectionView.register(UINib(nibName: "PropCell", bundle: nil), forCellWithReuseIdentifier: "PropCell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = propCollectionView.dequeueReusableCell(withReuseIdentifier: "PropCell", for: indexPath) as! PropCell
let propImage = cell.contentView.viewWithTag(1) as! UIImageView
let img = UIImage(named: photos[indexPath.row])
propImage.image = img
return cell
}
}
USES
let home = Home.instance()
home.configureView() //called configureView() with the home instance

swift pass images from collection view controller to another view controller

i have downloaded set of users photo from firebase and view it as collection view (instagram like)
but im trying to enlarge the photo clicked in another view controller using segue but its not working.
Any thoughts about my code:
class ProfileViewController: UIViewController{
var photoThumbnail: UIImage!
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection_cell", for: indexPath) as! ProfileCollectionViewCell
cell.imageCollection.downloadImage2(from: currPosts[indexPath.row].photoUrl)
cell.imageCollection.image = photoThumbnail
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
performSegue(withIdentifier: "photoViewSegue", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var destViewController : EnlargePhotoViewController = segue.destination as! EnlargePhotoViewController
destViewController.labelText = "test" //**** this works
destViewController.myImage = photoThumbnail //**** this doesnt work
}
}
and the collection view cell is:
class ProfileCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageCollection: UIImageView!
}
lastly the target viewController:
class EnlargePhotoViewController: UIViewController {
#IBOutlet weak var myLabel: UILabel!
#IBOutlet weak var enlargedPhoto: UIImageView!
var labelText = String()
var myImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
myLabel.text = labelText
enlargedPhoto.image = myImage
}
}
Try to change to this code:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! ProfileCollectionViewCell
photoThumbnail = cell.imageCollection.image
performSegue(withIdentifier: "photoViewSegue", sender: nil)
}
your only goal is to get the image of the selected cell, this can be done more efficiently. All you have to do is read/write to the cells imageView property, photoThumbnail is never set so always nil, just modify this
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection_cell", for: indexPath) as! ProfileCollectionViewCell
cell.imageCollection.downloadImage2(from: currPosts[indexPath.row].photoUrl)
//cell.imageCollection.image = photoThumbnail <-- No need of this
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// get the correct cell on select
if let cell = collectionView.cellForItem(at: indexPath) as! ProfileCollectionViewCell
{
photoThumbnail = cell.imageCollection.image <-- finally assign the imageview to image
performSegue(withIdentifier: "photoViewSegue", sender: self)
}
}
for safer retrieve the image, use like
override func viewDidLoad() {
super.viewDidLoad()
if let getImage = myImage
{
myLabel.text = labelText
enlargedPhoto.image = getImage
}
}
First View Controller
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == 0
{
let objstory = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
objstory.strd = imageView.image
_ = self.navigationController?.pushViewController(objstory, animated: true)
}
}
SecondViewController
var strd:UIImage!
#IBOutlet weak var imgprof: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imgprof.image = strd
// Do any additional setup after loading the view.
}
class ProfileViewController: UIViewController{
var photoThumbnail: UIImage!
var selectedPhotoURL: NSUrl!
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection_cell", for: indexPath) as! ProfileCollectionViewCell
cell.imageCollection.downloadImage2(from: currPosts[indexPath.row].photoUrl)
cell.imageCollection.image = photoThumbnail
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedPhotoURL = currPosts[indexPath.row].photoUrl
performSegue(withIdentifier: "photoViewSegue", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var destViewController : EnlargePhotoViewController = segue.destination as! EnlargePhotoViewController
destViewController.labelText = "test" //**** this works
//make image from selected url or pass url and download it in EnlargePhotoViewController
let downlodedImage = yourMethodToDownload(selectedPhotoURL)
destViewController.myImage = downlodedImage //**** this will work work
}
}

Swift - how to open another viewcontroller with CollectionViewCell inside UITableViewCell

I'm really new in iOS/Swift and i'm in a small project. In this project i have a UITableView inside ViewController. And i have another file custom CollectionViewCell in side UITableViewCell.
I want when user click a cell in collectionview it will open another ViewController and it get data from this collectionviewcell.
This is my uitableview swift file:
class IndexRow: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var names:[String] = ["Movie 1","Movie 2","Movie 3","Movie 4","Movie 5","Movie 6"]
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.registerClass(indexOneMovie.self, forCellWithReuseIdentifier: "onemovie")
let nib = UINib(nibName: "indexOneMovie",bundle: nil)
collectionView.registerNib(nib, forCellWithReuseIdentifier: "onemovie")
self.collectionView.backgroundColor = UIColor.clearColor()
self.collectionView.delegate = self
self.collectionView.dataSource = self
print("Hello")
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return names.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCellWithReuseIdentifier("onemovie", forIndexPath: indexPath) as! indexOneMovie
cell.poster.image = UIImage(named: "poster.jpg")
cell.name.text = names[indexPath.row]
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print(indexPath.item)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let itemsPerRow:CGFloat = 2
let hardCodedPadding:CGFloat = 0
let itemWidth = (collectionView.bounds.width / itemsPerRow) - hardCodedPadding
let itemHeight = collectionView.bounds.height - (hardCodedPadding)
return CGSize(width: itemWidth, height: itemHeight)
}
How i can do it?
ok i have recently implemented the same in my app these are the links where i refered initially -
https://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell-in-swift/
http://www.thorntech.com/2015/08/want-your-swift-app-to-scroll-in-two-directions-like-netflix-heres-how/
you are making uicollectionview delegate confirms to uitableview cell so you cannot present or push to other view controller.
here is my code hope it will help you
homeController.swift which contains uitableview
extension HomeController : UITableViewDelegate {
func tableView(tableView: UITableView,willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
//here setting the uitableview cell contains collectionview delgate conform to viewcontroller
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row, andForSection: indexPath.section)
tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}
func tableView(tableView: UITableView,didEndDisplayingCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
}
extension HomeController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
let element : [CollectionViewElement] = self.returnCollectionViewElementAccordingToIndex(collectionView.tag)
return element.count
}
func collectionView(collectionView: UICollectionView,cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell",forIndexPath: indexPath) as! horizontalCollectionViewCell
let element : [CollectionViewElement] = self.returnCollectionViewElementAccordingToIndex(collectionView.tag)
cell.cellTitleLabel.text = element[indexPath.row].videos.title
cell.cellGenerLabel.text = element[indexPath.row].videos.gener
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
print("collectionviewtag:\(collectionView.tag) + indexpathrow:\(indexPath.row)")
//from here you can do push or present to anyview controller
// collectionviewtag is tableView cell row value and indexpathrow return collectionView cell row value.
}
}
TableViewCell.swift :custom UITableViewCell which contains collectionView
class TableViewCell: UITableViewCell {
#IBOutlet private weak var collectionView: UICollectionView!
#IBOutlet weak var cellLabel: UILabel!
#IBOutlet weak var cellButton: UIButton!
#IBAction func CellButtonActionTry(sender: UIButton) {
print("Dude \(cellButton.tag)")
}
var collectionViewOffset: CGFloat {
get {
return collectionView.contentOffset.x
}
set {
collectionView.contentOffset.x = newValue
}
}
func setCollectionViewDataSourceDelegate<D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>>
(dataSourceDelegate: D, forRow row: Int , andForSection section : Int) {
collectionView.delegate = dataSourceDelegate
collectionView.dataSource = dataSourceDelegate
collectionView.tag = row // tableView indexpathrow equals cell tag
collectionView.reloadData()
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
You can do it like this :
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print(indexPath.item)
let name = names[indexPath.item]
let distinationViewController = DistinationViewController()
distinationViewController.name = name
if let navVC: UINavigationController = UIApplication.sharedApplication().keyWindow?.rootViewController as? UINavigationController {
navVC.pushViewController(distinationViewController, animated: true)
}
}
This is just a way to do it i dont know which view you want to push or what your names array contains so kindly change those things accordingly.
get root navigationcontroller from uiapplication and perform push on it.

Resources