Shadow rate on UITableViewCell contenview increasing while scrolling - ios

In my app, I'm using dynamic height cells using auto layout. So for creating cardview effect I've to use tableview willdisplaycell method. It only add shadow only once to cell. But I don't know why shadow increasing while scrolling.
Here's my code
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
//setup card view style on cell
if !cellArray.contains(indexPath.row) {
cell.contentView.backgroundColor = UIColor.clear
let whiteRoundedView : UIView = UIView(frame: CGRect(x: 5.0, y: 5.0, width: cell.contentView.frame.size.width-10, height: cell.contentView.frame.size.height-10))
whiteRoundedView.layer.backgroundColor = UIColor.white.cgColor
whiteRoundedView.layer.masksToBounds = false
whiteRoundedView.layer.cornerRadius = 5.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1, height: 1)
whiteRoundedView.layer.shadowOpacity = 0.5
cell.contentView.addSubview(whiteRoundedView)
cell.contentView.sendSubview(toBack: whiteRoundedView)
cellArray.add(indexPath.row)
}
}

this piece of line is the causing the issue.
cell.contentView.addSubview(whiteRoundedView)
whenever willDisplayCell gets called, you will be adding the view everytime. That is the reason shadow is getting increased while scrolling. The solution is,
1. check the cell content view if the view is already added or not. If not, then add the view. use view tag to do it.
2. otherwise, create a shadow view and initialize the specific things in the -(void)awakeFromNib, which will get called only once.
but personally, i prefer option 2, which will isolate your view render logic from view controller or cell.
add the below code to your custom cell class. In this case, i have given leading-trialing-top-bottom constraints as 15-15-15-15. If you wish you can set it to 0. but make sure that it should in sync with the background constraints.
override func awakeFromNib() {
super.awakeFromNib()
contentView.backgroundColor = UIColor.clear
let whiteRoundedView : UIView = UIView(frame: CGRect(x: 5.0, y: 5.0, width: contentView.frame.size.width-10, height: contentView.frame.size.height-10))
whiteRoundedView.layer.backgroundColor = UIColor.white.cgColor
whiteRoundedView.layer.masksToBounds = false
whiteRoundedView.layer.cornerRadius = 5.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1, height: 1)
whiteRoundedView.layer.shadowOpacity = 0.5
whiteRoundedView.tag = shadowTag
whiteRoundedView.translatesAutoresizingMaskIntoConstraints=false
contentView.addSubview(whiteRoundedView)
contentView.sendSubview(toBack: whiteRoundedView)
let leading = NSLayoutConstraint(item: whiteRoundedView,
attribute: .leading,
relatedBy: .equal,
toItem: contentView,
attribute: .leading,
multiplier: 1.0,
constant: 15.0)
let trailing = NSLayoutConstraint(item: whiteRoundedView,
attribute: .trailing,
relatedBy: .equal,
toItem: contentView,
attribute: .trailing,
multiplier: 1.0,
constant: -15.0)
let top = NSLayoutConstraint(item: whiteRoundedView,
attribute: .top,
relatedBy: .equal,
toItem: contentView,
attribute: .top,
multiplier: 1.0,
constant: 15.0)
let bottom = NSLayoutConstraint(item: whiteRoundedView,
attribute: .bottom,
relatedBy: .equal,
toItem: contentView,
attribute: .bottom,
multiplier: 1.0,
constant: -15.0)
contentView.addConstraint(leading)
contentView.addConstraint(trailing)
contentView.addConstraint(top)
contentView.addConstraint(bottom)
}
Ref screenshot :

You can add your code here
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: <idenitfier>, for: indexPath) as? JobListTableViewCell
if cell == nil {
//Initialization and setting of shadow
}
return cell
}
Hope this helps

Related

Add UIView to ContentView in a TableViewCell using constraints

