I have a tableView with three images in each cell which display all the images from my posts class.. So I download all the images then divide them by 3 when they're put in the cell!! So it doesn't show the same image 3 times in each cell when downloaded...
A bit confusing but If I show you my code you might understand how it works better!
But anyway what I'm trying to do now is the same but with the text, so in a cell depending on what's downloaded it will either show the images as normal or if they're text It will show text instead of the image!!
// HERE'S HOW I SORT THE 3 IMAGES WHEN DOWNLOADED (CellForRowAtIndexPath)
if post.dataType == 1
{
for imageView in cell.threeImages {
imageView.image = UIImage(named: "ImagePlaceHolder")
if counter < posts.count{
imageView.hidden = false
let imagePost = posts[counter++].image
imagePost!.getDataInBackgroundWithBlock { (data:NSData?, error:NSError?) -> Void in
if error == nil {
if let imageData = data {
imageView.image = UIImage(data: imageData)
}
}
}
} else {
imageView.hidden = true
}
// AND HERE'S HOW I SORT THEM / DIVIDE THEM BY 3 SO THEY'RE NOT ALL THE SAME FOR EACH ROW.
func roundUp(value: Double) -> Int {
if value == Double(Int(value)) {
return Int(value)
} else if value < 0 {
return Int(value)
} else {
return Int(value) + 1
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return = roundUp(Double(posts.count) / 3.0)
}
Here is what it looks like now on the simulator, after downloading all the images and it is also downloading 1 text column from parse: [![enter image description here][1]][1]
Now after I tried this code here:
//IMAGES
if post.dataType == 1
{
//Images
for imageView in cell.threeImages {
imageView.image = UIImage(named: "ImagePlaceHolder")
if counter < posts.count{
imageView.hidden = false
let imagePost = posts[counter++].image
imagePost!.getDataInBackgroundWithBlock { (data:NSData?, error:NSError?) -> Void in
if error == nil {
if let imageData = data {
imageView.image = UIImage(data: imageData)
//TEXT
for textHide in cell.threeLabels{
textHide.hidden = true
}}}} } else {
imageView.hidden = true
}
I get this result which is nearly there:
[![enter image description here][2]][2]
But what I am actually after is something where the text can be mixed up with the images like so:
[![enter image description here][3]][3]
I have a feeling it could be to do with the DataType code, as it allows either all images or all text...So here the code for my Struct too!
truct PostStruct {
var dataType : Int = 0 // 0 for text, 1 for picture
var date : NSDate
var username : NSString
var text : NSString?
var title : NSString?
var image : PFFile?
var uuid : NSString
var profileImage : PFFile
var caption : NSString?
init (dataTypeInit: Int, dateInit : NSDate, usernameInit: String, textInit: String, titleInit: String, uuidInit: String,profileImageInit: PFFile) {
dataType = dataTypeInit
date = dateInit
username = usernameInit
text = textInit
title = titleInit
uuid = uuidInit
profileImage = profileImageInit
}
init (dataTypeInit: Int, dateInit : NSDate, usernameInit: String, imageInit: PFFile, uuidInit: String, profileImageInit: PFFile, captionInit: String) {
dataType = dataTypeInit
date = dateInit
username = usernameInit
image = imageInit
uuid = uuidInit
profileImage = profileImageInit
caption = captionInit
}
}
var posts : [PostStruct] = []
UPDATE
for imageView in cell.threeImages {
imageView.image = UIImage(named: "ImagePlaceHolder")
for textView in cell.threeLabels {
let rowData = tableData[indexPath.row]
for indexInRow in 0...2
{
if indexInRow > rowData.posts.count
{
textView.hidden = true
imageView.hidden = true
// there are less posts for this row than the current index - so hide both the image and the text
// hide the imageView at position indexInRow
// hide the text view (label) at position indexInRow
}
else
{
let postt = rowData.posts[indexInRow]
// there is a post - check to see if it's text or an image
if postt.dataType == 1
// image type (replace this with an enumerator at some point)
{
postt.image!.getDataInBackgroundWithBlock { (data:NSData?, error:NSError?) -> Void in
if error == nil {
if let imageData = data {
imageView.image = UIImage(data: imageData)
imageView.hidden = false
textView.hidden = true
}
}
}
// display the image in image at position indexInRow
// hide the text view (label) at position indexInRow
}
else
{
imageView.hidden = true
textView.hidden = false
textView.text = postt.text as? String
// hide the imageView at position indexInRow
// display the text view (label) at position indexInRow
}
}
}}
}
Thanks in advance for any help!
I think you're overcomplicating things by using having to keep dividing by three - why not create the data for the tableview already split into rows of three?
You could have the rowData structure like this
struct rowData
{
var posts : [PostStruct] = []
}
and store it in a class-level variable like this
var tableData : [rowData] = []
and then parse the data into that structure when you load it
// create an array of tableData,
// where each element is of type rowData
// which has up to 3 `post` entries
// each of which is either an image or a text post
// the tableView methods are then based on tableData
var indexInRow = 0
for post in posts
{
if indexInRow == 0
{
// create a new rowData object
tableData.append(rowData())
}
tableData[tableData.count - 1].posts.append(post)
// using the modulo operator like this will return the remainder of dividing by 3, so it will always be 0, 1, 2
indexInRow = (indexInRow + 1) % 3
}
and then your tableView methods look something like this
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let rowData = tableData[indexPath.row]
for indexInRow in 0...2
{
if indexInRow > rowData.posts.count
{
// there are less posts for this row than the current index - so hide both the image and the text
// hide the imageView at position indexInRow
// hide the text view (label) at position indexInRow
}
else
{
// there is a post - check to see if it's text or an image
// UPDATE
let post = rowData.posts[indexInRow]
// UPDATE
if post.dataType == 0 // image type (replace this with an enumerator at some point)
{
// display the image in image at position indexInRow
// hide the text view (label) at position indexInRow
}
else
{
// hide the imageView at position indexInRow
// display the text view (label) at position indexInRow
}
}
}
return UITableViewCell()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return tableData.count
}
Related
My UICollectionview works fine when I add items to Section 1, and changing the section of an item from section 1 to section 2 works. However, the items start displaying incorrectly if I do the following:
Add items to Section 1
Move item from section 1 to section 2
Add new item to Section 1 (<--> here the data breaks and the collection view starts displaying one item twice)
I'll refer to this as the "Breakdown Scenario" below.
I have been struggling with understanding the reason for this problem for a few days now. I am sure it is something basic, but at my current level of knowledge I have not been able to figure it out. I'm fine implementing UICollectionviews with one section, but I relied on the Raywenderlich tutorial on UICollectionViews for figuring out how to implement multiple sections, and I don't feel entirely at home with the sample code. The tutorial I relied on is here (though I think behind a paywall): (https://www.raywenderlich.com/6308-beginning-collection-views/lessons/16).
Here's the description of how the UICollectionview works in my app, and the key bits of code.
When the app is loaded, a function in datasource.swift runs a function that populates the UICollectionview.
This is the code:
private func loadPicturesFromDisk() -> [Picture] {
sections.removeAll(keepingCapacity: false)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let archiveURL = documentsDirectory.appendingPathComponent("pictures").appendingPathExtension("plist")
let propertyListDecoder = PropertyListDecoder()
if let retrievedPicturesData = try? Data(contentsOf: archiveURL), let decodedPictures = try? propertyListDecoder.decode(Array<Picture>.self, from: retrievedPicturesData) {
for picture in decodedPictures {
let pictureName = picture.pictureName
print("The pictureName in loadPicturesFromDisk = \(pictureName), the pictureCategory is = \(picture.pictureCategory)")
let pictureCategory = picture.pictureCategory
if !sections.contains(pictureCategory) {
sections.append(pictureCategory)
}
let newPicture = Picture(picture: pictureName, category: pictureCategory)
pictures.append(newPicture)
}
print("Enumerating through pictures in loadPicturesFromDisk")
enumerateThroughPictures(pictures: pictures)
return pictures
} else {
return []
}
}
This works as intended. I have a couple of print functions there to check that the data loaded looks right.
Now when the UICollectionView calls this data in cellForItemAt in the normal scenario, it works fine. However, in the Breakdown Scenario (as defined above) the data is not in sync with the data in the datasource array variables. Here is an example of how the data looks like when loaded, and when called by cellForItemAt in the Breakdown Scenario:
Data when checked when loading
Item(0: 1825 - No Category - indexPath = [0, 0] - absoluteindexpath = 0
Item(1: 3630 - Filed - indexPath = [1, 0] - absoluteindexpath = 3
Item(2: 8946 - No Category - indexPath = [0, 1] - absoluteindexpath = 1
Item(3: 696 - No Category - indexPath = [0, 2] - absoluteindexpath = 2
Data when checked at cellForItemAt:
cellForItemAt is processing picture: 1825 - No Category, with indexPath of [0, 0] and absoluteindexpath of 0
cellForItemAt is processing picture: 3630 - Filed, with indexPath of [0, 1] and absoluteindexpath of 1
cellForItemAt is processing picture: 8946 - No Category, with indexPath of [0, 2] and absoluteindexpath of 2
cellForItemAt is processing picture: 3630 - Filed, with indexPath of [1, 0] and absoluteindexpath of 3
Here is the code for cellForItemAt:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PicAppCollectionViewCell
cell.backgroundColor = UIColor.white
cell.imageView.layer.borderColor = UIColor.black.cgColor
cell.imageView.layer.borderWidth = 1
// create a temporary picture object used to populate the view
if let picture = dataSource.pictureForItemAtIndexPath(indexPath) {
print("cellForItemAt is processing picture: \(picture.pictureName) - \(picture.pictureCategory), with indexPath of \(indexPath) and absoluteindexpath of \(dataSource.absoluteIndexForIndexPath(indexPath))")
if debuggingMode == true {
cell.photoIDLabel.isHidden = false
cell.photoIDLabel.text = picture.pictureName
}
cell.imageView.image = getSavedImage(named: picture.pictureName)
cell.isEditing = isEditing
} else {
print("did not find an image for indexpath: \(indexPath)")
}
return cell
}
I use a UICollectionViewController, which relies heavily on dataSource.swift derived from the RW tutorial. I have replicated all of the data source code below as there are a lot of interdependencies in the function call.
class DataSource {
private var pictures = [Picture]()
//private var immutablePictures = [Picture]()
private var sections : [String] = []
private var latestPictureID = 0
var count: Int {
return pictures.count
}
var numberOfSections: Int {
return sections.count
}
// MARK:- Public
init() {
// add init code if needed
pictures = loadPicturesFromDisk()
}
func newPicture(newPicture: Picture) -> IndexPath {
for picture in pictures {
if picture.pictureName == newPicture.pictureName {
let randomName = Int.random(in: 0 ..< 10000)
newPicture.pictureName = String(randomName)
}
}
pictures.append(newPicture)
print("The pictureName of the saved picture = \(newPicture.pictureName)")
saveToFile(pictures: pictures)
print("Launching array enumeration from newPicture before sort")
enumerateThroughPictures(pictures: pictures)
pictures.sort { $0.pictureCategory < $1.pictureCategory }
print("Launching array enumeration from newPicture after sort sort")
enumerateThroughPictures(pictures: pictures)
return indexPathForPicture(newPicture)
}
func replacePictureAtIndexPath(picture: Picture, indexPath: IndexPath) {
// make this update the collectionview and maybe it works
pictures[absoluteIndexForIndexPath(indexPath)] = picture
let pictureCategory = picture.pictureCategory
if !sections.contains(pictureCategory) {
sections.append(pictureCategory)
}
saveToFile(pictures: pictures)
print("Launching array enumeration from replacePictureAtIndexPath")
enumerateThroughPictures(pictures: pictures)
//pictures.sort { $0.pictureCategory < $1.pictureCategory }
}
func enumerateThroughPictures(pictures: [Picture]) {
print("Enumerating through pictures.array:")
var index = 0
for picture in pictures {
print("Item(\(index): \(picture.pictureName) - \(picture.pictureCategory) - indexPath = \(indexPathForPicture(picture)) - absoluteindexpath = \(absoluteIndexForIndexPath(indexPathForPicture(picture)))")
index += 1
}
}
func deleteItemsAtIndexPaths(_ indexPaths: [IndexPath]) {
var indexes = [Int]()
for indexPath in indexPaths {
indexes.append(absoluteIndexForIndexPath(indexPath))
}
var newPictures = [Picture]()
for (index, picture) in pictures.enumerated() {
if !indexes.contains(index) {
newPictures.append(picture)
}
}
pictures = newPictures
}
func movePictureAtIndexPath(_ indexPath: IndexPath, toIndexPath newIndexPath: IndexPath) {
if indexPath == newIndexPath {
print("Returning from movePicture as indexPath and newIndexPath were the same")
return
}
let index = absoluteIndexForIndexPath(indexPath)
let currentPicture = pictures[index]
currentPicture.pictureCategory = sections[newIndexPath.section]
let newIndex = absoluteIndexForIndexPath(newIndexPath)
print("About to remove picture at : \(index)")
pictures.remove(at: index)
print("About to add picture at : \(newIndex)")
pictures.insert(currentPicture, at: newIndex)
}
func indexPathForPicture(_ picture: Picture) -> IndexPath {
let section = sections.index(of: picture.pictureCategory)!
var item = 0
for (index, currentPicture) in picturesForSection(section).enumerated() {
if currentPicture === picture {
item = index
break
}
}
return IndexPath(item: item, section: section)
}
func numberOfPicturesInSection(_ index: Int) -> Int {
let currentPictures = picturesForSection(index)
return currentPictures.count
}
func pictureForItemAtIndexPath(_ indexPath: IndexPath) -> Picture? {
if indexPath.section > 0 {
let currentPictures = picturesForSection(indexPath.section)
return currentPictures[indexPath.item]
} else {
return pictures[indexPath.item]
}
}
func titleForSectionAtIndexPath(_ indexPath: IndexPath) -> String? {
if indexPath.section < sections.count {
return sections[indexPath.section]
}
return nil
}
// MARK:- Private
private func loadPicturesFromDisk() -> [Picture] {
sections.removeAll(keepingCapacity: false)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let archiveURL = documentsDirectory.appendingPathComponent("pictures").appendingPathExtension("plist")
let propertyListDecoder = PropertyListDecoder()
if let retrievedPicturesData = try? Data(contentsOf: archiveURL), let decodedPictures = try? propertyListDecoder.decode(Array<Picture>.self, from: retrievedPicturesData) {
for picture in decodedPictures {
let pictureName = picture.pictureName
print("The pictureName in loadPicturesFromDisk = \(pictureName), the pictureCategory is = \(picture.pictureCategory)")
let pictureCategory = picture.pictureCategory
if !sections.contains(pictureCategory) {
sections.append(pictureCategory)
}
let newPicture = Picture(picture: pictureName, category: pictureCategory)
pictures.append(newPicture)
}
print("Enumerating through pictures in loadPicturesFromDisk")
enumerateThroughPictures(pictures: pictures)
return pictures
} else {
return []
}
}
private func saveToFile(pictures: [Picture]) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let archiveURL = documentsDirectory.appendingPathComponent("pictures").appendingPathExtension("plist")
let propertyListEncoder = PropertyListEncoder()
let encodedPictures = try? propertyListEncoder.encode(pictures)
try? encodedPictures?.write(to: archiveURL, options: .noFileProtection)
}
func absoluteIndexForIndexPath(_ indexPath: IndexPath) -> Int {
var index = 0
for i in 0..<indexPath.section {
index += numberOfPicturesInSection(i)
}
index += indexPath.item
return index
}
private func picturesForSection(_ index: Int) -> [Picture] {
let section = sections[index]
let picturesInSection = pictures.filter { (picture: Picture) -> Bool in
return picture.pictureCategory == section
}
return picturesInSection
}
}
Can you guys give me some help to hide the image and name if the message it's from the same user... I want only to show it for the first message...and if that user send more not to show anymore until another Id appear... like whatsapp does it..
currently I m having like this to show u an example
[![enter image description here][1]][1]
var isTheSameUser = false
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let selectedChat = chat[indexPath.row]
let myId = String(describing:UserDefaults.standard.value(forKey: "user_id")!)
let messageUserId = String(describing:selectedChat.owner_id)
if messageUserId == myId {
return myMessageCell(indexPath: indexPath)
}else {
return userMessageCell(indexPath: indexPath)
}
}
func myMessageCell(indexPath :IndexPath) -> UITableViewCell {
let cell = self.mainTableView.dequeueReusableCell(withIdentifier: "MyMessageTableViewCell", for: indexPath) as! MyMessageTableViewCell
let selectedChat = self.chat[indexPath.row]
let myId = String(describing:UserDefaults.standard.value(forKey: "user_id")!)
// Show only for the first message
// photo image
if !isTheSameUser {
cell.profileImageView.isHidden = false
cell.profileNameLabel.isHidden = false
} else {
cell.profileImageView.isHidden = true
cell.profileNameLabel.isHidden = true
}
if let userInfo = getUserMemberOf(userId: messageUserId) {
cell.profileImageView.imageFromURL(urlString: userInfo["photo"] as! String)
} else {
cell.profileImageView.image = #imageLiteral(resourceName: "accountIcon")
}
cell.profileNameLabel.text = "\(String(describing: cell.userProfileInfo!["name"]!))"
return cell
You need check the previous chat messsage id like for every message
if indexPath.row != 0 {
let prevItem = chat[indexPath.row - 1]
let currentItem = chat[indexPath.row]
if prevItem.owner_id! == currentItem.owner_id! {
// hide label and image
}else {
// show them
}
}
else {
// show them
}
Hey guys I need your help please, when I reload a tableview and call the scroll to row function for the bottom row (array.length - 1) as index path, it scrolls to it, then it scrolls one row up. I have made a cool chat part to my app, and it is simple, I have a function that grabs messages, and for some reason on my iPhone simulator, it does this weird scrolling back up motion. Basically I was hoping one of you guys could help me find out why it is doing that. It is some simple code.
main function:
func grabMessages () {
if let uid = Auth.auth().currentUser?.uid {
if let theirId = theirUid {
let ref = Database.database().reference()
ref.child("users").child(uid).child("chats").child(theirId).child("messages").observe(.value, with: {(snapshot) in
var reloadi = false
if let values = snapshot.value as? [String : AnyObject] {
for (_, one) in values {
if let whoSent = one["sender"] as? String, let messagl = one["message"] as? String, let timerl = one["timeStamp"] as? Int, let keyer = one["key"] as? String {
let newMess = Message()
print("googd")
newMess.key = keyer
newMess.timeStamp = timerl
newMess.messager = messagl
newMess.sender = whoSent
if self.messages.contains( where: { $0.key == newMess.key } ) {
} else {
self.messages.append(newMess)
if self.messages.count != 0 {
self.messages.sort { $1.timeStamp > $0.timeStamp }
reloadi = true
}
if newMess.sender == theirId {
let update = ["unseen" : "iViewed"]
ref.child("users").child(theirId).child("chats").child(uid).updateChildValues(update)
}
}
}
if reloadi == true {
reloadi = false
DispatchQueue.main.async {
self.tablerView.reloadData()
let indexPat = IndexPath(row: 0, section: self.messages.count - 1)
self.tablerView.isHidden = false
self.tablerView.scrollToRow(at: indexPat, at: .bottom, animated: false)
}
}
}
}, withCancel: nil)
}
}
}
I will say in my viewdidload I set the frame of the tableview, which is just a cgrect and same size across all platform, fixed width and height. And on my own iPhone it runs and works fine, only on simulator iPhones did it do this.
Here is a screen shot
https://imgur.com/a/ZAhbJ
So if you can see, it shows other section below it, but it is scrolled to the one above it. So it originally scrolls to it, then scrolls back up one section.
some other stuff
numb of sections = messages.count
number of rows in section = 1
I am modifying my paid for app to a free with IAP.
Some group types are free and some will need to be paid for.
On the tableView controller, there is a padlock UIImageView that displays each "locked" item if it is a part of a locked group.
When someone buys that group, or all, that padlock is meant to disappear. This padlock is not a part of the code that prevents the user from seeing the details as I have that code somewhere else and it works fine.
Initially, "Padlock" displays accurately. However, If I scroll up and down on the tableView, the padlocks will randomly disappear.
How to prevent this?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
//
// We need to fetch our reusable cell.
//
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: Resource.SpeciesCell)!
//
// Get all of the components of the cell.
//
let specieImage: UIImageView = cell.viewWithTag(Resource.SpeciesImageTag) as! UIImageView
let specieName: UILabel = cell.viewWithTag(Resource.SpeciesNameTag) as! UILabel
let specieGenus: UILabel = cell.viewWithTag(Resource.SpeciesGenusTag) as! UILabel
let specieFamily: UILabel = cell.viewWithTag(Resource.SpeciesFamilyTag) as! UILabel
// Set our name, family and genus labels from our data.
//
specieName.text = self.species[(indexPath as NSIndexPath).row].specie
specieFamily.text = ""
specieGenus.text = self.species[(indexPath as NSIndexPath).row].speciesSubgroup
// **** Adding Padlock Begins HERE ****
let padLock: UIImageView = cell.viewWithTag(Resource.SpeciesCategoryLabelTag) as! UIImageView
padLock.image = UIImage(named: "PadlockIcon")
padLock.alpha = 0.7
let speciesGroupFreeArray: Array<String>
let speciesGroupVertebratesArray: Array<String>
let speciesGroupInvertebratesArray: Array<String>
speciesGroupFreeArray = ["eels", "Mammals", "Annelids", "Bivalvians", "Cephalopods", "Cool oddities", "Crustacean", "Echinoderms", "Hydrozoans", "Isopods"]
speciesGroupVertebratesArray = ["Fish", "Sharks", "Rays", "Reptilia", "Syngnathiformes"]
speciesGroupInvertebratesArray = ["Corals", "Gastropods"]
let fishesPurchased = UserDefaults.standard.bool (forKey: "ReefLife5Fishes")
let sharksPurchased = UserDefaults.standard.bool (forKey: "ReefLife6Sharks")
let nudisPurchased = UserDefaults.standard.bool (forKey: "ReefLife7Nudis")
let turtlesPurchased = UserDefaults.standard.bool (forKey: "ReefLife8Turtles")
let seahorsesPurchased = UserDefaults.standard.bool (forKey: "ReefLife9Seahorses")
let coralsPurchased = UserDefaults.standard.bool (forKey: "ReefLife4Corals")
let vertebratesPurchased = UserDefaults.standard.bool (forKey: "ReefLife3Vertebrates")
let invertebratesPurchased = UserDefaults.standard.bool (forKey: "ReefLife2Invertebrates")
let fullPurchased = UserDefaults.standard.bool (forKey: "ReefLife1Full")
let categoryName = self.species[(indexPath as NSIndexPath).row].group
if fullPurchased == true {
padLock.isHidden = true
} else if speciesGroupVertebratesArray.contains(categoryName) {
if vertebratesPurchased == true {
padLock.isHidden = true
} else {
if categoryName == "Fish" {
if fishesPurchased == true{
padLock.isHidden = true
} else{
}
} else if (categoryName == "Sharks" || categoryName == "Rays" ) {
if sharksPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Syngnathiformes" {
if seahorsesPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Reptilia" {
if turtlesPurchased == true{
padLock.isHidden = true
} else{
}
}
}
} else if speciesGroupInvertebratesArray.contains(categoryName) {
if invertebratesPurchased == true {
padLock.isHidden = true
} else {
if categoryName == "Corals" {
if coralsPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Gastropods" {
if nudisPurchased == true{
padLock.isHidden = true
} else{
}
}
}
}
if speciesGroupFreeArray.contains(categoryName) {
padLock.isHidden = true
}
// **** Adding Padlock Ends HERE ****
//
// We now need to set our photo. First, we need to fetch the photo based on our specie
// id.
//
let photos = AppDelegate.getRLDatabase().getSpeciePhotos(self.species[(indexPath as NSIndexPath).row].id)
//
// Set the image for our UIImageView.
//
if photos.isEmpty != true
{
specieImage.clipsToBounds = true
specieImage.contentMode = .scaleAspectFill
specieImage.image = UIImage(named: photos[0].name)
// specieImage.image = UIImage(named: photos[0].name)?.resizeTo(specieImage.bounds)
}
else
{
specieImage.image = UIImage(named: Resource.UnknownImage)?.resizeTo(specieImage.bounds)
}
//
// Return our new cell.
//
return cell
}
Please try replace this
if speciesGroupFreeArray.contains(categoryName) {
padLock.isHidden = true
}
to
padLock.isHidden = speciesGroupFreeArray.contains(categoryName)
Your code only ever sets padlock.isHidden = true. If you get a recycled cell where the padlock is already hidden, there's nothing to unhide it.
You need to explicitly set the padlock isHidden state in all cases.
Given your somewhat contorted code for setting the isHidden property, the simplest way to fix your current code would be to set padlock.isHidden = false At the beginning of your cellForRowAt() method. Then, if none of the cases set isHidden to true, it will always be unbidden, even in a case where you are reconfiguring a recycled cell where the padlock was hidden.
EDIT:
This a key take-away for managing table views and collection views in iOS. Always assume that a cell comes to you with all views set to a non-default state. Your code always needs to explicitly set every view to a specific state.
Think of a table view cell as a paper patient info form at a doctor's office where the office recycles the forms, and doesn't erase the info left by the previous patient. You always have to erase the info left by the previous patient. If you don't have an allergy to peanuts, it's not enough to simply not check that box. You have to erase the previous check marks and other info, or the previous patient's info will get mixed up with yours.
That's what's happening with your padlock.isHidden state. You're assuming it starts out in the default state, but it may not.
I have this problem, I have a tableview with 3 different kind of news manage by segmented control. When I scrolled the news stays for example in the fifth new, if I click in the second segment, appears in the position 5 . Is not showing the news from the segment 1(the new one),at row 0 (beginning) , stays in the position I leave when I was scrolling. Why is happening this? what I'm doing wrong?. I'm using one tableview for the 3 different kinds of news and reload the tableview data every time I change the segment.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
NSLog("selectedSegmentIndex: \(self.sectionSegmentedControl.selectedSegmentIndex) - Row: \(indexPath.row)")
let cell:UITableViewCell = self.tableview.dequeueReusableCellWithIdentifier("Cell")!
// Grab the elements using the tag
let labelTitle:UILabel? = cell.viewWithTag(1) as! UILabel?
let labelSection:UILabel? = cell.viewWithTag(2) as! UILabel?
let labelDate:UILabel? = cell.viewWithTag(3) as! UILabel?
let imageView:UIImageView? = cell.viewWithTag(4) as! UIImageView?
// Check which segment to get data from
switch self.sectionSegmentedControl.selectedSegmentIndex {
case 0:
// If segment is 0, take data from cover News
if (indexPath.row <= self.coverNews.count - 1){
//Current new to display
let currentNewToDisplay = self.coverNews[indexPath.row]
//let currentNewToDisplay = self.news[indexPath.row]
// Get the image and assign to the imageView
if let actualImageView = imageView {
// Imageview actually exists
if currentNewToDisplay.imageUrl != "" {
// Image url exists, so download it
let imageUrl:NSURL? = NSURL(string: currentNewToDisplay.imageUrl)
// Download image with SDWebImage library
if let url = imageUrl {
actualImageView.sd_setImageWithURL(url)
}
}
}
// Get the news title and assign to the label
if let actualLabelTitle = labelTitle {
let title = currentNewToDisplay.title
actualLabelTitle.text = title
actualLabelTitle.numberOfLines = 0
actualLabelTitle.minimumScaleFactor = 0.1
}
// Get the news date and assign to the label
if let actualLabelDate = labelDate {
let character = "| "
actualLabelDate.text = character + currentNewToDisplay.date_short
}
// Get the news section and assign to the label
if let actualabelSection = labelSection {
actualabelSection.text = currentNewToDisplay.section
}
}
case 1:
// If segment is 1, take data from toprated News
if (indexPath.row <= self.topratedNews.count - 1){
let currentNewToDisplay2 = self.topratedNews[indexPath.row]
// Get the image and assign to the imageView
if let actualImageView2 = imageView {
// Imageview actually exists
if currentNewToDisplay2.imageUrl != "" {
// Image url exists, so download it
let imageUrl2:NSURL? = NSURL(string: currentNewToDisplay2.imageUrl)
// Download image with SDWebImage library
if let url2 = imageUrl2 {
actualImageView2.sd_setImageWithURL(url2)
}
}
}
// Get the news title and assign to the label
if let actualLabelTitle2 = labelTitle {
actualLabelTitle2.text = currentNewToDisplay2.title
actualLabelTitle2.numberOfLines = 0
actualLabelTitle2.minimumScaleFactor = 0.1
}
// Get the news date and assign to the label
if let actualLabelDate2 = labelDate {
let character2 = "| "
actualLabelDate2.text = character2 + currentNewToDisplay2.date_short
}
// Get the news section and assign to the label
if let actualabelSection2 = labelSection {
actualabelSection2.text = currentNewToDisplay2.section
}
}
case 2:
if (indexPath.row <= self.latestNews.count - 1){
// If segment is 2, take data from latestNews News
let currentNewToDisplay3 = self.latestNews[indexPath.row]
// Get the image and assign to the imageView
if let actualImageView3 = imageView {
// Imageview actually exists
if currentNewToDisplay3.imageUrl != "" {
// Image url exists, so download it
let imageUrl3:NSURL? = NSURL(string: currentNewToDisplay3.imageUrl)
// Download image with SDWebImage library
if let url3 = imageUrl3 {
actualImageView3.sd_setImageWithURL(url3)
}
}
}
// Get the news title and assign to the label
if let actualLabelTitle3 = labelTitle {
actualLabelTitle3.text = currentNewToDisplay3.title
actualLabelTitle3.numberOfLines = 0
actualLabelTitle3.minimumScaleFactor = 0.1
}
// Get the news date and assign to the label
if let actualLabelDate3 = labelDate {
let character3 = "| "
actualLabelDate3.text = character3 + currentNewToDisplay3.date_short
}
// Get the news section and assign to the label
if let actualabelSection3 = labelSection {
actualabelSection3.text = currentNewToDisplay3.section
}
}
default:
break
}
// Set insets to zero
cell.layoutMargins = UIEdgeInsetsZero
return cell
}
// MARK: Segmented Control
#IBAction func segmentedChanged(sender: UISegmentedControl) {
switch self.sectionSegmentedControl.selectedSegmentIndex {
case 0:
// If segment is 0, return rows for coverNews array
if (self.coverNews.count == 0) {
loadNews()
}else{
dispatch_async(dispatch_get_main_queue(), {
self.tableview.reloadData()
})
}
case 1:
// If segment is 1, return rows for topratedNews array
if (self.topratedNews.count == 0) {
loadNews()
}else{
dispatch_async(dispatch_get_main_queue(), {
self.tableview.reloadData()
})
}
case 2:
// If segment is 2, return rows for latestNews array
if (self.latestNews.count == 0) {
loadNews()
}else{
dispatch_async(dispatch_get_main_queue(), {
self.tableview.reloadData()
})
}
default:
break
}
}
// MARK: Load News
func loadNews(){
switch(sectionSegmentedControl.selectedSegmentIndex){
case 0:
self.model.getFeedNews("cover")
case 1:
self.model.getFeedNews("toprated")
case 2:
self.model.getFeedNews("latest")
default:
break
}
}