views:

246

answers:

2

I want to implement a movable UIView class (view moves when you touch on it and move your finger), e.g.:

@interface MovableView : UIView {
  some members;
 }
-touchesBegan;
-touchesMoved;
@end

How can I apply this code to UILabel, UIButton etc without multiple inheritance? In C++, I'd do it like this (with UIView as a virtual base to MovableView):

struct MovableLabel : UILabel, MovableView {};

Categories are offered as an alternative to multiple inheritance but I definitely don't want to extent UIView using categories because that would apply to all views in my application. I only want some of my views to be movable.

My current strategy to avoid code duplication is putting MovableView code in a header file and including it everytime I need some class to use it. Besides that I have to add members of MovableView to whatever class I am writing. It is pure code ugliness but better than copy/pasting code all over my project.

Does anyone have any other ideas to get around this Objective C limitation [of not having multiple inheritance]?

Thanks,

Altan

+4  A: 

Objective-C won't let you do this mixin inheritance thing, except by adding the same category to each of the classes you care to augment. And then, you won't get extra instance variables.

For your specific problem, I might approach it by designing MovableView as a container class that was just an object that has a child view (UILabel, UIButton, etc) that you want to move as its subview.

quixoto
And there is a good reason for prohibiting multiple inheritance: In the old C++ times such techniques caused dependency hell and in modern times of loose coupling, you want to avoid anything like dependency hell
Great idea, quixoto. A little more work in Interface Builder but less # of classes and coding.
Altan
A: 

Categories would not help anyway because replacing the real touchesBegan method on UIButton would be pretty bad... you can't call [super] from a category.

Another solution would be to inject a method into those class definitions with something like:

Method origMethod = class_getClassMethod([UIButton class], @selector(touchesBegan));
Method newMethod = class_getClassMethod([TemplateClass class], @selector(replacementTouchesBegan));
method_exchangeImplementations(origMethod, newMethod);

But that's pretty fiddly. Although if it's really where you want to go, it's worth looking into...

What I would do is make a MovableView class that inherits from UIView, and simply add whatever you want movable as a subview of that view (which I think might be slightly different than what quixoto was saying, my apologies if not). It gets to respond to touches first and passes along whatever it doesn't need to the next responder... no need to build up a special class with a single subview. Then in IB you can just place these movable views wherever and put things inside of them.

In general compositional techniques like this are very handy across UIKit rather than modifying core classes.

Kendall Helmstetter Gelner