Kodeco Forums

Video Tutorial: CALayers Part 1: Getting Started

Learn how to set some interesting properties on CALayer to accomplish some neat effects in your apps.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/3246-calayers/lessons/2

Hi Caroline

Fellow Brit really appreciating your video tutorials :slight_smile:

How would you set the corner radius only for certain corners using CALayer i.e say the top left and bottom left corners?

Cheers

Hi Caroline

To be more specific I am round to create rounded corners of a border for a UIButton

This is the code i have but the corners aren’t being drawn. Not sure what I am doing wrong

class MinusButtonRoundedCorners: UIButton {

override func layoutSubviews() {
super.layoutSubviews()

self.layer.borderColor = UIColor.whiteColor().CGColor
self.layer.borderWidth = 1.0
self.layer.masksToBounds = true

let shapeLayer = CAShapeLayer()

shapeLayer.path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.TopRight, .BottomRight], cornerRadii: CGSize(width: 30.0, height: 30.0)).CGPath
shapeLayer.frame = self.bounds
shapeLayer.strokeColor = UIColor.whiteColor().CGColor

layer.mask = shapeLayer

}

}

Any help would be awesome
Thanks

@swiftlearnerforlife - [currently residing in Aus where the winter weather is 10 degrees warmer than your summer :laughing:]

IIRC I cover this later in episode 3. Your code uses shape layer as a mask. Quite an intriguing way to approach the problem, but you could remove the layer border and just add the shape layer as an actual layer.

Your code draws a square button with a border, and then masks out the rounded corners. That’s why they’re not showing.

Try this:

class MinusButtonRoundedCorners: UIButton {
  
  override func layoutSubviews() {
    super.layoutSubviews()
    
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.TopRight, .BottomRight], cornerRadii: CGSize(width: 30.0, height: 30.0)).CGPath
    shapeLayer.frame = self.bounds
    shapeLayer.strokeColor = UIColor.greenColor().CGColor
    shapeLayer.fillColor = UIColor.whiteColor().CGColor
    layer.addSublayer(shapeLayer)
  }
}

Hi Caroline

Thanks for getting back to me and very jealous about the weather (is currently raining in London :frowning: )

Your solution was great and have already implemented it for my app.

I look forward to watching and learning more from your future tutorials

Cheers
Piers

1 Like

Hi, Caroline

Did you try to convert it to swift3 xcode8?
I tried it but when I opened main.storyboard xcode asks me for the initial device view and I choosed the iPhone 6s and now I am getting error Unable to simultaneously satisfy constraints.
I tried with setting to suggested constraints but I wasn’t able to find out in a short time period.

Cheers, G

@goblin - I just tried and I used these suggestions from Interface Builder. I don’t know why yours didn’t work:

First click the red circle next to Book View Controller Scene

Then click the red dot next to Content Priority Ambiguity and choose Change Priority in the popover.

That should fix it. (I’m quite impressed with the Swift 3 conversion wizard.)

If it doesn’t have a look at the suggested constraint list and see what the problem is.

For example, To set the vertical hugging priority, first select the Book Title Label and change the Content Hugging Priority in the Size Inspector.

I’m not sure why the StackView is putting out warnings. It seems to be working OK.

@caroline I got this even if I tried resolving it with suggestions by changing the priority.

I noticed this issue because next thing which it didn’t work is

print(followButton.bounds.height/2.0) // Retrun 0.0
followButton.layer.cornerRadius = followButton.bounds.height/2.0

RWBooks[2669:1362072] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) ( "<NSAutoresizingMaskLayoutConstraint:0x16d5eb90 h=--& v=--& V:[UIView:0x16e76cd0(0)]>", "<NSLayoutConstraint:0x16e76320 UIImageView:0x16e76dc0.bottom == UIView:0x16e76cd0.bottomMargin>", "<NSLayoutConstraint:0x16e76fe0 UIImageView:0x16e76dc0.top == UIView:0x16e76cd0.topMargin>" )

Could you upload the converted project?

Xcode 8 beta 4 behaved even better (in regard to the auto layout anyway). I downloaded a fresh version from the video website, converted to Swift 3 on opening the project.

I then went into the storyboard for a 6s and clicked on all the suggestions and fixed frames, and all the errors went away - even the yellow ones for the stack view that I had problems with yesterday.

I suggest you download a fresh version and try with Xcode 8 beta 4, but failing that, here’s a zipped copy of the starter in beta 4:

CALayers-01-GettingStarted-DemoStarted.zip (1.4 MB)

However, something has changed internally. The view’s bounds are not available in viewDidLoad(). So I suggest you move the cornerRadius code and anything else that checks view size into the view controller’s viewDidLayoutSubviews().

Here’s the finished challenge project:

CALayers-01-GettingStarted-ChallegeFinished.zip (1.4 MB)

1 Like

Hi @caroline

I think something went wrong. Did you build that code in xcode8b4, because I got errors with UIColor.black missing brackets and UIStoryboardSegue has no destination (fix-destinationViewController). Error with constraints continue for me (UIViewAlertForUnsatisfiableConstraints).

I moved forward …
Cheers, G

I don’t have b4 at the moment - I went back to b3. Perhaps you could accept the fixes the compiler suggests?

Hi, Caroline!
Hope you’ll read this )
I’ve just started this tutorial and glad you provided Swift 3 starter, which can be opened in Xcode 9.
I have a little questions: @ 7:40 you added cornerRadius for doneButton as a half of it’s height. When I did this, I didn’t see any changes. When i looked at doneButton in Interface Builder and doneButton.frame during viewWillAppear - the height was zero. Is it a an incompatibility between Xcode 7 & 9 or something else?

Hi @pavoleg - I think stack views must have changed the timing of when they size their views.

You can take the done button out of the stack view and use auto layout on it to pin it to the bottom of the screen - you’ll have to do vertical spacing auto layout on the stack view bottom to separate it from the done button - but it will work.

1 Like

Caroline, thank you for your answer. I just added height constraint for button and it works good enough

@pavoleg - oh yes - that would work better :+1: