Cell not display after scroll in collection view - swift 2.1 - ios

Main Controller
class MainController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionView: UICollectionView!
let reUseCellName = "imgCell"
var counter = 1
override func viewDidLoad() {
super.viewDidLoad()
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reUseCellName, forIndexPath:indexPath) as! CellClass
cell.imageView.image = UIImage(named: "\(counter)")
cell.imgName = counter
counter++
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let newView = segue.destinationViewController as! showImage
let cell = sender as! CellClass
newView.imgNo = cell.imgName
}

I think its the way how your using them, try to define an array with images:
var arrayOfImages = ["1","2","3","4"]
And use it in cellForItemAtIndexPath :
cell.imageView.image = UIImage(named: arrayOfImages[indexPath.row])
Be sure to connect DataSoruce and Delegate for collectionView from connection inspector into your view controller to have the data loaded, and be sure to place the right image names.

Use the following code . the reason for the image not being displayed is the you have not mentioned the file extension with the image as jpg or png ... your counter value is "1" so app cannnot load the image name 1 without extension png or jpg
Use this code :
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reUseCellName, forIndexPath:indexPath) as! CellClass
cell.imageView.image = UIImage(named: "Complete image name with .png/.jpg")
cell.imgName = counter
counter++
return cell
}

Related

Swift - get UIImage from UIColllectionViewCell

I have a collectionView where each cell contains a UIImage and an empty UIButton . How do I the picture that the user tapped on?
class ImageCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout{
#IBOutlet weak var imageCollectionView: UICollectionView!
let images: [UIImage] = [
UIImage(named: "beerImage")!,
UIImage(named: "christmasImage")!,
UIImage(named: "goalImage")!,
UIImage(named: "travelImage")!,
UIImage(named: "rollerImage")!,
UIImage(named: "giftImage")!,
UIImage(named: "shirtImage")!,
UIImage(named: "dressImage")!,
]
let columnLayout = FlowLayout(
itemSize: CGSize(width: 150, height: 150),
minimumInteritemSpacing: 30,
minimumLineSpacing: 10,
sectionInset: UIEdgeInsets(top: 20, left: 20, bottom: 10, right: 20)
)
var colViewWidth: CGFloat = 0.0
override func viewDidLoad() {
self.imageCollectionView.collectionViewLayout = columnLayout
super.viewDidLoad()
imageCollectionView.dataSource = self
imageCollectionView.delegate = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCollectionViewCell
cell.imageView.image = images[indexPath.item]
cell.layer.cornerRadius = 2
return cell
}
#IBAction func imageButtonTapped(_ sender: Any) {
print("tapped")
}
#IBAction func closeButtonTapped(_ sender: Any) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let HomeViewController = storyBoard.instantiateViewController(withIdentifier: "HomeVC") as! ExampleViewController
self.present(HomeViewController, animated: false, completion: nil)
}
}
Update
In the end I would like to pass that image to another ViewController. I tried it this way but the picture isn't showing up in the other ViewController:
ViewControllerA
var tappedImage = UIImage()
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
tappedImage = images[indexPath.row]
}
var showPopUpView = true
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print(showPopUpView)
var vc = segue.destination as! ExampleViewController
vc.pickedImage = self.tappedImage
vc.ShowPopUpView = self.showPopUpView
}
ViewControllerB
var pickedImage = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
imagePreview.image = pickedImage
Duo to the conversation in comments:
The order of actions should be:
User clicks on a cell
Fetching the image according to the indexPath of the selected cell
Setting it in a temporary variable (tappedImage)
Performing segue
Pass the temporary image to the destination's temporary image (pickedImage)
Loading the destination's view
Show the image.
Seems like you are missing one of these steps ( probably the step 3, since you are not calling performSegue in the ...didSelectItemAt indexPath... and it maybe not getting called at all! Try print something there and check if it's true )
Or you may disorder the flow ( probably you setting the image after destination's View is loaded and the result is to not seeing that. )
Debug:
Try printing all variables you have access (e.g tappedImage, pickedImage, images[indexPath.row], etc.) on each these 7 states and see where is the issue and where are you loosing the selected image reference
Possible issue
You are not using ...didSelectItemAt indexPath... to performSegue, Probably you have a UIButton for that, so the button is blocking the cell from getting selected.
You could do something like this
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
imageToPass = images[indexPath.row]
}
Edit:
As far as passing that image to your next view controller, one possible way is to add a property to your first and second view controllers for the image, set that image in your didSelectItemAt call, then pass it using prepare(for segue: UIStoryboardSegue, sender: Any?)
let imageToPass: UIImage?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "identifier name here" {
// Get the new view controller using segue.destination.
if let destVC = segue.destination as? SecondViewController {
// Pass the selected object to the new view controller.
destVC.image = imageToPass
}
}
}
Try this
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let image = images[indexPath.row]
//Result image
}
(or)
If you want to get image from button tap (Not recommended)
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCollectionViewCell
cell.imageView.image = images[indexPath.item]
cell.layer.cornerRadius = 2
//Replace your button
cell.yourButton.tag = indexPath.row
cell.yourButton.addTarget(self, action: #selector(self.imageButtonTapped(_:)), for: .touchUpInside)
}
in button action
func imageButtonTapped(_ sender: UIButton) {
let image = images[sender.tag]
//Result image
}

