ios 9 UITableView ghost empty cells - ios

After updating to latest XCode 7 beta 5, my application is behaving very strange. After launch I got this:
After several updates of the page:
And again after several updates the section went normal (but bugs in another sections):
All the time in debugger all seems to be good: all the data is loaded from server and sent to table...
Does anybody have any ideas, why this is happening?
Code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:EventCell = self.contentWindow.dequeueReusableCellWithIdentifier("evcell")! as! EventCell
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "HH:mm"
var index = 0;
for date in keysSet {
if (index==indexPath.section)
{
cell.timeLabel.text = dateFormatter.stringFromDate(datesOfEvents[date]![indexPath.row].time)
cell.nameLabel.text = datesOfEvents[date]![indexPath.row].title
print(index)
print(cell.nameLabel.text)
if datesOfEvents[date]![indexPath.row].state == MessageState.SENT {
cell.nameLabel.textColor = UIColor.blackColor()
}
else {
let currentDate = NSDate()
if datesOfEvents[date]![indexPath.row].time > currentDate {
cell.nameLabel.textColor = UIColor.blueColor()
}
else
{
cell.nameLabel.textColor = UIColor.redColor()
}
}
break;
}
index++
}
//cell.backgroundColor = UIColor(colorLiteralRed: 39, green: 185, blue: 200, alpha: 0)
//cell.textLabel?.textColor = UIColor(colorLiteralRed: 255, green: 255, blue: 255, alpha: 1)
cell.textLabel?.numberOfLines = 0;
return cell
}

I also had this problem in iOS 9.1. If you're only developing for one device family per storyboard, try unchecking "Use Size Classes" in the file inspector of the storyboard. It solved it for me.

Related

Update UI with Firebase Observe Data (Swift)

I am having a hard time updating the UI on my Swift app while observing a Firebase node. I have a red_value, a green_value, and a blue_value stored in firebase which is being fetched and used to construct a UIColor which is then used to update the background color of a button on my UI. I am successfully fetching the color values, but when i try to update the UI from within the observe closure, the color always turns out to be white and I can't figure out why.
My code can be found below for a better idea of what i am trying to accomplish when loading the view:
override func viewDidLoad() {
super.viewDidLoad()
self.charitiesReference.child(charityUsername!).observe(.value) {
snapshot in
let values = snapshot.value as! [String: Any]
let redValue = values["red_value"] as! CGFloat
let greenValue = values["green_value"] as! CGFloat
let blueValue = values["blue_value"] as! CGFloat
let charityColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1.0)
let ripplerFollowers = values["follower_ripplers"] as! [String: Bool]
if ripplerFollowers["\(self.username!)"] ?? false {
self.followOrFollowingButton.setTitle("Following", for: .normal)
//ERROR -> The line below is producing a white background on my button
self.followOrFollowingButton.backgroundColor = charityColor
} else {
self.followOrFollowingButton.setTitle("Follow", for: .normal)
self.followOrFollowingButton.backgroundColor = .clear
}
}
}
Update:
When I change self.followOrFollowingButton.backgroundColor = charityColor line to self.followOrFollowingButton.backgroundColor = UIColor(red: 0, green: 120, blue: 120, alpha: 1.0)
it works as intended, which means that something is going on with the redValue, greenValue, & blueValue variables
Thank you in advance for your help!
As it turned out, I had forgotten to divide each of the color values by 255 to put them in the 0.0 - 1.0 range. if the value is above 1.0, it is set to 1.0, which resulted in the white color.
After dividing by 255, it's working like a charm

Change UITextView text by using its tag number to identify the element due for change

//UITextView Creation
let textarea = UITextView (frame : CGRect (x: 40, y: 100 ,width:100 , height:100))
textarea.delegate = self
textarea.tag = self.numarr
textarea.backgroundColor = UIColor(red: 0.9686, green: 0.9686, blue: 0.9686, alpha: 1.0)
textarea.layer.cornerRadius = 20.0
textarea.contentInset = UIEdgeInsetsMake(5, 5, 5, 5);
textarea.layer.masksToBounds = true
self.scrollviewxp.addSubview(textarea)
//Later after, the button function
#IBAction func loadbutton(_ sender: Any) {
if let hellatextview = self.scrollviewxp.viewWithTag(index) as? UITextView
{
hellatextview.text = "success"
}
}
The above code is not flagged as an error on Xcode but doesn't change the UITextView (hellatextview) value upon execution. A textView with a tag number (index) exists but isn't being changed.
Any ideas why it isn't working? Ive had the same issue with UIButtons
You only need to make sure that the scrollviewxp is the very
superview for the view trying to get with tag.
Otherwise, there is absolutely 0 reasons to fail.
SWIFT 4 Working solutions:
1.
if let hellaTextView = scrollviewxp.subviews.first(where: { $0.tag == index }) as? UITextView {
hellaTextView.text = "success"
}
or
2.
for subview in scrollviewxp.subviews
{
if let hellatextview.text = subview as? UITextView
{
if hellatextview.tag == index {
hellatextview.text = "success"
}
}
}

