4

Can a Cocoahead please explain why UIView and it's sub classes don't adopt the NSCopying Protocol?

I can see, philosophically, why UITouch would not be copy compliant, as it's a very temporal object. By UIView, and it's subclasses, especially UIButton, seem like they should be able to be copied.

Certainly Apple has good reasons for doing things the way they do. Do you know their reason?

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
SooDesuNe
  • 9,880
  • 10
  • 57
  • 91
  • What circumstances do you have for needing to copy a view? – Abizern Oct 12 '09 at 00:30
  • This question is just informational..However, to answer your question the problem that sparked my question was one with UIButtons. I had a UIButton that was almost exactly like another button. So I wanted to copy the first button into the second. and then just modify the few differences. – SooDesuNe Oct 12 '09 at 03:15

3 Answers3

4

It would seem the question they asked wasn't "Why not?" but "Why do it?" There's little point to doing so. There's rarely a need to copy a live view. Usually, template views are created through the NSCoding protocol (i.e. with Interface Builder), and that's about all a copyable view would be good for.

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • 3
    A good example of when you'd want to make multiple copies of an object, like a view, is in UITableView when creating the dozen or so reuseable cells. Being able to copy one is much easier than multiple allocations of UIViews/UIButtons/UILabels, etc. – mahboudz Oct 12 '09 at 19:30
  • 1
    As an example, I created a chess piece via a UIView subclass in IB. Now I want clone that view for all similar chess pieces. Putting each piece in its own NIB file just seems a little silly (and inefficient). The *obvious* thing to do is what the OP suggested, but there seems no simple way to clone UIView's. – wcochran Jan 26 '12 at 18:48
  • 1
    @wcochran: There's nothing stopping you from creating a UIView subclass that implements the behavior you want if it's that important to you. Requiring every view class anyone writes to implement copying just because you don't like nibs would be silly and inefficient. – Chuck Jan 26 '12 at 19:14
  • 2
    "There's rarely a need to copy a live view." -- except that Apple decided to implement their collections - nsdictionary etc - as REQUIRING that keys are COPIED. So, you cannot use a UIView as a key in dictionary - even though this is a common use-case. – Adam Nov 04 '12 at 17:11
4

Interesting question. In addition to Chuck's answer I wanted to add that the reason is possibly because Apple made that design decision... Just that simple; no real specific reason but that was the decision made.

I can also postulate that this decision might have been made because UIView is used as a subclass for a few other classes and the engineers didn't want to impose NSCopying forcefully on the subclasses.

Frank V
  • 25,141
  • 34
  • 106
  • 144
3

Because NSCopying is not so great at deep (recursive) copies of object graphs. For instance, [NSArray copy] copies the list of objects, not the objects themselves. Object graphs are better served by NSCoding. Which in a happy coincidence is supported by UIView.

If you want to copy custom view with properties, you'll have to support NSCoding. E.g.,

@interface SKCustomCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UILabel* nameLabel;
@property (strong, nonatomic) IBOutlet UIView* topView;

@end


static NSString* propertiesKey = @"SKCustomCellProperties";

@implementation SKCustomCell

@synthesize nameLabel;
@synthesize topView;

- (id) initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder: aDecoder];
    [self setValuesForKeysWithDictionary: [aDecoder decodeObjectForKey: propertiesKey]];
    return self;
}

- (void) encodeWithCoder:(NSCoder *)aCoder
{
    [super encodeWithCoder: aCoder];

    [aCoder encodeObject: [self dictionaryWithValuesForKeys: [[NSArray alloc] initWithObjects: @"nameLabel", @"topView", nil] forKey: propertiesKey];
}


@end
Steven Kramer
  • 8,473
  • 2
  • 37
  • 43
  • it's interesting to know that UIVIews implement NSCoding, but you don't relate that to actually answering the question. – Mark Lummus Mar 28 '13 at 11:05
  • 1
    @MarkL, I think I did. Classes that adopt NSCopying seem to do shallow copies by convention. A shallow copy of a UIView is not generally useful. A deep copy would be impractical, because all the properties of every UIView subclass would need to support NSCopying. – Steven Kramer Mar 28 '13 at 20:56