change tableview cell content on collection view cell selection - swift

I have a tableView and collectionView in one view controller.
in tableView I have title description and in collectionView I have lable .
I want on collectionView label selection tableView content should change .
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Bookmark.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionViewBookmark.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BookMarkCollectionViewCell
cell.lblTitle.text = Bookmark[indexPath.row]
cell.backgroundColor = UIColor.white
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionViewBookmark.cellForItem(at: indexPath)
cell?.backgroundColor = UIColor.blue
self.selectedIndexPath = indexPath
//
let newsDict = arrNewsData[indexPath.row]
if (indexPath.row == 1)
{
let cell1 = tableViewBookMark.cellForRow(at: indexPath) as! BookMarkFirstTableViewCell
cell1.lblTitle.text = newsDict["title"] as! String
tableViewBookMark.reloadData()
}
tableViewBookMark.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableViewBookMark.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! BookMarkFirstTableViewCell
let dict = arrNewsData[indexPath.row]
cell.lblTitle.text = dict["title"] as! String
// cell.imgBookMark.image = dict["image_url"]
let url = URL(string: dict["image_url"] as! String)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if data != nil{
DispatchQueue.main.async {
let image = UIImage(data: data!)
cell.imgBookMark.image = image
}
}
}.resume()
return cell
}

See my inline comments.
var tempCell: BookMarkFirstTableViewCell?
//Inside cellForRowAt indexPath
tempCell = cell
//Inside (collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
tempCell.lblTitle.text = newsDict["title"] as! String

You're reloading the tableView after updating the values in the cell,
tableViewBookMark.reloadData()
This will trigger the data source function including cellForRowAt, so you will lose your updated values a solution to this is to have a global variable in the UIViewController and check its values inside the cellForRowAt and update it in the collectionView DidSelect .
Extra tip: you don't need to reload all the tableView for a single change you can use
tableView.reloadRows(at: [indexPath], with: .top)
to reload only number of selected cells in the tableView

Related

How can I fix a UIcollectionViewCell from displaying an empty cell?

I have purposely left an empty image in my assets catalog so that I can get my collectionView to somehow skip that image if it is nil, but so far it will render an empty image in that cell. It is better than crashing my app but how can I get it to skip that image?
here is my cellForItemAt indexPath code. Any ideas would be much appreciated.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: K.collectionViewCell, for: indexPath) as! CollectionViewCell
DispatchQueue.main.async {
let image = RoomModel.roomModel.rooms[indexPath.item]
if let image = image {
cell.imageView.image = image
}
}
return cell
}
Model Solution:
import UIKit
var data = [long list of UIImage(named: ...)]
class RoomModel {
var rooms = data.compactMap { ($0) }
var roomNo = 0
func setRoomNo(sender: Int) {
roomNo = sender
}
func getRoom() -> UIImage {
let image = rooms[roomNo]
return image
}
}
itemForRow Solution:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: K.collectionViewCell, for: indexPath) as! CollectionViewCell
DispatchQueue.main.async {
cell.imageView.image = self.roomModel.rooms[indexPath.item]
}
return cell
}
You would need to modify the data model to not include it if the image is nil and can be done by a simple if check before adding it in the model and then your cell would not render it as it is omitted from the data model.

set image to imageview in uicollectionview that is in uitableviewcell xib

I have taken a UITableView and deque a UITableViewCell XIB and set data to a label in it, also I have UICollectionView in UITableViewCell XIB in which I have to set images in a UICollectionViewCell.
UIImageView is in UICollectionViewCell and respective UICollectionView is in UITableViewCell so how to set an image to that UIImageView?
also have tableview delegate function in one file
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.discoverData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "discoveryTableViewCell", for: indexPath) as! discoveryTableViewCell
let data = discoverData[indexPath.row]
cell.messageLbl.text = (data["content"] as! String)
// This how normally image is set in tableview, how to do with collectionview
cell.userImage.pin_updateWithProgress = true
let riderImage = URL(string: (data["profile_pic"] as! String))
cell.userImage.pin_setImage(from: riderImage, placeholderImage: nil, completion: nil)
return cell
}
collection view delegate function in UITableViewCell.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numCell
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "discoverCell", for: indexPath as IndexPath) as! discoverCollectionViewCell
cell.postImage.backgroundColor = .cyan
return cell
}
Here is a picture of how it looks yellow box is UICollectionView and cyan color box is UIImageView.
In cellForRowAt indexPath:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "discoveryTableViewCell", for: indexPath) as! discoveryTableViewCell
if let data = discoverData[indexPath.row] as? [String: Any] {
cell.messageLbl.text = (data["content"] as! String)
cell.data = data
}
return cell
}
In your "discoveryTableViewCell" (It should be "DiscoveryTableViewCell") :
var data: [String: Any] {
didSet {
collectionView.reloadData()
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "discoverCell", for: indexPath as IndexPath) as! discoverCollectionViewCell
if let profilePic = data["profile_pic"] as? String {
let riderImage = URL(string: profilePic)
cell.postImage.pin_setImage(from: riderImage, placeholderImage: nil, completion: nil)
}
return cell
}
You should follow the proper style guide and naming conventions in Swift.
Please check this URL for better understanding:
https://github.com/raywenderlich/swift-style-guide

How can we reload header view inside our collection view