UIView Not Rounded, UITableView Cell Recycling

I have a UIView within the cell of a UITableView. My cellForRowAtIndexPath rounds that view. When I open the viewcontroller and see the table, all the visible views are rounded. However, when I scroll down, the first new cell to appear does not have a rounded view. How do I fix it?
My cellForRowAtIndex looks like this:
let cell = tableView.dequeueReusableCell(withIdentifier: "RepeatingCell", for: indexPath) as! CustomTableViewCell
cell.delegate = self
tableView.contentInset = UIEdgeInsetsMake(10, 0, 0, 0)
if (indexPath as NSIndexPath).row < tableListInfo_Context.count {
let task = tableListInfo_Context[(indexPath as NSIndexPath).row
let accState = task.value(forKey: "state") as? String
//Removed assigning labels their text
let mainView = cell.mainView
mainView.isHidden = false
let circleView = cell.viewToRound
circleView?.isHidden = false
circleView?.layer.cornerRadius = (circleView?.frame.size.width)!/2
circleView?.layer.masksToBounds = true
cell.layoutMargins = UIEdgeInsetsMake(0, 1000, 0, 1000)
} else {
//My last cell hides several views to reveal a view under them
//If I comment this one line out, I get the not-rounded problem only once and it does not show up again even if I continue scrolling up / down
let mainView = cell.mainView
mainView.isHidden = true
let circleView = cell.viewToRound
circleView?.isHidden = true
}
I understand that UITableViews recycle cells and I think that's likely causing me problems. I think it's related to that last cell where I hide views.
In a list of 20 cells, sometimes a non-rounded view shows up as the first to scroll on screen, sometimes the second. As I scroll up/down, randomly a view isn't rounded! I know there's a reason/pattern, but I don't know what.
I also tried adding the rounding code to willDisplayCell:
let circleView = myCell.mainCircle
circleView?.layer.cornerRadius = (circleView?.frame.size.width)!/2
circleView?.layer.masksToBounds = true
However, that did not solve it. How inconsistent this is is very frustrating. Any help would be appreciated.
FULL CODE AS REQUESTED BY DUNCAN:
func buildCell_RepeatableCell (indexPath: IndexPath) -> CustomTableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RepeatingCell", for: indexPath) as! CustomTableViewCell
cell.delegate = self
tableToSV_Left.constant = 10
tableToSV_Right.constant = 10
tableView.contentInset = UIEdgeInsetsMake(10, 0, 0, 0)
if (indexPath as NSIndexPath).row < curLifeList_Context.count {
resetDataCell_ToDefaultLaylout(cell: cell, hideExpand: true)
let task = curLifeList_Context[(indexPath as NSIndexPath).row]
let accState = task.value(forKey: "state") as? String
cell.nameLabel!.text = task.value(forKey: "name") as? String
cell.descLabel!.text = task.value(forKey: "desc") as? String
let redTrashIcon = UIImage(named: "trash")
let maskedIcon = redTrashIcon?.maskWithColor(color: .red)
cell.row5_LeftBtnImg?.image = maskedIcon
let doneGreen = UIColor(colorLiteralRed: 83/255, green: 223/255, blue: 56/225, alpha: 0.9)
let greenCheck = UIImage(named: "check_Green")
let maskedCheck = greenCheck?.maskWithColor(color: doneGreen)
cell.row5_RightBtnImg?.image = maskedCheck
roundQtyCircle(view: cell.mainCircle)
if accState == "Selected" {
cell.circleLine.backgroundColor = doneGreen
cell.mainCircle.borderColor = doneGreen
cell.hdrCrossOutLine.isHidden = false
cell.row5_RightBtnImg.alpha = 0.5
} else {
cell.circleLine.backgroundColor = UIColor(colorLiteralRed: 211/255, green: 211/255, blue: 211/255, alpha: 0.9)
cell.mainCircle.borderColor = UIColor(colorLiteralRed: 211/255, green: 211/255, blue: 211/255, alpha: 0.9)
cell.hdrCrossOutLine.isHidden = true
cell.row5_RightBtnImg.alpha = 1.0
}
cell.dataHdr_Left!.text = doneColon_lczd
cell.dataHdr_Right!.text = lastDoneColon_lczd
cell.dataVal_Left!.text = "0"
cell.dataVal_Right!.text = "-"
if let lastCompDate = task.value(forKey: "lastCompleted") as? Date {
cell.dataVal_Left!.text = "\(task.value(forKey: "timesCompleted") as! Int)"
if NSCalendar.current.isDateInToday(lastCompDate) {
cell.dataVal_Right!.text = "Today"
cell.dataBotDtl_Right.text = ""
} else {
let secondsUntilChange = (lastCompDate.seconds(from: now)) * -1
print("Seconds ago \(secondsUntilChange)")
var timeAgo = getDateString(secondsUntilChange, resetDate: lastCompDate)
timeAgo.remove(at: timeAgo.startIndex)
cell.dataVal_Right!.text = timeAgo
}
}
cell.layoutMargins = UIEdgeInsetsMake(0, 1000, 0, 1000)
} else {
buildAddNew_ForRepeatableCell(cell: cell)
}
return cell
}
func resetDataCell_ToDefaultLaylout (cell: CustomTableViewCell, hideExpand: Bool) {
cell.addnewBtn.isHidden = true
cell.nameLabel.isHidden = false
cell.dataHdr_Left.isHidden = false
cell.dataHdr_Right.isHidden = false
cell.dataTopDtl_Right.isHidden = false
cell.dataBotDtl_Right.isHidden = false
cell.mainBox.isHidden = false
}
func buildAddNew_ForRepeatableCell (cell: CustomTableViewCell) {
cell.addnewBtn.isHidden = false
cell.descLabel.text = addNew_lczd //For editor
cell.mainBox.isHidden = true
cell.layoutMargins = UIEdgeInsetsMake(0, 1000, 0, 1000)
cell.container.layoutIfNeeded()
}
Instead of setting layer properties of the view in cellForRowAtIndexPath, set them in your CustomTableViewCell class. You can set them in awakeFromNib Method.
In short move your below code to awakeFromNib.
let circleView = cell.viewToRound
circleView?.layer.cornerRadius = (circleView?.frame.size.width)!/2
circleView?.layer.masksToBounds = true
The sudo code could be something like this:
awakeFromNib(){
self.viewToRound?.layer.cornerRadius = (viewToRound?.frame.size.width)!/2
viewToRound?.layer.masksToBounds = true
}
#Adeel already told you the problem and the solution in his comment.
You always need to fully configure your cells in every case. Remember that when you get a recycled cell, it might be in any possible leftover state.
In your case, the key bit is:
if (indexPath as NSIndexPath).row < tableListInfo_Context.count {
//Configure cells that are not the last cell
} else {
//Configure cells the last cell
mainView.isHidden = true
}
You hide mainView in the case where you're configuring the last cell, but don't un-hide it if it's not the last cell. So, if you configure the last cell, scroll it off-screen, then scroll back towards the top of the screen, that recycled cell will get reused for an indexPath other than the last one, and it's mainView will never get un-hidden.
if (indexPath as NSIndexPath).row < tableListInfo_Context.count {
//Configure cells that are not the last cell
//-----------------------------
// This is what you are missing
mainView.isHidden = false
//-----------------------------
} else {
//Configure cells the last cell
mainView.isHidden = true
}
#VishalSonawane's answer is good, but to make that work you should use 2 different identifiers, one for all cells but the last one, and a different identifier, with a cell pre-configured with mainView hidden, for the last cell. That way you won't get a recycled last cell and try to use it for one of the other positions in your table view.
Try this, it will work.
override func awakeFromNib() {
super.awakeFromNib()
self.viewToRound?.layer.cornerRadius = (viewToRound?.frame.size.width)!/2
viewToRound?.layer.masksToBounds = true
}
override func prepareForReuse() {
super.prepareForReuse()
self.viewToRound?.layer.cornerRadius = (viewToRound?.frame.size.width)!/2
viewToRound?.layer.masksToBounds = true
}

