0

Every time I create my UIScrollView subclass I add a UIImageView to it. I get the image for the UIImageView from the scroll view's init method where I pass a UIImage.

But where do I add this subview? Normally I would do it in awakeFromNib but this is created programmatically. And it's bad practice to mess with the view hierarchy in the init methods.

Where should I do it?

Doug Smith
  • 29,668
  • 57
  • 204
  • 388
  • I think the fact that there's no good place to do it means this probably isn't a good approach... Is it possible to build the view hierarchy from the view controller which contains the scrollView? You would create the scrollView, and then add the imageView to the scrollView. Then, constrain all edges of the imageview to the scrollView. Call imageview.sizeToFit and it will automagically make itself scrollable within the scrollView's bounds. – Anna Dickinson Nov 15 '14 at 20:23
  • ^ is probably the best suggestion unless there is a good reason to make a new class for your UIScrollView. – Acey Nov 15 '14 at 20:29
  • @AnnaDickinson I don't understand, UIButton's and the like have a `titleLabel` property that is a `UILabel` for the title of the button. How do they have a UIView set up automatically? It seems odd that a `UIView` subclass can't be automatically be comprised of other sub `UIView`s, especially when it's easy to do with Interface Builder/nibs. There must be a way. – Doug Smith Nov 16 '14 at 18:49
  • More discussion: http://stackoverflow.com/questions/15978370/proper-practice-for-subclassing-uiview @Acey - yes, I changed my mind. Sounds like you create subviews during init. Then, you can potentially move them around/resize them in layoutSubviews. I think you'd set the scrollView content size in layoutSubviews so it can handle the imageView potentially resizing. .... I dunno, I've just been punting this whole issue lately and embracing autolayout. :-) – Anna Dickinson Nov 16 '14 at 19:22
  • @AnnaDickinson As much as I'd love to do that, scroll views and auto layout still seem like hell. – Doug Smith Nov 16 '14 at 21:27
  • This is helpful: https://developer.apple.com/library/ios/technotes/tn2154/_index.html – Anna Dickinson Nov 16 '14 at 23:39

2 Answers2

2

For UIView subclasses, init is where you should add your subviews. Think about if you created a UIButton for example, wouldn't you expect it to have a titleLabel right away?

Acey
  • 8,048
  • 4
  • 30
  • 46
  • I think the OP is correct: init isn't the right place. In Obj-C, there's no guarantee that an object is ready to go immediately after (or during) init. I think that's the motivation behind the strict init requirements in Swift. For UIKit components, it's better to wait until a point where specific things are defined; in a view controller, for example, you need to wait until viewDidLoad before touching views. – Anna Dickinson Nov 15 '14 at 20:13
  • No, that can't be right. A `UIView` subclass should have its structure after initialization, the same as you would expect it to have its subviews after un-archiving it from a nib. `UIViewController` isn't a `UIView` subclass so isn't really relevant here, but suffice it to say you can't access outlets or views only because they aren't created until you access the view. – Acey Nov 15 '14 at 20:27
0

I would pass it into your init, since it sounds like your scrollview subclass always requires an image.

class ScrollViewCustom: UIScrollView {

    init(frame: CGRect, image: UIImage) {
        super.init(frame: frame)

        var imageView = UIImageView(frame: CGRectMake(0, 0, 100, 200)) // Just an example size
            imageView.image = image
    }
}
Alex
  • 5,298
  • 4
  • 29
  • 34
  • Question is tagged Objective-C. Post an answer in Objective-C, not Swift. – rmaddy Nov 15 '14 at 19:19
  • 1
    Don't know Obj-C. I will leave my answer up instead of deleting since I still think it will be helpful for the OP to see implementation, even if specific syntax is different because it is the new language. – Alex Nov 15 '14 at 19:29