I am trying to add cells to UITableView using Constraints. Do you know how. The following just gives:
And says: Height is ambiguous for UIView
Do you know how to add a UIView to ContextView using constraints - note the fixed height in the constraints.
import UIKit
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier:"Cell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
}
let view = UIView(frame: cell!.frame)
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.orange
let constraintTop = NSLayoutConstraint(item: cell!.contentView,
attribute: NSLayoutAttribute.top,
relatedBy: NSLayoutRelation.equal,
toItem: view,
attribute: NSLayoutAttribute.top,
multiplier: 1,
constant: 0)
let constraintLeading = NSLayoutConstraint(item: cell!.contentView,
attribute: NSLayoutAttribute.leading,
relatedBy: NSLayoutRelation.equal,
toItem: view,
attribute: NSLayoutAttribute.leading,
multiplier: 1,
constant: 0)
let constraintTrailing = NSLayoutConstraint(item: cell!.contentView,
attribute: NSLayoutAttribute.trailing,
relatedBy: NSLayoutRelation.equal,
toItem: view,
attribute: NSLayoutAttribute.trailing,
multiplier: 1,
constant: 0)
let constraintHeight = NSLayoutConstraint(item: cell!.contentView,
attribute: NSLayoutAttribute.height,
relatedBy: NSLayoutRelation.equal,
toItem: nil,
attribute: NSLayoutAttribute.height,
multiplier: 1, constant: 50) // << Note fixed height
view.translatesAutoresizingMaskIntoConstraints = false
cell?.contentView.addSubview(view)
cell?.contentView.addConstraints([constraintTop, constraintLeading, constraintTrailing, constraintHeight])
return cell!
}
}
Tried to change constraints to include bottom of the contentView:
import UIKit
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier:"Cell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
}
let view = UIView(frame: cell!.frame)
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.orange
let constraintTop = NSLayoutConstraint(item: cell!.contentView,
attribute: NSLayoutAttribute.top,
relatedBy: NSLayoutRelation.equal,
toItem: view,
attribute: NSLayoutAttribute.top,
multiplier: 1,
constant: 0)
let constraintLeading = NSLayoutConstraint(item: cell!.contentView,
attribute: NSLayoutAttribute.leading,
relatedBy: NSLayoutRelation.equal,
toItem: view,
attribute: NSLayoutAttribute.leading,
multiplier: 1,
constant: 0)
let constraintTrailing = NSLayoutConstraint(item: cell!.contentView,
attribute: NSLayoutAttribute.trailing,
relatedBy: NSLayoutRelation.equal,
toItem: view,
attribute: NSLayoutAttribute.trailing,
multiplier: 1,
constant: 0)
let constraintBottom = NSLayoutConstraint(item: cell!.contentView,
attribute: NSLayoutAttribute.bottom,
relatedBy: NSLayoutRelation.equal,
toItem: view,
attribute: NSLayoutAttribute.bottom,
multiplier: 1, constant: 0)
view.translatesAutoresizingMaskIntoConstraints = false
cell?.contentView.translatesAutoresizingMaskIntoConstraints = false
cell?.contentView.addSubview(view)
cell?.contentView.addConstraints([constraintTop, constraintLeading, constraintTrailing, constraintBottom])
return cell!
}
}
You're doing a couple things wrong.
First, you are setting the constraints backward. You want to constrain your new view to the contentView:
let constraintTop = NSLayoutConstraint(item: view, // constrain this view
attribute: NSLayoutAttribute.top,
relatedBy: NSLayoutRelation.equal,
toItem: cell?.contentView, // to this view
attribute: NSLayoutAttribute.top,
multiplier: 1,
constant: 0)
Second, don't do this:
cell?.contentView.translatesAutoresizingMaskIntoConstraints = false
Third, your code is (well, will be) adding a new "orange view" every time the cell is reused. Much better to add subviews in the init portion of a custom cell class, but if you're going to do it in cellForRow, check if it's already there first:
if cell.contentView.subviews.count == 0 {
// no, so add it here
let view = UIView()
// continue with view setup
Fourth, you may find it easier / more logical / cleaner / etc to add constraints this way:
cell.contentView.addSubview(view)
view.topAnchor.constraint(equalTo: cell.contentView.topAnchor, constant: 0.0).isActive = true
view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor, constant: 0.0).isActive = true
view.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: 0.0).isActive = true
view.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: 0.0).isActive = true
And... since you have registered a cell class for reuse, this format will give you a valid cell:
// instead of this
//var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
//if cell == nil {
// cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
//}
// better method
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
So, here is the full function:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
// have we already added the subview?
if cell.contentView.subviews.count == 0 {
// no, so add it here
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.orange
cell.contentView.addSubview(view)
view.topAnchor.constraint(equalTo: cell.contentView.topAnchor, constant: 0.0).isActive = true
view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor, constant: 0.0).isActive = true
view.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: 0.0).isActive = true
view.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: 0.0).isActive = true
}
return cell
}
Your fourth constraint is applying a fixed height to the contentView. What you want instead is to pin the bottom edges of the contentView and your custom view (like you did with leading/top/trailing) and apply the constant height constraint to view, not contentView. contentView simply adapts to its subviews, you don't tell it its height directly.
Additionally, in your viewDidLoad, you'll want to set your tableView.rowHeight = UITableViewAutomaticDimension, since you're calculating the height via constraints.
Also, you will run into problems because this code is in cellForRow. This function is called every time a new cell comes onscreen, which means as you scroll, you're going to reuse the same views and have duplicate extra views added. I recommend you subclass UITableViewCell and put this code in its init.
Well, the solutions is: Read the "Output"!
Changing the translatesAutoresizingMaskIntoConstraints property of the contentView of a UITableViewCell is not supported and will result in undefined behavior, as this property is managed by the owning UITableViewCell
Having the following messed it all up:
cell?.contentView.translatesAutoresizingMaskIntoConstraints = false
Remove this line and it will work.

