Custom Controls in iOS - Part 2: Your First Custom | Ray Wenderlich

Learn how to compose UIKit components to build your first custom control, all within a playground.


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

hi… I have a couple questions from the code in this lesson… I’ve made some comments…

fileprivate let imageView: UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFit
    return imageView
}() //what is this syntax with the () ?

can you explain the () used above to me? I haven’t seen it used like that before…

here are a couple more questions, in the code below:

fileprivate lazy var stackView: UIStackView = {
    //why is stackView a lazy var?
    let stackView = UIStackView(
        arrangedSubviews: [self.imageView, self.label]
    )
    stackView.axis = .vertical
    stackView.translatesAutoresizingMaskIntoConstraints = false
    //why didn't xcode autocomplete the 2 lines above for me?
    return stackView
}()
//why is the init using a coder?

I’ll just start with those. I’m sure they’re relatively obvious… well I am hoping they are :wink:

Hi @dkliman,

The {//code}() syntax defines a closure and immediately executes it. We use it as a way to collect multiple lines of code that will only be executed once, and so don’t warrant a reusable, named function. Brian has a nice introductory video on closures here, if that would be helpful.

Both of the examples you’ve listed use closures for initializing properties. We use let when possible, but lazy var is the next best thing when the closure depends on instance methods or properties: the subviews, in this case.

As for the autocomplete not working, that’s just Xcode for you. :disappointed: Please file a bug if you have time!

1 Like

hi… yes I’d love to know much more about closures… sadly, the link you suggested above gets a 404 error :-/

1 Like

Sorry, the formatting of the correct address changed. I updated it. Hopefully that’s helpful! Closures are my favorite. :smiley_cat:

1 Like
var imagePadding: CGFloat {
  get {
    return image?.alignmentRectInsets.top ?? 0
  }
  set {
    image = image?.withAlignmentRectInsets(
      UIEdgeInsets(
        top: -newValue,
        left: -newValue,
        bottom: -newValue,
        right: -newValue
) )
} }

This code in challenge has no effect at all. I am using Xcode 8.3.3. which mean image is not being padded. First I wrote the code myself then thought it might be me. then I copied the code from pdf still no effect. any hint for me

I am having trouble running the sample code. I can not see the image or label when I open the Demo End, Challenge Start, or Challenge End. When working through the tutorial I also can never see the image or Label. Has there been an Xcode/Swift update that causes this problem or have I got some setting somewhere that could cause them to be hidden or on some layer. I have no idea where to start with this problem.

Thanks for your help.

hi iam not getting the padding for uiimage. now using xcode 9. any help. alignment with rect is not working

I can’t add a Playground to my project the way you do it.

I can set up a Playground outside the project and then use <right-click add files to … > to achieve this.

But <right-click newfile … > does not offer a Playground template.

I’m running Xcode 9.1deploying to IOS 10.3

Am I missing some switch somewhere?

Thanks

Nope, you’re not missing something :slight_smile: There were a fair number of changes between Xcode 8 (which is what’s used in the videos) and Xcode 9. One of the changes appears to have been the removal of the ability to add playground directly to a project. So I believe the way you’re using is fine.

This code doesn’t work at all in the latest version of XCode (9.4). I thought it came from my code so I tried with the Demo end project and I got the same messed up layout for my Deluxe button:

50

Is anybody else getting the same thing?

@catie Can you please help with this when you get a chance? Thank you - much appreciated! :]

I followed complete lesson (first one) and got this: 00%20PM

setting text and images from outside of the class ruins all the pre added constraints.

yes, I am also getting the same result after running the sample code.

@catie Do you have any feedback regarding this? Thank you - much appreciated! :]

I am also seeing this issue. The constraints work nicely if the image, text, and tintColor are set during initialization. However, assigning any of these values outside of the class seems to cause the constraints to disappear.

Xcode 10.0 beta 4

Edit:
It seems that changing tintColor outside of the class has the effect of:

  • Removing the label view from the stackView.arrangedSubviews array
  • Setting the label.heightAnchor constraint to inactive

Explicitly reactivating constraints and readding the label to arrangedSubviews seems to partially fix the problem, but surely this is not the correct way to do it. Any help would be appreciated!

Update:

After giving up and moving on with the next tutorial the problem seems to correct itself. Moving the class into a separate file in the sources directory made the behavior go back to normal. Perhaps it is a bug in Xcode Storyboards.

@catie Can you please help with this when you get a chance? Thank you - much appreciated! :]

I think I found a solution : simply set the stack view’s alignment property to center :
stackView.alignment = .center

@ericlm Thank you for sharing your solution - much appreciated! :]