App crashes when I deselect an item in a UICollectionView - swift

I'm working on UICollectionView. I'm assigning one image to collection view cell when user selects it, and changing the image when user selects other cell, as shown in below code
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
let selectedCell : CollectionCellForAlertView = collectionView.cellForItemAtIndexPath(indexPath) as! CollectionCellForAlertView
println("cell selected")
selectedCell.imageView.image = UIImage(named: "someImage.png")
}
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath){
println("deselected")
let deselectedCell : CollectionCellForAlertView = collectionView.cellForItemAtIndexPath(indexPath) as! CollectionCellForAlertView
deselectedCell.imageView.image = UIImage(named: "someOtherImage.png")
}
Sometimes it works properly but some other times it crashes because 'deselectedCell' will have nil value. Can anybody please tel me how to resolve this.

I think this might work for you. I tested it in my app and it worked.
let deselectedCell = collectionView.cellForItemAtIndexPath(indexPath) as CollectionCellForAlertView
deselectedCell.imageView.image = UIImage(named: "someOtherImage.png")

Related

ReloadData is not working for a UICollectionView

I would like to change my entier array used to created all my cells with a button and then reload my collection view, but it is not working. I've tried to reload the collection view into the main thread but it also not working
I've tried to reload the collection view into the main thread, or just using collectionView.reloadData() but it also not working
#IBAction func BicepsBtn(_ sender: Any) {
self.current = "Biceps"
Data = user.getMuscleDataChart(typeMuscle: current)
listMuscle = user.getListMuscle(typeMuscle: current)
collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return listMuscle.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
let switchView = cell.viewWithTag(1000) as? UISwitch
let titleView = cell.viewWithTag(1001) as? UILabel
if let titleView = titleView, let switchView = switchView {
titleView.text = self.listMuscle[indexPath.row].label
titleView.textColor = self.listMuscle[indexPath.row].color
switchView.tag = indexPath.row
switchView.addTarget(self, action: #selector(yourFunc),
for: UIControl.Event.valueChanged)
}
return cell
}
Here is my current code, when the user is going to click on the Biceps button, the function will fetch all data about this muscle and then trying to reload.
Any idea ?
Thanks in advance

Swift Uicollection view inside a table View

I got an image url array inside a post object array I want to display this post array in a table view and display the images as a collection view inside the table view. How can I enter image description heredo it? I tired to use a int i as an indicator but it doesn't work.
here are the codes
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeCell", for: indexPath) as! HomeTableViewCell
cell.postsText.text = postLists[indexPath.row].postText
i = indexPath.row
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (postLists[i].imageUrlList?.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath) as! PhotosCollectionCell
let url = postLists[i].imageUrlList![indexPath.row]
let imgUrl = URL(string: url)
URLSession.shared.dataTask(with: imgUrl!, completionHandler: { (data, response, error) in
if error != nil {
// if download hits an error, so lets return out
print(error)
return
}
// if there is no error happens...
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // in half a second...
cell.postPhoto.image = UIImage(data: data!)
}
}).resume()
return cell
}
Never forcefully wrap optional ever Until you are very sure. (I can comment also but I want to add more details which is not suitable for comment so forgive )
Another thing I can see is use indexPath.item in collectionView not indexPath.row both will be same but this is standard I always follows.
You are not calling URLSession.data task in background thread. it is always recommend to do so. my suggestion is to that you should use some third party library like SDWebIamge which will helpful to you cache already downloaded image.
Wy Crash:
What I am seeing is Crash because of your variable i in your code postLists[i].
What you should do
Inside
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
you can set tag to your collection view like
cell.yourCollectionViewObject.tag = indexPath.row
and replace
let url = postLists[i].imageUrlList![indexPath.row]
with
let url = postLists[collectionView.tag].imageUrlList![indexPath.row]
Hope it is helpful

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
}

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
}

CollectionView populate at randomIndex in Swift

I have a colllectionView running successfully which grabs url image content from web link .I am trying to populate collectionView at random index once every time view loads.my try as below...
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! Cell
let randomIndex = Int(arc4random_uniform(UInt32(apps.count)))
cell.app = apps[randomIndex] as? AppInfo
return cell
}
Above method reload the collectionView everytime page scrolls. I am trying to achieve reload once only...
Thanks in Advance....