Get Switch State from specific cell

I am working on a iOS app that has two ViewControllers. The first is a TableView which creates a row for each index in a array. Each cell of this TableView shows the content in the array corresponding to the index and has a switch. The second ViewController has an image and a label and they are supposed to change depending the switch state. So, how can I get the switch state from a specific cell?
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var state_label: UILabel!
#IBOutlet weak var descr_label: UILabel!
#IBOutlet weak var myimg: UIImageView!
let arr: [String] = ["Text1","Text2", "Text3", "Text4"]
var switch_isOn = false
override func viewDidLoad() {
super.viewDidLoad()
if(switch_isOn == false){
myimg?.image = UIImage(named: "img1")
}else{
myimg?.image = UIImage(named: "img2")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
cell.textLabel?.text = arr[indexPath.row]
let mySwitch = UISwitch()
cell.accessoryView = mySwitch
mySwitch.tag = 1001
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let segueIdentifier: String
segueIdentifier = "segue"
// Get the selected Cell and Iterate through it's subviews to find the switch using the tag
let cell = tableView.cellForRow(at: indexPath)
//Get the Cell Text
print("\(cell?.textLabel?.text ?? "")")
// Iterate through subviews of Cell
for v in cell?.subviews ?? [] {
// If a view found with tag == 1001 then it's the switch view because we had assigned 1001 to the switch view
if v.tag == 1001 {
// One last check we cast the view to UISwitch if it succeed then it's the switch view
if let mySwitch = v as? UISwitch {
if(mySwitch.isOn == true){
descr_label?.text = "\(cell?.textLabel?.text ?? "")"
print("The cell has the Switch On")
switch_isOn = true
}else{
descr_label?.text = "\(cell?.textLabel?.text ?? "")"
switch_isOn = false
print("The cell has the Switch Off")
}
}
}
}
self.performSegue(withIdentifier: segueIdentifier, sender: self)
}
}
Using the accessory view for the switch seems to be an easy solution but it's very cumbersome to access the view. Something like for v in cell?.subviews ?? [] and dealing with tags is horrible.
A better more efficient solution is a custom cell class.
In Interface Builder set the style of the cell to custom and drag an UILabel and an UISwitch into the canvas. Set the class of the cell to TableViewCell.
Add a new CocoaTouch class TableViewCell as subclass of UITableViewCell. You need two IBOutlets, one IBAction and a callback variable. The callback is important to keep the state of the switch in the model. Connect the outlets and the action in IB.
class TableViewCell: UITableViewCell {
#IBOutlet weak var switcher : UISwitch!
#IBOutlet weak var label : UILabel!
var callback : ((Bool)->())?
#IBAction func switchChanged(_ sender : UISwitch) {
callback?(sender.isOn)
}
}
Create a data source model containing the text and the state of the switch
struct Item {
var text : String
var isSelected : Bool
init(text : String, isSelected : Bool = false {
self.text = text
self.isSelected = isSelected
}
}
Declare the data source array
var arr : [Item] = [Item(text: "Text1"), Item(text: "Text2"), Item(text: "Text3"), Item(text: "Text4")]
Replace cellForRow with
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
let item = arr[indexPath.row]
cell.label.text = item.text
cell.switcher.isOn = item.isSelected
// the callback updates the model and is called when the value of the switch changes
cell.callback = { newValue in
item.isSelected = newValue
}
return cell
}
Replace didSelectRow with (yes, it's only one line, it passes the index path as sender parameter)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "segue", sender: indexPath)
}
Finally Implement prepare(for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let viewController = segue.destination as! ViewController // the class of the second view controller
// get the current index path
let indexPath = sender as! IndexPath
let item = arr[indexPath.row]
// get the state of the switch from the model, not from the view
let isSelected = item.isSelected
// do something with `isSelected`
}
}
}
In order to achieve what you want properly, you're going to want to set up a custom cell.
An example of this is below, and assumes a Storyboard/XIB UI:
import UIKit
class SwitchTableViewCell: UITableViewCell {
#IBOutlet weak var textLabel: UILabel!
#IBOutlet weak var contentSwitch: UISwitch!
// So that we can identify the cell in our table view controller.
static let identifier: String {
return String(describing: type(of: self))
}
}
in order to use this with your table view. you will have to register the cell for use in SwitchTableViewController.viewDidLoad():
tableView.register(SwitchTableViewCell.self, forCellReuseIdentifier: SwitchTableViewCell.identifier)
Next, you're going to want to modify cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(SwitchTableViewCell.identifier, forIndexPath: indexPath) as! SwitchTableViewCell
cell.textLabel?.text = arr[indexPath.row]
// cell.contentSwitch will be setup as an outlet via Storyboard / XIB.
return cell
}
after that's done, go ahead and add a variable to SwitchTableViewController:
fileprivate var selectedState: UIControl.State?
And update didSelectRowAt to store the state from the cell:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! SwitchTableViewCell
selectedState = cell.contentSwitch.state
segueIdentifier = "segue" // probably want a more meaningful segue name here.
self.performSegue(withIdentifier: segueIdentifier, sender: self)
}
finally, override prepare(for:sender:):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
if let vc = segue.destination as? ContentViewController { // cast accordingly, 'ContentViewController' is placeholder
// pass the state to the destination view controller
vc.state = selectedState
selectedState = nil
}
}
}
and that's you done!
There are many ways to read the state of a switch from a cell. You can create a custom cell class and access that using IBOutlets and even you can use delegates to get back from the Custom Cell class back to your View Controller. If you're using this code for learning purposes it's Ok to use and add any types of Controls to the cell like this but in real project you might try Custom cells.
See the commented areas in the code
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var myimg: UIImageView!
var arr: [String] = ["bla", "blablabla", "blabla"]
override func viewDidLoad() {
super.viewDidLoad()
myimg?.image = UIImage(named: "Image1")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default,
reuseIdentifier: "cell")
cell.textLabel?.text = arr[indexPath.row]
let mySwitch = UISwitch()
// Add a tag to your switch so later on you can access the switch using this tag
mySwitch.tag = 1001
cell.accessoryView = mySwitch
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
segueIdentifier = "segue"
// Get the selected Cell and Iterate through it's subviews to find the switch using the tag
let cell = tableView.cellForRow(at: indexPath)
// Iterate through subviews of Cell
for v in cell?.subviews ?? [] {
// If a view found with tag == 1001 then it's the switch view because we had assigned 1001 to the switch view
if v.tag == 1001 {
// One last check we cast the view to UISwitch if it succeed then it's the switch view
if let mySwitch = v as? UISwitch {
// Here you can get the state of the switch
let switchState = mySwitch.state
}
}
}
self.performSegue(withIdentifier: segueIdentifier, sender: self)
}
}
As I said this is not the best way to add and read views using tags but still good to know that you can
Edit:
Here is the complete solution for your project to work. You already have a ViewController but you don't have a DetailViewController to which you want to segue
View Controller Code
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let rooms: [String] = ["Kitchen","Living Room", "Master's Bedroom", "Guest's Bedroom"]
let segueIdentifier = "segueIdentifier"
var switch_isOn = false
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return rooms.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
cell.textLabel?.text = rooms[indexPath.row]
let mySwitch = UISwitch()
cell.accessoryView = mySwitch
mySwitch.tag = 1001
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Get the selected Cell and Iterate through it's subviews to find the switch using the tag
let cell = tableView.cellForRow(at: indexPath)
// Iterate through subviews of Cell
for v in cell?.subviews ?? [] {
// If a view found with tag == 1001 then it's the switch view because we had assigned 1001 to the switch view
if v.tag == 1001 {
// One last check we cast the view to UISwitch if it succeed then it's the switch view
if let mySwitch = v as? UISwitch {
// Assign the current state of the switch to switch_isOn variable
self.switch_isOn = mySwitch.isOn
}
}
}
self.performSegue(withIdentifier: segueIdentifier, sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == segueIdentifier {
if let detailViewController = segue.destination as? DetailViewController {
// used guard let to be on safe side
guard let indexPath = sender as? IndexPath else { return }
// pass in the data needs to the detail view controller
detailViewController.descr = rooms[indexPath.row]
detailViewController.isOn = switch_isOn
}
}
}
}
Detail View Controller Code
import UIKit
class DetailViewController: UIViewController {
#IBOutlet weak var descr_label: UILabel!
#IBOutlet weak var state_label: UILabel!
#IBOutlet weak var myImageView: UIImageView!
var descr = ""
var isOn = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
descr_label.text = descr
// for UIImage you can use UIImage(named: "on_image") but i have used the imageLiteral which is pics directly the image from xcassets
myImageView.image = isOn ? #imageLiteral(resourceName: "on_image") : #imageLiteral(resourceName: "off_image")
state_label.text = isOn ? "Switch is ON" : "Switch is Off"
}
}
Example Project download here