UITableViewAutomaticDimension with programmatically added images

I have a problem with UITableViewAutomaticDimension:
In my tableview I have multiple imageviews created programmatically with calculated height:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "managePlayset", for: indexPath) as! ManagePlaysetTableViewCell
let playset = playsets[indexPath.row]
cell.playsetName.text = playset.name
if (playset.musicItems?.count)! > 0 {
var i = 0
for musicItem in (playset.musicItems?.array)! {
let imageView = UIImageView(image: (musicItem as! MusicItem).getFirstPhoto())
imageView.frame = CGRect(x: cell.contentView.frame.origin.x+CGFloat(i)*(imageWidth+10.0), y: cell.contentView.frame.origin.y+40, width: imageWidth, height: imageWidth)
imageView.contentMode = .scaleAspectFit
cell.contentView.addSubview(imageView)
let constraint = NSLayoutConstraint(item: imageView,
attribute: NSLayoutAttribute.bottomMargin, relatedBy:
NSLayoutRelation.equal, toItem: cell.contentView,
attribute: NSLayoutAttribute.bottomMargin, multiplier: 1,
constant: 0)
cell.contentView.addConstraint(constraint)
i = i + 1
}
}
cell.editButton.tag = indexPath.row
return cell
}
In viewDidLoad I set:
let width = view.frame.width
imageWidth = width / CGFloat(maxItemsOnPage) - 10.0
tableView.estimatedRowHeight = imageWidth + 20.0
tableView.rowHeight = UITableViewAutomaticDimension
But height is not adjusted properly (images are cut off)
Any advice is highly appreciated!
I think it's because UIImageView created programmatically.
Then it don't use autolayout system.
To change it, you have to add
imageView.translatesAutoresizingMaskIntoConstraints = false in your loop.
Have you tried constraining both top and bottom edges of the imageView? i.e.
let constraintTop = NSLayoutConstraint(item: imageView,
attribute: NSLayoutAttribute.top, relatedBy:
NSLayoutRelation.equal, toItem: cell.contentView,
attribute: NSLayoutAttribute.topMargin, multiplier: 1,
constant: 0)
let constraintBottom = NSLayoutConstraint(item: imageView,
attribute: NSLayoutAttribute.bottom, relatedBy:
NSLayoutRelation.equal, toItem: cell.contentView,
attribute: NSLayoutAttribute.bottomMargin, multiplier: 1,
constant: 0)
cell.contentView.addConstraints([constraintTop, constraintBottom])

AutoLayout issue UITable View header section: Adding image in the left does not works fine

