My aim is to perform segue from collection view cells to view controller. In the next view controller I have statement
let selectedCar = CarViewController()
if selectedCar.selectedMaker == "a"
I know the way to perform segue with additional class, but do not know how to perform with collection view. I used indexPath with if else statements.
Segue name is "toModels"
class CarsViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
public var selectedMaker = ""
#IBOutlet weak var collectionView: UICollectionView!
let mainMenu = ["a","b"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return mainMenu.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCell", for: indexPath) as! CustomCollectionViewCell
cell.imageCell.image = UIImage(named: mainMenu[indexPath.row])
cell.labelCell.text = mainMenu[indexPath.row].capitalized
return cell
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
performSegue(withIdentifier: "toModels", sender: selectedMaker)
if indexPath == [0, 0]
{
selectedMaker = "a"
print("a")
}
else if indexPath == [0, 1]
{
selectedMaker = "b"
print("b")
}
Try this EDIT
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.item == 0
{
selectedMaker = "a"
print("a")
}
else if indexPath.item == 1
{
selectedMaker = "b"
print("b")
}
performSegue(withIdentifier: "toModels", sender: selectedMaker)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if (segue.identifier == "toModels")
{
let objVC = segue.destination as! YOUR_NEXT_VIEWCONTROLLER
objVC.strMaker = sender as? String ?? ""
}
}
Define in YOUR_NEXT_VIEWCONTROLLER
public var strMaker = ""
Related
class ViewController: UICollectionViewController {
var selectedRow : Int?
let data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier : "MyCell")
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! CollectionViewCell
cell.Label.text = String(data[indexPath.row])
return cell
}}
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var Label: UILabel!
#IBOutlet weak var button: UIButton!
#IBAction func buttonPressed(_ sender: UIButton) {
if Label.textColor == .red{
Label.textColor = .black
} else if Label.textColor == .black{
Label.textColor = .red
}}
public override func awakeFromNib() {
super.awakeFromNib()}}
I want to recognize whether cell is selected or not.
but I really don't know where in I have to use what function.
many people are saying using setSelected function but I think there is no such function.
I'm beginner so I don't know well.
what I want to is make "if I select one of that number then that cell's textColor turn red.
and then I select another cell. then that cell's textColor turn red and original one turn black again."
what function I have to use and where I have to use function.
There are so many ways to do it, I prefer the below way.
Change: 1
You need to add buttonPressed method into UIViewController
Change: 2
You need to add code for UILabel text color into cellForItemAt.
Full code:
class ViewController: UICollectionViewController {
var selectedRow : Int?
let data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier : "MyCell")
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! CollectionViewCell
cell.button.tag = indexPath.item
cell.button.addTarget(self, action:#selector(buttonPressed(_:)) , for: .touchUpInside)
cell.Label.text = String(data[indexPath.row])
if selectedRow == indexPath.item{
cell.Label.textColor = .black
}else{
cell.Label.textColor = .red
}
return cell
}
#objc func buttonPressed(_ sender: UIButton) {
if selectedRow == sender.tag{
selectedRow = nil
}else{
selectedRow = sender.tag
}
collectionView.reloadData()
}
}
You should overload UICollectionViewDelegate's collectionView(_:didSelectItemAt:) method in your ViewController class. It gets called whenever user taps on a cell.
I open a second view that displays a series of images in a collection, Can I press on an image of the collection for use image in the first view?
//from first ViewController
#IBAction func backgroundButton(_ sender: UIButton) {
}
//SecondViewController
class SecondViewController: UIViewController {
#IBAction func returnHome(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
......
extension SecondViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width/2.5, height: collectionView.frame.width/2)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
cell.data = self.data[indexPath.item]
return cell
}
}
class CustomCell: UICollectionViewCell {
var data: CustomData? {
didSet {
guard let data = data else { return }
bg.image = data.backgroundImage
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
bg.isUserInteractionEnabled = true
bg.addGestureRecognizer(tapGestureRecognizer)
}
}
#objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer) {
let tappedImage = tapGestureRecognizer.view as! UIImageView
self.addSubview(tappedImage)
}
// When I tap on Image in this case addSubview but I want use that image in First View Controller
I'm running into a problem while working on a simple project. This app essentially just displays a collection of images and when I tap one of the images, it is suppose to transition into a new view controller and display the name of the image on a label.
I am new at Swift. Is it something to do with the indexPath that I used in the function to fill the collection view? I tried to see if I could get the indexPath and then pass that into the images array to get the name and send the name in the second view controller but it comes up nil. Any help would be greatly appreciated
This is my CollectionViewController
class ImagePickerViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet var collectionView: UICollectionView!
var images = Data()
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as? CollectionViewCell {
cell.imageView.image = UIImage(named: "\(images.images[indexPath.item])")
return cell
}
return UICollectionViewCell()
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dest = segue.destination as? FeedPickerViewController{
if segue.identifier == "detailViewController_segue"{
let cell = sender as! CollectionViewCell
let indexPath = self.collectionView.indexPath(for: cell)
let imgName = images.images[indexPath!.item]
dest.imgName = imgName
}
}
}
}
This is theViewController that I am segueing to
class DetailViewController: UIViewController {
var imgName: String!
#IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label.text = "Posting Image: \(imgName)"
}
}
and this is the data class
class Data {
let images = ["bear", "bird", "bridge",
"cabin"]
}
You should remember indexPath which is selected cell's
You can use collectionView:didSelectItemAtIndexPath: to retrieve selected cell's indexPath
selectedIndexPath = indexPath
then pass the data of the selected using selected IndexPath to destination view controller
dest.imageName = images.images[selectedIndexPath!.item]
Try this one
class ImagePickerViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet var collectionView: UICollectionView!
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return DataImage.images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as? CollectionViewCell {
cell.imageView.image = UIImage(named: DataImage.images[indexPath.item])
return cell
}
return UICollectionViewCell()
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dest = segue.destination as? FeedPickerViewController{
if segue.identifier == "detailViewController_segue"{
let cell = sender as! CollectionViewCell
let indexPath = self.collectionView.indexPath(for: cell)
let imgName = DataImage.images[indexPath!.item]
dest.imgName = imgName
}
}
}
}
class DetailViewController: UIViewController {
var imgName: String!
#IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label.text = "Posting Image: " + imgName
}
}
Use struct instead of Class
struct DataImage {
static var images = ["bear", "bird", "bridge", "cabin"]
}
I am trying to change my "selected" variable so that when a character cell in the collectionview is selected, the view controller can be dismissed when the user clicks the button (sendTapped). However, it is not changing the variable value back to false when the user deselects a cell, so the view controller is dismissed when the user deselects a cell and then clicks the button.
class CharactersViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
let characters = [...]
let characterImages = [...]
var selectedIndex: Int?
var selected = false
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func sendTapped(_ sender: Any) {
***if selected {
self.dismiss(animated: true, completion: nil)
let initialViewController = UIStoryboard.initialViewController(for: .main)
self.view.window?.rootViewController = initialViewController
self.view.window?.makeKeyAndVisible()
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.characters.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CharacterViewCell
cell.characterImage.image = UIImage(named: characterImages[indexPath.row])
if selectedIndex == indexPath.row {
cell.contentView.layer.borderColor = UIColor.yellow.cgColor
cell.contentView.layer.borderWidth = 2.0
}else{
cell.contentView.layer.borderColor = UIColor.clear.cgColor
cell.contentView.layer.borderWidth = 1.0
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let character = characters[indexPath.row]
***selected = true
selectedIndex = selectedIndex == indexPath.row ? nil : indexPath.row
ProfileService.updateChild(child: "char", childVal: character)
collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
***selected = false
}
}
i have a collection view which has an array of images. when i press on any of the images it will open that image in full screen in another class. i tried to add swipe gesture recognizer in the second view controller but i dont know how to access the array that is in the first view controller.
This is my first view controller that displays the images in collection view
class sowrController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource{
#IBOutlet weak var collectionView: UICollectionView!
var albums = [AlbumModel]()
let db : DBHelperMo2lfat = DBHelperMo2lfat()
var selectedIndex : Int = -1
var posts : Post!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
self.albums.removeAll()
self.albums.append(contentsOf: self.db.fetchAllImages())
self.collectionView.reloadData()
DataService.ds.REF_POSTS_SOWR.observe(.value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
self.albums.removeAll()
for snap in snapshot {
print ("SNAP: \(snap)")
if let postDict = snap.value as? Dictionary<String, AnyObject>{
let album : AlbumModel = AlbumModel(id: postDict["id"] as! String, name: postDict["image_name"] as! String, path: postDict["image_path"] as! String, url: postDict["image_path"] as! String, localPath: "")
if let items = snap.children.allObjects as? [FIRDataSnapshot] {
for itemSnap in items {
if let albumSnap = itemSnap.value as? Dictionary<String, AnyObject> {
album.childAlbums.append(AlbumModel(id: albumSnap["id"] as! String, name: albumSnap["image_name"] as! String, path: albumSnap["image_path"] as! String, url: albumSnap["image_path"] as! String, localPath: ""))
}
}
}
self.albums.append(album)
}
}
self.collectionView.reloadData()
}
})
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.albums.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.BookCellReuseIdentifier, for: indexPath) as? collectionViewCellSowr {
let album = albums[indexPath.item]
cell.initWithAlbumModel(album: album)
return cell
}else {
return collectionViewCellSowr()
}
}
private struct Constants {
static let BookCellReuseIdentifier = "cell"
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.selectedIndex = indexPath.row
self.performSegue(withIdentifier: "showAlbum", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "showAlbum"
{
let vc = segue.destination as! imageFullScreen
vc.images = self.albums[self.selectedIndex]
}
}
This is the second view controller that makes the images go in full screen
class imageFullScreen: UIViewController{
var images : AlbumModel?
let db : DBHelperMo2lfat = DBHelperMo2lfat()
#IBAction func pictureSwipe(_ sender: Any) {
}
#IBOutlet weak var caption: UILabel!
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.caption.text = images?.imageName
let url = URL(string: (images?.imagePath)!)
self.imageView.sd_setImage(with: url, placeholderImage: nil, options: [.progressiveDownload,.retryFailed])
}
EDIT:
Ok, so here is a collection view controller that creates image view as a subview and responding to swipe gestures. Please make sure you have two images "Image" and "Image-1" in your assets folder.
//
// CollectionViewController.swift
// test
//
// Created by Yonatan Vainer on 05/08/2017.
// Copyright © 2017 Sensus Healthcare LLC. All rights reserved.
//
import UIKit
private let reuseIdentifier = "id"
class CollectionViewController: UICollectionViewController {
var imageView = UIImageView(frame: CGRect(x: 0, y: 100, width: 300, height: 300))
var index = 0;
let names = ["Image","Image-1"]
override func viewDidLoad() {
super.viewDidLoad()
//For left swipe
let left = UISwipeGestureRecognizer(target: self, action: #selector(self.goLeft(_:)))
left.direction = .left
imageView.addGestureRecognizer(left)
//For right swipe
let right = UISwipeGestureRecognizer(target: self, action: #selector(self.goRight(_:)))
right.direction = .right
imageView.addGestureRecognizer(right)
imageView.isUserInteractionEnabled = true
self.view.addSubview(imageView)
self.view.layoutSubviews()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Register cell classes
// Do any additional setup after loading the view.
}
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 prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
// MARK: UICollectionViewDataSource
override func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return names.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
// Configure the cell
let nail = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
nail.image = UIImage(named: names[indexPath.row])
cell.backgroundView = nail
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
imageView.image = UIImage(named: names[indexPath.row])
index = indexPath.row
}
func goLeft(_ gesture: UISwipeGestureRecognizer){
index += 1
if index<0{
index = 0
}
imageView.image = UIImage(named: names[index])
}
func goRight(_ gesture: UISwipeGestureRecognizer){
index -= 1
if index>1{
index = 1
}
imageView.image = UIImage(named: names[index])
}
// MARK: UICollectionViewDelegate
/*
// Uncomment this method to specify if the specified item should be highlighted during tracking
override func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
return true
}
*/
/*
// Uncomment this method to specify if the specified item should be selected
override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
return true
}
*/
/*
// Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item
override func collectionView(_ collectionView: UICollectionView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool {
return false
}
override func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
return false
}
override func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) {
}
*/
}
==================================================================
In storyboard, click on your collection view and embed navigation controller.
This will add a top bar with the back button.
Attached image.
I'm not sure I completely understand your question, because I don't understand what the array has to do with a gesture recognizer, but if you are just trying to access the array from the previous ViewController, this should work if you have a navigation controller :
let vcIndex = self.navigationController?.viewControllers.index(where: { (viewController) -> Bool in
if let _ = viewController as? sowrController {
return true
}
return false
})
let prevVC = self.navigationController?.viewControllers[vcIndex!] as! sowrController
let albums:[AlbumModel] = prevVC.albums