title: Round UIView bottom corners inside custom UITableViewCell
body: <p>I'm trying to round the bottom corners of a custom view inside a tableview cell. The code I'm using it's not working and I don't understand why...</p>
  
  <p>So, I have a <code>UItableViewCell</code> and inside the <code>contentView</code> there is a custom view <code>containerView</code>. Inside that, on top, I have two labels and in the bottom another view. That view must have rounded bottom corners.</p>
  
  <p>My code:</p>
  
  <pre><code>class HomeTableViewCell: UITableViewCell {
  
  var containerView: UIView!
  var bottomDetailsView: UIView!
  var titleLabel: UILabel!
  var timeLabel: UILabel!
  
  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
      super.init(style: style, reuseIdentifier: "tableCell")
  
      containerView = UIView()
      bottomDetailsView = UIView()
      timeLabel = UILabel()
      titleLabel = UILabel()
  
  
      self.contentView.addSubview(containerView)
      containerView.addSubview(bottomDetailsView)
      containerView.addSubview(titleLabel)
      containerView.addSubview(timeLabel)
  
      containerView.snp.makeConstraints({ (maker) in
          maker.top.equalTo(self.contentView.snp.top)
          maker.bottom.equalTo(self.contentView.snp.bottom)
          maker.left.equalTo(self.contentView.snp.left).inset(10)
          maker.right.equalTo(self.contentView.snp.right).inset(10)
      })
  
      bottomDetailsView.snp.makeConstraints { (maker) in
          maker.top.equalTo(containerView.snp.centerY).offset(30)
          maker.left.equalTo(containerView.snp.left)
          maker.right.equalTo(containerView.snp.right)
          maker.bottom.equalTo(containerView.snp.bottom)
      }
  
      timeLabel.snp.makeConstraints { (maker) in
          maker.centerX.equalTo(containerView.snp.centerX)
          maker.centerY.equalTo(containerView.snp.centerY).offset(10)
      }
  
      titleLabel.snp.makeConstraints { (maker) in
          maker.left.equalTo(containerView.snp.left).inset(10)
          maker.top.equalTo(containerView.snp.top).inset(10)
          maker.right.equalTo(containerView.snp.right).inset(10)
      }
  }
  
  override func layoutSubviews() {
      super.layoutSubviews()
  
      bottomDetailsView.backgroundColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
      containerView.backgroundColor = #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)
      containerView.layer.cornerRadius = 15.0
      timeLabel.font = timeLabel.font.withSize(24)
      timeLabel.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
      titleLabel.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
  
      let path = UIBezierPath(roundedRect: bottomDetailsView.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 15, height: 15))
      let shapeLayer = CAShapeLayer()
      shapeLayer.frame = bottomDetailsView.frame
      shapeLayer.path = path.cgPath
      bottomDetailsView.layer.backgroundColor = UIColor.red.cgColor
      bottomDetailsView.layer.mask = shapeLayer
  }
  
  
  required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
  }
  }
  </code></pre>
  
  <p>I'm using <code>SnapKit</code> for the auto-layout. The problematic code is</p>
  
  <pre><code>let path = UIBezierPath(roundedRect: bottomDetailsView.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 15, height: 15))
  let shapeLayer = CAShapeLayer()
  shapeLayer.frame = bottomDetailsView.frame
  shapeLayer.path = path.cgPath
  bottomDetailsView.layer.backgroundColor = UIColor.red.cgColor
  bottomDetailsView.layer.mask = shapeLayer
  </code></pre>
  
  <p>I tried different combinations with this code, but can't get anything to work. It doesn't display absolutely nothing. If instead of <code>bottomDetailsView.layer.mask = shapeLayer</code> I write <code>bottomDetailsView.layer.addSublayer(shapeLayer)</code> the view shows but without the corners rounded.</p>
  
  <p>I don't remember what I did, but at certain point I achieved that I saw a black rounded layer on top of the view, but only if the cell was outside of the screen and then loaded again with <code>dequeueReuseableCell</code>. Every solution I found on the internet points to the same code I have, maybe it must be done somewhere else?</p>
  
  <p><strong>EDIT 1:</strong></p>
  
  <p>After the answers I got, I updated the code, and now it looks like this:</p>
  
  <pre><code>class HomeTableViewCell: UITableViewCell {
  
  var containerView: UIView!
  var bottomDetailsView: BottomDetailsView!
  var titleLabel: UILabel!
  var timeLabel: UILabel!
  
  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
      super.init(style: style, reuseIdentifier: "tableCell")
  
      containerView = UIView()
      bottomDetailsView = BottomDetailsView(frame: .zero)
      timeLabel = UILabel()
      titleLabel = UILabel()
  
      self.contentView.addSubview(containerView)
  
      containerView.addSubview(titleLabel)
      containerView.addSubview(timeLabel)
      containerView.addSubview(bottomDetailsView)
  
      containerView.snp.makeConstraints({ (maker) in
          maker.top.bottom.left.right.equalToSuperview()
      })
  
      titleLabel.snp.makeConstraints { (maker) in
          maker.height.equalTo(15)
          maker.top.left.right.equalTo(containerView)
          maker.bottom.equalTo(timeLabel.snp.top)
      }
  
      timeLabel.snp.makeConstraints { (maker) in
          maker.height.equalTo(34)
          maker.top.equalTo(titleLabel.snp.bottom)
          maker.centerX.equalTo(containerView.snp.centerX)
          maker.bottom.equalTo(bottomDetailsView.snp.top)
      }
      bottomDetailsView.snp.makeConstraints { (maker) in
          maker.top.equalTo(timeLabel.snp.bottom)
          maker.left.equalTo(containerView.snp.left)
          maker.right.equalTo(containerView.snp.right)
          maker.bottom.equalTo(containerView.snp.bottom)
      }
  }
  
  override func layoutSubviews() {
      super.layoutSubviews()
  
      bottomDetailsView.backgroundColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
  
      containerView.backgroundColor = #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)
      containerView.layer.cornerRadius = 15.0
  
      timeLabel.font = timeLabel.font.withSize(24)
      timeLabel.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
      titleLabel.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
      titleLabel.numberOfLines = 0
  }
  
  
  required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
  }
  }
  </code></pre>
  
  <p>Also I made a subclass of UIView as Duncan C suggested:</p>
  
  <pre><code>class BottomDetailsView: UIView {
  var shapeLayer: CAShapeLayer!
  
  //If the view's bounds change, update the shapeLayer's frame and also rebuild the path
  override var bounds: CGRect {
      didSet {
          shapeLayer.frame = self.bounds
          createShapeLayerPath()
      }
  }
  
  func createShapeLayerPath() {
      let path = UIBezierPath(roundedRect: bounds,
                              byRoundingCorners: [.bottomLeft, .bottomRight],
                              cornerRadii: CGSize(width: 15.0, height: 15.0))
      shapeLayer.path = path.cgPath
  }
  
  override init(frame: CGRect) {
      super.init(frame: frame)
  
      shapeLayer = CAShapeLayer()
      shapeLayer.frame = bounds
      layer.mask = shapeLayer
  }
  
  required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
  }
  }
  </code></pre>
  
  <p>Now everything works, except the fact that if I zoom in, if I look hard I can see e little bit of the underneath view on the corners. They are not perfectly aligned. The bottom line is ok, just the corners.</p>