I have added a custom image to my UITableView header section. It's working fine when the screen is in portrait mode. Large gap appears in landscape mode. Can any one help me out?
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerView = UIView(frame: CGRect(x: 1, y: 1, width: tableView.frame.width, height: 40))
var myLabel = UILabel()
myLabel.frame = CGRectMake(0, 0, tableView.frame.width - 70, 40)
print(myLabel.frame)
myLabel.font = UIFont.boldSystemFontOfSize(18)
myLabel.backgroundColor = UIColor.blueColor()
myLabel.text = self.tableView(tableView, titleForHeaderInSection: section)
let button = UIButton(frame: CGRect(x: 230,y: 0,width: 100,height: 40))
button.tag = section
button.backgroundColor = UIColor.clearColor()
headerView.addSubview(button)
headerView.addSubview(myLabel)
headerView.backgroundColor = UIColor.clearColor()
// the button is image - set image
button.setImage(UIImage(named: "icoDraft"), forState: UIControlState.Normal)
let tapOnCardCell: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(HHLabTestExaminationViewController.handleTapOnSectionImage(_:)))
button.addGestureRecognizer(tapOnCardCell)
return headerView
}
Now the title for header sections are
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if(section == 0)
{
return "Exam"
}
else if(section == 1)
{
return "News"
}
else if(section == 2)
{
return "Movie"
}
else if(section == 3)
{
return "Sport"
}
return ""
}
This image is my output when the screen is in portrait orientation:
This is when the screen is in landscape orientation. How can i fix this gap in landscape?
I don't see any autolayout code when you set up this header view. However, this simple layout can be handled without autolayout.
headerView.autoResizesSubviews = true
myLabel.autoResizingMask = [.flexibleWidth, .flexibleHeight]
button.autoResizingMask = .flexibleLeftMargin
As #DaveWeston says, there is no auto layout code, and his answer should work fine. If you want auto layout, here is what it would look like for the button.
(Note this is Swift 3 vs. 2.x in the OP's code).
let button = UIButton()
button.tag = section
button.backgroundColor = UIColor.clear
headerView.addSubview(button)
// Autolayout for button
button.translatesAutoresizingMaskIntoConstraints = false
button.addConstraint(NSLayoutConstraint.init(item: button,
attribute: .height,
relatedBy: .equal,
toItem: headerView,
attribute: .height,
multiplier: 1.0,
constant: 0.0))
button.addConstraint(NSLayoutConstraint.init(item: button,
attribute: .width,
relatedBy: .equal,
toItem: nil,
attribute: .width,
multiplier: 1.0,
constant: 40.0))
button.addConstraint(NSLayoutConstraint.init(item: button,
attribute: .trailing,
relatedBy: .equal,
toItem: headerView,
attribute: .trailing,
multiplier: 1.0,
constant: 0.0))
button.addConstraint(NSLayoutConstraint.init(item: button,
attribute: .centerY,
relatedBy: .equal,
toItem: headerView,
attribute: .centerY,
multiplier: 1.0,
constant: 0.0))

Can't add constraints between UICollectionView cell and the cell subview

After I run my app, it crashes:
Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal.
My image is subview of the cell.
What am I doing wrong?
let image = UIImageView(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
image.image = UIImage.init(named: "Bitmap")
cell.contentView.addSubview(image)
let bottomConstr = NSLayoutConstraint(item: image, attribute: .bottom, relatedBy: .equal, toItem: cell.contentView, attribute: .bottom, multiplier: 1, constant: 0)
//let leftConstr = NSLayoutConstraint(item: image, attribute: .leading, relatedBy: .equal, toItem: cell.contentView, attribute: .leading, multiplier: 1, constant: 0)
//let rightConstr = NSLayoutConstraint(item: image, attribute: .trailing, relatedBy: .equal, toItem: cell.contentView, attribute: .trailing, multiplier: 1, constant: 0)
let heightConstr = NSLayoutConstraint(item: image, attribute: .height, relatedBy: .equal, toItem: nil , attribute: .notAnAttribute, multiplier: 1, constant: 10)
image.addConstraint(bottomConstr)
//image.addConstraint(leftConstr)
//image.addConstraint(rightConstr)
image.addConstraint(heightConstr)
You need to add constraint on Superview. so, add it on cell contentView.
cell.contentView.addConstraint(bottomConstr)
cell.contentView.addConstraint(heightConstr)
Constraints weren't working well for me when zooming UICollectionView. Here's how I resized a label to always fill the cell.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mycell", for: indexPath as IndexPath) as! SliceCollectionViewCell
cell.label.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
func collectionView(_ collectionView: UICollectionView,
willDisplay cell: UICollectionViewCell,
forItemAt indexPath: IndexPath) {
guard let cell = cell as? MyCollectionViewCell else {
print("ERROR: wrong cell type")
return
}
cell.label.frame = CGRect(x: 0, y: 0, width: cell.frame.width, height: cell.frame.height)
}

Add and layout subviews loaded from xib to a custom cell

I have a custom cell 'CustomCell' that I wish to compose based on a custom data element.
I am trying to add subviews to CustomCell but for those subviews loaded from a xib (https://stackoverflow.com/a/26326006/3546621), I can't figure out how to layout them into the cell's contentView; i.e programmatically setting their frame nor adding constraints seem to work. ( CustomCell has no xib attached, every subviews is loaded programmatically. Some of these subview are loaded from xib.)
For example, here is my custom cell. It has two subviews, a yellowView initialized with UIView(frame: CGRect()) and right below a blueView initialized with UIView.fromNib.
This is BlueView.xib
I am not succeeding at placing blueView below yellowView, instead I have the blueView being stacked on top of the yellowView:
class CustomCell: UITableViewCell {
let yellowView: UIView = UIView()
let blueViewFromXib: BlueView = UIView.fromNib()
override init(style: UITableViewCellStyle, reuseIdentifier: String?){
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
fun configureForData(custom: Custom){
yellowView.backgroundColor = UIColor.yellowColor()
yellowView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(yellowView)
blueView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(blueView)
layoutIfNeeded()
}
override func layoutSubviews() {
super.layoutSubviews()
let height = NSLayoutConstraint(item: contentView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 80)
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.addConstraint(height)
yellowView.frame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: 40)
// I want to add the blueView at the bottom of the yellowView
// Option 1: not working
blueView.frame = CGRect(x: 0, y: 40, width: contentView.frame.width, height: 40)
// Option 2: not working
let top = NSLayoutConstraint(item: blueView, attribute: .Top, relatedBy: .Equal, toItem: contentView, attribute: .Top, multiplier: 1, constant: 40)
let bottom = NSLayoutConstraint(item: blueView, attribute: .Bottom, relatedBy: .Equal, toItem: contentView, attribute: .Bottom, multiplier: 1, constant: 0)
let leading = NSLayoutConstraint(item: blueView, attribute: .Leading, relatedBy: .Equal, toItem: contentView, attribute: .Leading, multiplier: 1, constant: 0)
let trailing = NSLayoutConstraint(item: blueView, attribute: .Trailing, relatedBy: .Equal, toItem: contentView, attribute: .Trailing, multiplier: 1, constant: 0)
contentView.addConstraints([top, bottom, leading, trailing])
}
}
class BlueView: UIView {
// the project includes a BlueView.xib which is simply a UIView whose background color is blue
}
View Controller
override func viewDidLoad(){
super.viewDidLoad()
tableView.delegate = self
tableView.datasource = self
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 80
tableView.registerClass(CustomCell.self, forCellReuseIdentifier: "CustomCell")
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let custom = customs[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomCell
cell.configureForData(custom)
return cell
}
A couple things to be aware of
In layoutSubviews you shouldn't be adding/removing constraints that don't change. If you set the constraints, the default implementation (super.layoutSubviews()) will adjust the size/layout based on the constraints.
If you set constraints, they override any frames that were set.
blueView.frame = UIView(frame: CGRect(x: 0, y: 40, width: contentView.frame.width, height: 40)) shouldn't even compile. You're setting blueView's frame (a CGRect) to a new instance of UIView.
Regardless, it appears you're using layoutConstraints for blueView, and manually setting the frame for yellowView. I'm guessing if you use one of these you will be able to work out what's going on.
To simplify things, try setting your subViews to optionals:
let yellowView: UIView?
let blueViewFromXib: BlueView?
Then comment out layoutSubviews, and use this:
func configureForData(custom: Custom){
if yellowView == nil {
yellowView = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.width, height: 40))
yellowView?.backgroundColor = UIColor.yellowColor()
self.addSubview(yellowView)
}
if blueView == nil {
blueView = BlueView.fromNib()
blueView?.frame = CGRect(x: 0, y: 40, width: self.frame.width, height: 40)
self.addSubview(blueView)
}
}

Resources