Correct Implementation of Custom UIView into ViewController Programatically

I am familiar with using storyboards to construct UI elements in Xcode, but I am only beginning to learn how to make UI programmatically (without a storyboard).

I wanted to know if this is the correct way to implement a UIView into an existing ViewController class.

DetailView (Custom UIView class):

@interface DetailView : UIView

@property (strong, nonatomic) UIImageView *imageView;
@property (strong, nonatomic) UIImageView *ratingView;
@property (strong, nonatomic) UILabel *tagLabel;
@property (strong, nonatomic) UILabel *plotLabel;

@end


.m file (implementation)

- (instancetype)init {

if(self = [super init]){
// Creating the large movie image
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 64.0, 375.0f, 200.0f)];

// Creating the rating image
_ratingView = [[UIImageView alloc] init];

// Creating the tag Label
_tagLabel = [[UILabel alloc] initWithFrame:CGRectMake(38, 274, 355, 200)];
self.tagLabel.font =  [UIFont fontWithName:@"HelveticaNeue" size:12];

// Creating the plot label
_plotLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 299, 355, 200)];
self.plotLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:14];

}

return self;
}


View Controller:

Commented code is another way I attempted to implement the DetailView

- (void)viewDidLoad {
self.detailView = [[DetailView alloc] init];

self.title = self.movie.title;
self.view.backgroundColor = [UIColor whiteColor];

self.detailView.imageView.image =
[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:self.movie.fanArt]]];

[self setRatingImage:self.movie.rating];

self.detailView.tagLabel.numberOfLines = 0;
self.detailView.tagLabel.text = self.movie.tagline;
[self.detailView.tagLabel sizeToFit];

self.detailView.plotLabel.numberOfLines = 0;
self.detailView.plotLabel.text = self.movie.plot;
[self.detailView.plotLabel sizeToFit];

}

• Would you mind adding some detail as to why storyboards won't work for you? Oct 24 '14 at 13:25
• @nhgrif they work perfectly, I am just learning how to do it with code so I have a better understanding. Oct 24 '14 at 15:22

A couple of thoughts:

1. It is curious to do some of the configuration of the subview's within your custom class (e.g. the frames) and other portions (e.g. numberOfLines and sizeToFit) in the view controller. If I were going to have this UIView subclass, then I'd encapsulate all the presentation details within that class. As it is, if the UI isn't quite right, you'll never quite know which class you have to take a look at.

2. It is curious to use numberOfLines of zero, but then to use hard-coded frame sizes. (Sure, you sizeToFit, but don't adjust the origin.) If one label changes size, wouldn't you want to move the other controls accordingly? You might contemplate specifying preferredMaxLayoutWidth, too.

3. In this day and age of differing device dimensions, it is curious to see hard-coded frame sizes at all. I'd probably implement auto layout unless you had some compelling reason not to. And even if I didn't use auto layout, I'd still specify the autosizing masks.

4. I generally give my subviews weak references because the process of doing addSubview already maintains a strong reference, and it's not clear your really need two strong references. (Clearly, you have to temporarily use a local variable when instantiating the label, if you go this route.)

Clearly you're not contemplating it at this point, but let's say you ever wanted to do [self.tagLabel removeFromParentView]. Would you also want to have to remember to do self.tagLabel = nil as well?

It's not a big deal, but I tend to follow the NIB/storyboard model that I don't generally maintain strong references to subviews: The only strong reference I'd maintain would be to the root view.

5. You're never setting the frame for your ratingView. I might confirm the clipping and content mode, too.

6. If you're going to have this UIView subclass, it doesn't feel like the view controller should be playing around with which image to show in the rating view. The view controller should probably just tell the UIView subclass what the rating is, and that subclass should take care of the presentation of the appropriate rating image.

7. Rather than using fixed fonts, if this was an iOS 7+ target, I'd consider using Dynamic Type.

8. If [NSURL URLWithString:self.movie.fanArt] is in the local file system, you can get away with doing that main thread, but if it's a remote URL, then definite retrieve that image asynchronously.

9. In terms of having custom UIView subclass at all, I'm not sure there's enough utility in this subview to warrant a subclass. Perhaps, once you start incorporating the above points, there might be enough substance to make this worth while, but I'm not sure your existing code sample justifies it.