3

(I'm not saying it isn't, this is more of me asking in order to make sure I'm properly implementing object-oriented principles.)

Say I want to create a UIView with a UIImageView in it and a UILabel below the UIImageView captioning it.

In an iOS app, what would be the best way to reuse this UIView setup if I wanted to have it in multiple parts of my app?

It seems a lot of tutorials I read indicate to subclass UIView, and in one of the init methods create the subviews and then add them to self, and voila, just create new instances of this UIView subclass and you have a reusable implementation.

But is this "image with caption" concept make sense to be a subclass of UIView? I understand subclassing and inheritance to be something like you have a superclass called Vehicle, and you create a subclass of it called Truck. If you look at it, "Truck" is a "Vehicle" which is how I've understood inheritance.

Does

"image with caption" is a "view"

make conceptual sense in inheritance? I know many would say "Of course it is!" but I'm just looking at it and thinking that it's not exactly a derivation or a customization of the superclass, but an amalgamation of some other ones.

If I'm creating something like that, I'm almost thinking I want a reusable customized instance of UIView, more so than a subclass of UIView but maybe I'm applying too sharp a definition of subclassing.

What if I just wanted a bunch of red UIButtons with a special font for the label that I could reuse? Is that really a use for subclassing?

Is subclassing the best option? Or maybe creating it from a nib and importing it with code would be better?

Rishil Patel
  • 1,977
  • 3
  • 14
  • 30
Doug Smith
  • 29,668
  • 57
  • 204
  • 388
  • A subclass of a UIView makes perfect sense. What may confuse you is that your subclass of UIView may be made a "subview" of a different view, and you may add "subviews" to your UIView subclass. Subclass and subview are two entirely different things -- the difference between "isa" and "hasa" relationships in "normal" objects. – Hot Licks Feb 11 '14 at 22:55
  • (The only Cocoa classes you shouldn't subclass are those that say in their documentation something to the effect of "Subclassing of this class is not recommended". Everything else is fair game.) – Hot Licks Feb 11 '14 at 22:57

4 Answers4

4

Subclassing it is a perfectly fine option. You need to remember that UILabel and UIImageView are in fact subclasses of UIView. In fact, everything in UIKit is derived from UIView. The whole point of subclassing is to customize your objects. That is definitely a great way to go about this.

gurooj
  • 2,100
  • 4
  • 21
  • 25
  • But isn't it improper to subclass certain objects? It's pretty accepted [not to subclass UIButton](http://stackoverflow.com/questions/13202161/why-shouldnt-i-subclass-a-uibutton), so how would I do it if I wanted a specific, reusable implementation of UIButton? UIPageViewController is another that you weren't supposed to subclass [prior to iOS 6](https://developer.apple.com/library/ios/documentation/uikit/reference/UIPageViewControllerClassReferenceClassRef/UIPageViewControllerClassReference.html), what if I wanted to customize that for easy reuse? – Doug Smith Feb 11 '14 at 21:46
  • The issue with subclassing seems to be the style, if you assume subclassing with `UIButtonTypeCustom` that should be fine. There are no "notes" about subclassing UIButton as with by example `NSStream`. But even that and others such as `NSString` can be subclassed but may require social care. I've subclassed all three and UIButton was the easiest, `NSStream` the hardest. – zaph Feb 11 '14 at 22:16
  • That post even points out that UIButton is the exception to the rule. Overall, there are very few things you need to avoid subclassing (unless you are just introducing unnecessary complexity). I have subclassed UIButton before. – gurooj Feb 15 '14 at 10:57
1

If you need to reuse only views + layout using nib/xib file could be sufficient. If you want some parameters and actions it could be better to subclass.

Leszek Zarna
  • 3,253
  • 26
  • 26
0

If I'm creating something like that, I'm almost thinking I want a reusable customized instance of UIView, more so than a subclass of UIView but maybe I'm applying too sharp a definition of subclassing.

You're thinking of prototyping, and that's a reasonable way to design object-oriented systems. Self is the canonical example, but JavaScript is probably the most famous. Objective-C doesn't generally use prototyping. (Except that it uses it for views quiet a lot actually, almost exactly how you're describing it... more in a second.)

You're very correct to think about classes in terms of aggregation first and only moving to inheritance later. In many cases it's more natural to create a UIViewController subclass that configures a stock UIView. But sometimes that's unwieldy. Again, I'd look to the UIKit examples for guidance on what makes sense in a UIView subclass, and what doesn't. It rarely makes sense, though, to subclass a subclass of UIView. Deep object hierarchies are not common in (good) ObjC. It is better to move the complexity into controllers and delegation.

But I said that UIView uses prototypes a lot. And it does. They're called nib files. A nib file is nothing but a bunch of serialized prototypes that are cloned into your system (most of the time these are views, but they can actually be anything). And there's nothing wrong with configuring your complex views in Interface Builder and then instantiating them yourself with UINib. I've done that myself rather than creating complicated UIView subclasses.

And every so often, it does make sense to clone an existing, pre-configured view prototype, and I've done it in a couple of cases (particularly when the user has configured the view somehow). You can do that using NSCoding (you serialize the view to data, and then deserialize it back into a view). But this is not the common approach.

All that said, for your specific case of a captioned image view, I'd almost certainly build it as a UIView subclass personally.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
0

For your use-case it seems that you have a good idea and seems the sensible option to have another view. DDDImageCaptionView

Make sure you have a good model, view and controller separation to ensure you are not using the view to store data, the view should be dumb and display what its told.

Oliver Atkinson
  • 7,970
  • 32
  • 43