Use core data to populate detail view after selection from UICollectionView

I have a question that is very similar to the one found here, only I'm coding in Swift 2.0 (their question/answer is Objective-C), and my case is slightly different.
I have a UICollectionView that is essentially a contact list that pulls from core data. When the user selects a person (or an item within the UICollectionView), I want to present a detail view of the contact. I have that view/segue created and hooked up within the Storyboard, but I'm having trouble passing the selected item to the detail view ViewController so that it knows what data to query from core data.
Here is a snippet of my code with descriptions on each:
First, on my "FamilyCollectionViewController" I have the following viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Family")
fetchRequest.returnsObjectsAsFaults = false
do {
let results = try context.executeFetchRequest(fetchRequest)
userNames = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
Here is the cellForItemAtIndexPath method from the same view controller:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! FamilyCollectionViewCell
let person = userNames[indexPath.row]
cell.familyName!.text = person.valueForKey("name") as? String
print(userNames)
return cell
}
And here is the current didSelectItemAtIndexPath method (this may be where my problem is at, in combination with the prepareForSegue method):
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let selectedPerson = userNames[indexPath.row]
print(selectedPerson)
let selectedName = selectedPerson.valueForKey("name") as? String
let selectedNumber = selectedPerson.valueForKey("phone") as? String
let selectedEmail = selectedPerson.valueForKey("email") as? String
print(selectedName)
}
I attempted to create something similar to the answer as provided in the aforementioned linked question, but it is so laden with errors its not useful at all (the way I created it that is). I've passed data before from other views (using the prepareForSegue method), but the nuance of it now being from a UICollectionView and more, using core data, I'm left stumped. Any support is greatly appreciated.
Here's a complete example.
The contents of ViewController.swift
class ViewController: UICollectionViewController
{
var selectedIndex: Int!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ReuseID", forIndexPath: indexPath) as! CellCollectionViewCell
cell.contentView.backgroundColor = UIColor.whiteColor()
cell.label.text = "\(indexPath.row)"
return cell
}
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedIndex = indexPath.item
performSegueWithIdentifier("OtherSegueID", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "OtherSegueID" {
let otherViewController = segue.destinationViewController as! OtherViewController
otherViewController.selectedIndex = selectedIndex
}
}
}
The contents of CellCollectionViewCell.swift
class CellCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var label: UILabel!
}
The contents of OtherViewController.swift
class OtherViewController: UIViewController {
var selectedIndex: Int!
override func viewDidLoad() {
super.viewDidLoad()
title = String(selectedIndex)
}
}