how to hide label?

As you can see, i have a list of collection view here, and some product are having promotion price and some are not. For those product which having promotion, it will display the red colour price with the actual price strike through with it(beside). The problem now is, i was passing all these value from previous view using segue, now i have to hide promotion price label for those product which not having promotion price, how should i do it?
hide label
Here is the code:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! SubCategoryDetailsCollectionViewCell
let grey = UIColor(red: 85.0/255.0, green: 85.0/255.0, blue: 85.0/255.0, alpha: 1.0)
cell.layer.borderWidth = 1.0
cell.layer.borderColor = grey.CGColor
cell.titleLabel.text = name[indexPath.row]
cell.imageView.sd_setImageWithURL(NSURL(string: thumbImg1[indexPath.row] ))
I try to hide the label in this way, but its not really working,
it work for awhile and after i start scrolling my collection view, all promo label is hidden
if promo[indexPath.row] == "0"{
cell.promoLabel.hidden = true
}else{
cell.promoLabel.text = "RM" + promo[indexPath.row]
}
cell.priceLabel.text = "RM" + price[indexPath.row]
cell.productLabel.text = label[indexPath.row]
cell.setNeedsDisplay()
return cell
}
try this
if promo[indexPath.row] == "0"{
cell.promoLabel.hidden = true
}else{
cell.promoLabel.hidden = false
cell.promoLabel.text = "RM" + promo[indexPath.row]
}
cell.productLabel.text = label[indexPath.row]
cell.setNeedsDisplay()
return cell
}
You can hide label by changing alpha value also. Try
cell.priceLabel.alpha = 0 //to hide
cell.priceLabel.alpha = 1.0 //to show
This problem occurs because of cell reusing
Try this code:
if promo[indexPath.row] == "0" {
cell.promoLabel.hidden = true
}
else {
cell.promoLabel.hidden = false
cell.promoLabel.text = "RM" + promo[indexPath.row]
}