I've been looking for a way to reload my collection view header. So I have a collection view header & a CollectionViewCell that only contains an image. Now when the cell is press, I would like to display the image in the header view without calling collectionView.reloadData(). This is how my didSelectItemAt & didDeselectItemAt method looks like.
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedImage = images[indexPath.item]
let imageCell = collectionView.cellForItem(at: indexPath) as! CollectionCell
imageCell.photoBackgroundView.backgroundColor = .red
collectionView.reloadData()
}
override func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let imageCell = collectionView.cellForItem(at: indexPath) as! ImagePickerCell
imageCell.photoBackgroundView.backgroundColor = .black
}
So when I select a cell the view turns red, when I deselect it the view turns black. This video here, shows how the behavior without reloading the collectionView. Now here is were I would like to reload the header view.
If I do use collectionView.reloadData(), this is the outcome. How would I be able to reload the header or the collectionView where the header view displays the selected cell image & turns red.
You can try like global instance for that. Like
class YourClass: UIViewController {
/// Profile imageView
var profileImageview = UIImageView()
}
In CollectionView cellforItem assign a imageview. Like
let imageCell = collectionView.cellForItem(at: indexPath) as! CollectionCell
profileImageview = imageCell.imageView
Then when every you selecting collectionViewCell
You can call a function to change a image of imageView. Like
func updateImage() {
profileImageview.image = UIImage()
}
Well I'm trying to understand why sometimes you cast the cell in CollectionCell and sometimes in ImagePickerCell, anyway try to change your functions in these
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! CollectionCell
cell?.photoBackgroundView.backgroundColor = .red
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! CollectionCell
cell?.photoBackgroundView.backgroundColor = .black
}

UICollectionView keeps crashing unless i set indexpath.items = 1

Hi I have two codes for someone reason 1 works while the other doesn't can someone please explain why? The first function works, while the second doesn't. I'm trying to generate one cell as the type PayNowCell and every cell after that as the CheckOutCell type. However, it will only allow me to put the first cell as a CheckOutCell, the second as a PayNowCell, and every following cell as a CheckOutCell. Thanks!!! Error is index is out of bounds. And it points to this line
cell.item = checkout[indexPath.item].
Essentially i have a dynamic array checkout[] and im just trying to insert a description cell called paynow ontop of each checkoutcell while the checkout[] grows and shrinks
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 1 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paynow", for: indexPath) as! PayNowCell //init cells
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! CheckoutCell //init cells
cell.item = checkout[indexPath.item]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paynow", for: indexPath) as! PayNowCell //init cells
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! CheckoutCell //init cells
cell.item = checkout[indexPath.item]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (checkout.count + 1) //init number of cells
}
Try this array for manage your collection view
var array = [0,[]]
then add
array[1] = [your array for index 1]
You can add the section for manage multi-cell inside your collection view:-
func numberOfSections(in collectionView: UICollectionView) -> Int{
return (array[section] as AnyObject).count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return array[1].count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paynow", for: indexPath) as! PayNowCell //init cells
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! CheckoutCell //init cells
let checkout = array[1] // pass here array
guard checkout.count != 0 else {
return cell
}
cell.item = checkout[indexPath.item]
return cell
}
}

Why are image views sometimes not appearing in collection view cells?

I just updated to Swift 3.
My collection views were working great before the update. I did the recommended changes to make the compiler happy, but now I'm having this problem.
Image views that are in my custom UICollectionViewCells are simply not appearing anymore. Neither programmatically generated image views nor prototype image views are appearing.
I've given the image views background colors to check if my images are nil. The background colors aren't appearing, so it is safe to assume the image views are not appearing at all.
The cells themselves ARE appearing. Each image view has a label underneath, and the label is displaying properly with the correct text.
The most confusing part is that sometimes the image views DO appear, but there seems to be no rhyme or reason as to why or when.
My code is pretty standard, but I'll go ahead and share it anyway:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return searchClubs.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: HomeCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! HomeCollectionViewCell
cell.barLabel.text = searchClubs[indexPath.row].name
cell.imageCell.image = searchClubs[indexPath.row].image
cell.imageCell.layer.masksToBounds = true
cell.imageCell.layer.cornerRadius = cell.imageCell.frame.height / 2
return cell
}
func feedSearchClubs(child: AnyObject) {
let name = child.value(forKey: "Name") as! String
//Image
let base64EncodedString = child.value(forKey: "Image")!
let imageData = NSData(base64Encoded: base64EncodedString as! String, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters)
let image = UIImage(data:imageData! as Data)
//Populate clubs array
let club = Club.init(name: name, image: image!)
self.searchClubs.append(club)
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
Since Xcode 8 you have to call layoutIfNeeded() to calculate size (in your case you need to know cell.imageCell.frame.height) and position from auto layout rules or use a fixed value of cornerRadius.
cell.imageCell.layoutIfNeeded()
cell.imageCell.layer.masksToBounds = true
cell.imageCell.layer.cornerRadius = cell.imageCell.frame.height / 2
OR
cell.imageCell.layer.masksToBounds = true
cell.imageCell.layer.cornerRadius = 5
The imageCell's frame isn't set up ready yet in the cellForItemAt method.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: HomeCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! HomeCollectionViewCell
cell.barLabel.text = searchClubs[indexPath.row].name
cell.imageCell.image = searchClubs[indexPath.row].image
return cell
}
Instead put the setting up of layer on willDisplay since cell.imageCell.frame.height will have its value.
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
let cell: HomeCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! HomeCollectionViewCell
cell.imageCell.layer.masksToBounds = true
cell.imageCell.layer.cornerRadius = cell.imageCell.frame.height / 2
}