Collection view shows cells as selected at scrolling that haven't been selected

In my CollectionView I want the user to select cells. If a cell is selected, an image should appear and the label should disappear. The User should also be able do deselect the cell again and then selecting it again (the selecting after deselecting doesn't work at the moment).
The text for the labels comes from an array and is shown properly.
But when selecting a cell, and then scrolling other cells are selected to. When scrolling up back again randomly other cells a selected that have never been touched. I think it has to do something with the reuse of the cell so I already added a prepareForReuse Method in the Class of the cell.
I also want to store which cells were selected when the user closes the app and show them as selected when he opens it up again.
A further problem is, that I want it only to be possible to select a cell, when a certain other cell is also selected. What is the best way to do this?
class CollectionViewController: UICollectionViewController {
var array:[String] = []
var selectedIndexes:NSMutableDictionary = NSMutableDictionary()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
doors = ["1","2","3"]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return array.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:MyCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! MyCollectionViewCell
var Label = cell.viewWithTag(1) as! UILabel
Label.text = array[indexPath.row]
let keystring = String(format:"%i", indexPath.row)
if (self.selectedIndexes[keystring] != nil) {
cell.myLabel.hidden = true
cell.myImageView.image = UIImage(named:"1")!
}
else {
}
return cell
}
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let keystring = String(format:"%i", indexPath.row)
if (self.selectedIndexes[keystring] != nil) {
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCollectionViewCell
cell.myLabel.hidden = false
cell.myImageView.image = nil
}
else {
selectedIndexes.setObject(keystring, forKey: keystring)
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCollectionViewCell
cell.myLabel.hidden = true
cell.myImageView.image = UIImage(named:"1")!
}
The class of the CollectionViewCell:
class MyCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var myLabel: UILabel!
#IBOutlet weak var myImageView: UIImageView!
override func prepareForReuse() {
super.prepareForReuse()
self.myImageView.image = nil
self.myLabel.hidden = false
The cells are reused (which greatly optimises table scrolling speed, etc), and as you describe that is your "problem".
All you have to do is to "reinitialise" the text and labels, etc on the cells overtime they are loaded. The best thing is to have your cell content in an object and to have those object in an array. When the cell i loaded, you then set the values according to the values in the object in the array using cellForRowAtIndexPath (usually indexPath.row in the default implementation)

How to link two collection view that are connected to each other?

I am getting multiple images from image picker save it into two collection view and make a view like this.
As you see,there was two collection which link to each other.Like when I tapped the second image at second collection view,the first collection view show the tapped image of second collection view.So,how to i link two collection view that are connected to each other.That was detail image selection view after I picked muliple images from gallery or camera.
Is this possible?
I will be very happy if somebody can give me a hand. :)
TODO NEXT : When I got that,I will going to add delete button at each image at second collection view.And add image "Add Button" after "img_4" for making user add more images into these two uicollection view.
When you select any item into second collection view you can show same image into first collection view this way:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if collectionView == self.collectionView2{
collectionView1.scrollToItemAtIndexPath(indexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
}
}
Below is complete example code for multiple collection views:
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var collectionView1: UICollectionView!
#IBOutlet weak var collectionView2: UICollectionView!
let collectionViewAIdentifier = "CollectionViewACell"
let collectionViewBIdentifier = "CollectionViewBCell"
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [UIImage(named: "1.jpg")!, UIImage(named: "2.jpg")!, UIImage(named: "3.jpg")!, UIImage(named: "4.jpg")!, UIImage(named: "5.jpg")!, UIImage(named: "6.jpg")!, UIImage(named: "7.jpg")!, UIImage(named: "8.jpg")!, UIImage(named: "9.jpg")!, UIImage(named: "10.jpg")!, UIImage(named: "11.jpg")!, UIImage(named: "12.jpg")!, UIImage(named: "13.jpg")!]
print(imageArray)
collectionView1.delegate = self
collectionView2.delegate = self
collectionView1.dataSource = self
collectionView2.dataSource = self
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
if collectionView == self.collectionView1 {
let cellA = collectionView1.dequeueReusableCellWithReuseIdentifier(collectionViewAIdentifier, forIndexPath: indexPath) as! CollectionViewCell1
cellA.imageV.image = imageArray[indexPath.row]
return cellA
}
else {
let cellB = collectionView2.dequeueReusableCellWithReuseIdentifier(collectionViewBIdentifier, forIndexPath: indexPath) as! CollectionViewCell2
cellB.imageV.image = imageArray[indexPath.row]
return cellB
}
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if collectionView == self.collectionView2{
collectionView1.scrollToItemAtIndexPath(indexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
}
}
}
Result:
Project Sample for more Info.

Resources