Shadows in tableview keep stacking (Swift)

I currently have a list of 70 questions in a tableview. Once a question is solved, the table is updated and shows a checkmark (all works OK).
The issue I am having is with the shadow that I add to each of my cells in the tableview. For some reason they keep stacking when scrolling up and down. Also when putting the device in landscape, the new CGRect is drawn, but the old one is still there (also overlap).
The code:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:QuestionCell = tableView.dequeueReusableCellWithIdentifier("cell") as! QuestionCell
let bgColorView = UIView()
bgColorView.frame = CGRectMake(5, 5, (tableView.frame.width)-10, (cell.frame.height)-10)
bgColorView.backgroundColor = UIColor.clearColor();
cell.selectedBackgroundView = bgColorView
let myBackView=UIView(frame:cell.frame)
myBackView.frame = CGRectMake(5, 5, (tableView.frame.width)-10, (cell.frame.height)-10)
myBackView.backgroundColor = UIColor.whiteColor();
myBackView.layer.masksToBounds = false
myBackView.clipsToBounds = false
myBackView.layer.cornerRadius = 3
myBackView.layer.shadowOffset = CGSizeMake(-1, 1)
myBackView.layer.shadowRadius = 2
myBackView.layer.shadowOpacity = 0.4;
let test:CGRect = myBackView.layer.bounds
myBackView.layer.shadowPath = UIBezierPath(rect: test).CGPath
cell.addSubview(myBackView)
cell.sendSubviewToBack(myBackView)
if (question.showAfter == "true") {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
//give header of correct question blue color
cell.backgroundColor = UIColor.lightTextColor()
cell.headerQuestion.textColor = UIColor(red:0.01, green:0.53, blue:0.82, alpha:1.0)
}
else
{
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
cell.backgroundColor = UIColor.whiteColor()
cell.headerQuestion.textColor = UIColor(red:0.38, green:0.49, blue:0.55, alpha:1.0)
}
return cell
}
I have already tried the following (it was a solution from someone on an objective-C topic):
let tag = 120
if (cell.tag != 120) {
//the above code here
cell.tag = tag
}
This solves the shadow issue, BUT when I turn the device to landscape mode it does not redraw.
Any ideas? All are welcome
Your adding a new shadow every time a cell is reused. You should only add the shadow once at creation time.
Make a subclass of UITableViewCell and do your common customizations (background color, shadow) there. Then register your class with the tableview. Only do stuff that's different per cell in tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
Try this :
if(cell.viewWithTag(120)==nil)
{
let myBackView=UIView(frame:cell.frame)
myBackView.frame = CGRectMake(5, 5, (tableView.frame.width)-10, (cell.frame.height)-10)
myBackView.backgroundColor = UIColor.whiteColor();
myBackView.layer.masksToBounds = false
myBackView.clipsToBounds = false
myBackView.layer.cornerRadius = 3
myBackView.layer.shadowOffset = CGSizeMake(-1, 1)
myBackView.layer.shadowRadius = 2
myBackView.layer.shadowOpacity = 0.3;
let test:CGRect = myBackView.layer.bounds
myBackView.layer.shadowPath = UIBezierPath(rect: test).CGPath
myBackView.tag = 120;
cell.addSubview(myBackView)
}
cell.sendSubviewToBack(myBackView)

Resources