Kodeco Forums

Video Tutorial: Introducing Custom Controls Part 1: Your First Custom Control

Build your first custom control by learning how to compose UIKit components to create a powerful icon.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/4276-introducing-custom-controls/lessons/2

Hi,
I’m using your tutorial to crate my own custom view.
but i having problems with autolayout and interface builder.
you can see the full problem in stack overflow

Thanks,
Ilan

Hi Ilan,

There are a couple of reasons that might explain the behaviour you’re seeing. The first is that the constraints inside that custom view don’t define the size. Therefore it’ll depend on external constraints to define the size. What constraints do you have set up in IB? If they don’t determine the size of that view, then AL won’t know how to size it.

You can provide the intrinsic content size to avoid this - which would allow you to choose a “favourite” size, but then also override it from outside the custom view.

The other reason you could be seeing this is the result of a confusing issue with interface builder. When a view is instantiated in code, you need to set translatesAutoresizingMaskIntoConstraints to false as you have done. However, for some reason, the live rendering in IB expects this to be true.

This is very confusing, but it’s likely that this is causing the issues you’re seeing - the difference between running the code and IB.

To get around this, try removing the translatesAutoresizingMaskIntoConstraints = false line from setupView() and update init(frame:) to match the following:

override init(frame: CGRect) {
  super.init(frame: frame)
#if !TARGET_INTERFACE_BUILDER
  translatesAutoresizingMaskIntoConstraints = false
#endif
  setupView()
}

Check that your constraints are set up correctly in IB and then give the code snippet above a try to see whether that fixes the issue.

sam

Thanks for the response.

I removed

translatesAutoresizingMaskIntoConstraints = false

from setup view, and everything is working great.

But the macro TARGET_INTERFACE_BUILDER doesn’t exist for me.
(I’m using Swift 2.2)

Ilan

Great! And thanks for the pointer on the deprecation of TARGET_INTERFACE_BUILDER. Will investigate what it’s been replaced with.

sam

Hi Sam,
I have watched some of your videos tutorials, you are a great tutor!!!

In this video, you calling setContentHuggingPriority for the IconControl it-self (7:30), in addition to the label and imageView.

I do not understand the purpose of it. You have not overridden the method intrinsicContentSize() for IconControl, as far as I know, calling setContentHuggingPriority, in this situation, should have no effect.

Is that correct?

Hey,

From what I remember, I believe you’re correct - it’ll have no effect. Content hugging is not used internally for a UIView, but is used to determine how the control will interact with its siblings.

This is especially important when views appear inside stack views. If you haven’t already, I urge you to check out the stack views series:

https://www.raywenderlich.com/video-tutorials#stackviews

sam

Any chance you could cover building custom controls with xib files? I’d love to build visually the multiple elements of my app, separately and independently, to only then start piecing them together in my views. I can’t find a good tutorial on that online or anywhere, I managed to hack together something that works, but I’m certain it’s not the correct way to do it.

1 Like

true, this should be build in interface builder

1 Like

Hi Sam,

I was wondering is there a way to make only one side of the view have a corner radius? As I wanted to build a view that acts like a button sitting on the edge of the screen and when pressed a list of controls slide out.

Thanks

/ Musa

Hi @fabiogiolito

This is possibly something that could have been covered in this series, but there’s a limit to what can be fitted in 10 videos. The problem with XIB-based or storyboard-based custom controls is that they are a bit hacky to get working correctly.

I believe that this series is due to be updated in the next cycle, so I’ll suggest it as an addition to the existing content.

cheers!

sam

Hi @musa,

The cornerRadius property on CALayer affects all corners equally - there is no way to select which corner you want.

There are several options to achieve the effect that you’re after:

  • you could create a shape layer CAShapeLayer that has the appropriate shape and use that the background to your view.
  • Since you want just 2 corners on the same side rounded, you could use 2 layers - one with rounded corners, one without. Make the non-rounded one smaller, and overlay it on the rounded one to “cover-up” the 2 rounded corners you want to be right-angled.
  • Or you could create a background image that has the correct shape, and use it as the layer content. If you make the image stretchable it would be able to cope with different device sizes, and wouldn’t be an expensive memory hog.

Give one of these a try and see how it goes.

sam

Hi really cool videos :slight_smile: I’m on swift 3 and i don’t understand why you add sharedInitialization() into an extension because when i do that, i’ve got an error : “use of unresolved identifier sharedInitialization”, so i have change my code to add this function into my class and no problem. So why use an extension ? Thanks you

@horiz0n

I like to use extensions to separate functionality, but it’s entirely a personal preference. The difference in Swift 3 are the access specifiers. In Swift 3 private restricts access to the local scope only - and the new fileprivate specifier is equivalent to private in Swift 2; i.e. access is restricted to just that file.

Switch private for fileprivate and you should be fine.

sam

Thanks is now run perfectly. I have test coding with extension, really good :blush:

1 Like

Glad you were able to get it going!