Cant satisfy constrains in TableViewCell - ios

I have TableViewCell with this prototype.
When user select "No" in segmented control, textView for comment should appear. I have created a QuestionTableViewCell class:
class QuestionTableViewCell: UITableViewCell {
#IBOutlet weak var question: UILabel!
#IBOutlet weak var answer: UISegmentedControl!
#IBOutlet weak var comment: UITextView!
// height constraint for comment textView
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
// spacing between segmentedControl bottom and comment textView top
#IBOutlet weak var spacingConstraint: NSLayoutConstraint!
}
Then in cellForRowAtIndexPath i set this constrains to satisfy my needs:
if questionsAnswers[indexPath.row] == "" || questionsAnswers[indexPath.row] == "YES" {
comments[indexPath.row] = ""
cell.heightConstraint.constant = 0.0
cell.spacingConstraint.constant = 0.0
} else {
cell.spacingConstraint.constant = 8
cell.heightConstraint.constant = 70.0
}
But when i click "No" in cell's textView i got these constrains collisions:
"<NSLayoutConstraint:0x7fa28311d030 V:[UITextView:0x7fa2818c1600'Add a note if necessary..'(70)]>",
"<NSLayoutConstraint:0x7fa283123930 UILabel:0x7fa283119f20'1. Question 1?'.top == UITableViewCellContentView:0x7fa283119de0.topMargin>",
"<NSLayoutConstraint:0x7fa283123a20 V:[UILabel:0x7fa283119f20'1. Question 1?']-(NSSpace(8))-[UISegmentedControl:0x7fa28311a8d0]>",
"<NSLayoutConstraint:0x7fa283123bd0 UITextView:0x7fa2818c1600'Add a note if necessary..'.bottom == UITableViewCellContentView:0x7fa283119de0.bottomMargin>",
"<NSLayoutConstraint:0x7fa283123c20 V:[UISegmentedControl:0x7fa28311a8d0]-(8)-[UITextView:0x7fa2818c1600'Add a note if necessary..']>",
"<NSLayoutConstraint:0x7fa280cb4e30 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fa283119de0(73.5)]>"
I think this constraint is breaking the layout:
"<NSLayoutConstraint:0x7fa280cb4e30 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fa283119de0(73.5)]>"
But i don't know how to fix this( Any ideas how it can be solved?

Related

Swift constraint doesnot change in Autolayout while hiding views

These are my codes
//My UIViews
#IBOutlet weak var UIVIewFirst: UIView!
#IBOutlet weak var UIViewSecond: UIView!
#IBOutlet weak var UIViewThird: UIView!
#IBOutlet weak var middleViewHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var ViewThirdHeight: NSLayoutConstraint!
There is a button to show and hide the view as;
#IBAction func infoClicked(sender: SSRadioButton) {
if UIViewSecond.hidden {
sender.selected = false
UIViewSecond.hidden = false
self.middleViewHeightConstraint.constant = 134
} else {
sender.selected = true
UIViewSecond.hidden = true
self.middleViewHeightConstraint.constant = 0
self.ViewThirdHeight.constant = 180
}
}
the vertical gap between each view is 10. After hiding the view the gap becomes 20. But i need it to set it 10 between third and second view. Even though i set the third view height constant to any number it does not changes it position.Can anyone suggest why is this happening??
Constraints ignore the hidden property.
If possible for your requirements, embedd your views within a UIStackView.
See this example.
You need to take the outlet connection of the vertical spacing constraint between either First-Second or Second-Third views. Also if you want to hide/show only Second view, you don't need to do any changes to Third View height constraint.
Say For example, we take the outlet of vertical spacing between First and Second views, then:
#IBOutlet weak var UIVIewFirst: UIView!
#IBOutlet weak var UIViewSecond: UIView!
#IBOutlet weak var middleViewHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var verticalSpacingConstraint: NSLayoutConstraint!
#IBAction func infoClicked(sender: UIButton)
{
if UIViewSecond.hidden
{
sender.selected = false
UIViewSecond.hidden = false
self.middleViewHeightConstraint.constant = 134
self.verticalSpacingConstraint.constant = 10
}
else
{
sender.selected = true
UIViewSecond.hidden = true
self.middleViewHeightConstraint.constant = 0
self.verticalSpacingConstraint.constant = 0
}
}
Below are the screenshots of output:
1. When button is not selected
2. When button is selected
You have not tell your view to update the view with the new constraint, you have to call this code:
self.view.layoutIfNeeded()
firstView
| gap = 10
secondView
| gap = 10
thirdView
after removing secondView
firstView
| gap = 10
---------- height = 0
| gap = 10
thirdView
so the gap becomes 20
try to add constraint programmatically after hiding the view or decrease any one gap.
Try to change the frame of the view instead of changing the constraint, also do view.layoutIfNeeded after making any changes.

2 Round Corners of a UIView in UITableViewCell not working

I am trying to create round corners for a UIView with in a custom TableViewCell. The problem is when the table view loads, it only rounds the Top Left corner of the view and not the bottom one. Now when i scroll the table view little bit, it rounds the bottom left part of the view as well.
I have tried every possible method but i can't get my head around it. I am also attaching the screenshots as well as copying the code. Thanks
The code that i am using in the custom view cell class is below.
class FoodTVCell: UITableViewCell {
var food: Food!
#IBOutlet weak var foodPicture: UIImageView!
#IBOutlet weak var foodName: UILabel!
#IBOutlet weak var foodRating: UIImageView!
#IBOutlet weak var deliveryTime: UILabel!
#IBOutlet weak var minOrder: UILabel!
#IBOutlet weak var category: UILabel!
#IBOutlet weak var foodPriceLabelBG: UIView!
#IBOutlet weak var foodPrice: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
foodPicture.layer.cornerRadius = 75/2
foodPicture.clipsToBounds = true
}
override func layoutSubviews() {
super.layoutSubviews()
let maskLayer = CAShapeLayer()
let corners = UIRectCorner.TopLeft.union(UIRectCorner.BottomLeft)
maskLayer.path = UIBezierPath(roundedRect: foodPriceLabelBG.bounds, byRoundingCorners: corners, cornerRadii: CGSizeMake(20.0, 20.0)).CGPath
foodPriceLabelBG.layer.mask = maskLayer
foodPriceLabelBG.clipsToBounds = true
}
}
Your 'corner rounding' code is working very well, the problem is that your UIView's bottom edge is going outside of your Cell's bottom edge. Decrease your UIView's Y position and it will be covered by your Cell. I see your cell's separator line invisible too, that means you should give larger height to your Cell at heightForRowAtIndexPath:
You said it's working very well on scrolling, I suppose it's working when scrolling down and not working when scrolling to top. It means that your first cell was redrawn after second while scrolling to the bottom (where the second cell doesn't cover your first cell), and vice versa while scrolling to the top (where second cell covers your first cell)

Reordering subviews programatically won't work in a tableViewCell

I'm trying to reorder an image and a stackview (here called labelsStack) that are both contained in another stackview (here called stack). My goald would be to programatically reverse the index order of both subviews in order to change their postition at runtime (they are horizontally distributed, so theorically, if I reorder their indexes, it should reorder them in autolayout)
I have tried to update indexes, exchange subviews, sendViewForward etc from the Apple doc, but it doesn t work, here s the code of my tableViewCell :
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func layoutSubviews() {
cellImage.layer.cornerRadius = cellImage.bounds.height / 3
cellImage.clipsToBounds = true
if incoming {
} else {
// as one of the many methods that didn't work
self.stack.insertSubview(cellImage, belowSubview: labelsStack)
}
}
You could create two alternative sets of constraints, one for the default order and the other for the inverse order. The default constraints are the one ending in 1
To initially deactivate the alternative setting you can use the inspector and change the installed checkbox
Your view controller should now have 6 outlets:
#IBOutlet weak var topViewTopConstraint1: NSLayoutConstraint!
#IBOutlet weak var bottomViewTopConstraint1: NSLayoutConstraint!
#IBOutlet weak var bottomViewBottomConstraint1: NSLayoutConstraint!
#IBOutlet weak var topViewTopConstraint2: NSLayoutConstraint!
#IBOutlet weak var bottomViewTopConstraint2: NSLayoutConstraint!
#IBOutlet weak var topViewBottomConstraint2: NSLayoutConstraint!
now to activate the other set of constraints you can use:
self.topViewBottomConstraint2.active = true
self.topViewTopConstraint2.active = true
self.bottomViewTopConstraint2.active = true
self.topViewTopConstraint1.active = false
self.bottomViewBottomConstraint1.active = false
self.bottomViewTopConstraint1.active = false
and viceversa

UILabel height depending on text

I am getting data from JSON and it changes for each view so I need the labels to change their height depending on their content and also the rest of labels and buttons should move down. I am using sizeToFit but anything else moves and when I scroll it loses its height and goes to 1 line again.
My labels have 0 lines in storyboard.
#IBOutlet weak var titulares: UILabel!
#IBOutlet weak var scroller: UIScrollView!
#IBOutlet weak var imagen: UIImageView!
#IBOutlet weak var estilo: UILabel!
#IBOutlet weak var historia: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// I get JSON Data
self.historia.sizeToFit()
self.titulares.sizeToFit()
self.estilo.sizeToFit()
Use autolayout
from the storyboard, press on a label and then in the right bottom side of the screen, you have the "Add new constrains" button.
Use it to set a spacing from a view to it's neighbors
https://developer.apple.com/library/tvos/documentation/UserExperience/Conceptual/AutolayoutPG/index.html

UIScrollView needs to expand based upon UILabel sizes but maintaining bottom tab bar

So I have a self made menu bar at the bottom of my ViewController that I need to keep constrained to the bottom of the screen. Between the navigation bar and the bottom bar I want a scroll view so I inserted a UIScrollView and within that scroll view I put a UIView. I did this because I was getting an error that was addressed with this thread:
UIScrollView Scrollable Content Size Ambiguity
So I have some labels that adjust in size based upon the text being used for the labels. I want the UIScrollView and also the associated UIView to adjust based upon how long the UILabels are. Right now I have it where the labels go below the bottom bar but the view isn't scrolling. Here is my code:
//
// ItemViewController.swift
//
import UIKit
import Parse
class ItemViewController: UIViewController {
#IBOutlet weak var menuButton: UIButton!
#IBOutlet weak var mainImage: UIImageView!
#IBOutlet weak var innerView: UIView!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var heading1: UILabel!
#IBOutlet weak var body1: UILabel!
#IBOutlet weak var heading2: UILabel!
#IBOutlet weak var body2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
for var y = 0; y < detailsHeadings.count; y++ {
switch y {
case 0:
heading1.text = detailsHeadings[y]
body1.text = details[heading1.text!]
let numLines = calcLines(body1.text!)
body1.numberOfLines = numLines!
break;
case 1:
heading2.text = detailsHeadings[y]
body2.text = details[heading2.text!]
let numLines = calcLines(body2.text!)
body2.numberOfLines = numLines!
break;
default:
break;
}
}
//none of the below worked
scrollView.sizeToFit()
scrollView.sizeThatFits(CGSize(width: 310, height: 700))
innerView.sizeThatFits(CGSize(width: 310, height: 700))
innerView.frame = CGRect(x: 0, y: 0, width: 320, height: 700)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func calcLines(textString: String) -> Int? {
let text = textString
// cast text to NSString so we can use sizeWithAttributes
var myText = text as NSString
//Set attributes
var attributes = [NSFontAttributeName : UIFont.systemFontOfSize(12)]
//Calculate the size of your UILabel by using the systemfont and the paragraph we created before. Edit the font and replace it with yours if you use another
var labelSize = myText.boundingRectWithSize(CGSizeMake(body1.bounds.width, CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: attributes, context: nil)
//Now we return the amount of lines using the ceil method
var lines = ceil(CGFloat(labelSize.height) / body1.font.lineHeight)
println(lines)
let linesInt: Int = Int(lines)
return linesInt
}
}
Does anyone have any idea how to achieve this? Any help would be greatly appreciated.
Try these steps:
Set all leading, trailing, top, and bottom constraints of your label to its superview and the superview's to the scrollView
Set your label's number of lines to 0 (unlimited)
Assuming that you're using autolayout since you're referring to UIScrollView content size ambiguity

Resources