Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi inheritance for IOS

I want create a class that can inherit from two custom class. Do you have any idea to do this please? Please see below my example:

first class:

@interface UIZoomableView : UIView
{
    UITapGestureRecognizer *_tapGestureRecognizer;
}

and implementation:

- (void)onDoubleTap:(UITapGestureRecognizer *)sender
{
    CGSize newSize;
    CGPoint centerPoint = self.center;
    if ([self isSmall])
    {
        newSize = [self bigSize];
    }
    else
    {
        newSize = [self smallSize];
    }

    [UIView animateWithDuration:0.3 animations:^{
        self.size = newSize;
        self.center = centerPoint;
    }];
}

Second class:

@interface UIDraggableView : UIView

    UIPanGestureRecognizer *_panGestureRecognizer;

@end

implementation:

- (void)handlePan:(UIPanGestureRecognizer*)sender
{
    ..
}

i want to create a custom view that can be zoomable and draggable. Do you have any idea to do this please? (without copy code..)

I think something like protocols but i want default value for the base classes? How can i implement this using protocol or something like protocols.

Thanks for any response!

like image 686
Rebecca Avatar asked May 14 '15 16:05

Rebecca


People also ask

Does iOS support multiple inheritance?

In this blog, we are going to learn about the multiple inheritances in Swift and their implementation in your iOS project. Swift is an Object-oriented programming language but it does not support multiple inheritances.

Which inheritance is not supported in iOS?

@virus : Yes you're correct, In iOS(Swift) Single and Multi-Level inheritance exists among the basic inheritances(Singe, Multi-level, Multiple). Multiple inheritance is not possible in Swift.

What is alternative for multiple inheritance?

Interfaces provide an alternative to multiple inheritance. Java programming language does not support multiple inheritance. But interfaces provide a good solution.

What is inheritance in iOS?

Inheritance allows us to create a new class from an existing class. The new class that is created is known as subclass (child or derived class) and the existing class from which the child class is derived is known as superclass (parent or base class).


2 Answers

Objective-C doesn't support multiple inheritance. You could use a protocol, composition and message forwarding to achieve the same result.

A protocol defines a set of methods that an object must implement (it's possible to have optional methods too). Composition is basically the technique of include a reference to another object and calling that object when it's functionality is required. Message forwarding is a mechanism that allows objects to pass messages onto other objects, for example, an object that is included via composition.

Apple Reference:

  • Protocols
  • Composition
  • Message Forwarding (and specifically Forwarding and Multiple Inheritance)

So, in your case Composition might be a solution, below is the example code

@interface ClassA : NSObject {
}

-(void)methodA;

@end

@interface ClassB : NSObject {
}

-(void)methodB;

@end

@interface MyClass : NSObject {
  ClassA *a;
  ClassB *b;
}

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB;

-(void)methodA;
-(void)methodB;

@end

@implementation MyClass

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
    a = anA ;
    b = aB ;
}

-(void)methodA {
    [a methodA] ;
}

-(void)methodB {
    [b methodB] ;
}

@end

If you don't want to implement all the methods from ClassA and ClassB in MyClass, you can use Message Forwarding in MyClass to handle all the method invocations. Below works fine as long as ClassA and ClassB do not have any common methods.

@implementation MyClass

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
    a = anA ;
    b = aB ;
}

//This method will be called, when MyClass can not handle the method itself
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([a respondsToSelector:[anInvocation selector]])
        [a invokeWithTarget:someOtherObject];
    else if ([b respondsToSelector:[anInvocation selector]])
        [b invokeWithTarget:someOtherObject];
    else
        [super forwardInvocation:anInvocation];
}

@end
like image 54
Trident Avatar answered Oct 13 '22 20:10

Trident


The closest that you can get to multiple inheritance in Objective C is with categories. These are a mechanism for adding additional methods to a class that already exists.

Note that this has some important limitations:

  1. You can't add properties or ivars using a category, though you can use associated objects to get a similar effect;
  2. The compiler won't tell you if you have methods with the same name that are declared in the class and the category, or in two categories, so you have to be careful to avoid name collision;
  3. This won't appear as a proper class (because Objective C does not have multiple inheritance) so you won't have something in your code called ScrollableZoomableView which inherits from ScrollableView and ZoomableView. That's not possible in Objective C (unlike C++ for example).
  4. You need the -ObjC flag when linking files with categories, otherwise you'll get unrecognized selector errors when you run your code;
  5. You can't get your code called during -init or +initialize, because those belong to the base class. You'll need to initialize your properties explicitly. You can still use +load though;
  6. You can't intercept dealloc either, so you may need to be careful to explicitly deregister your listeners too.

You want something like this:

@interface UIView (Zoomable)

@property (nonatomic) UITapGestureRecognizer * my_tapGestureRecognizer;

@end


@implementation UIView (Zoomable)

-(void)my_enableZooming() {
   self.my_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(my_onDoubleTap:)];
   self.my_tapGestureRecognizer.numberOfTapsRequired = 2;
   [self addGestureRecognizer:self.my_tapGestureRecognizer];
}

-(void)my_disableZooming() {
   [self removeGestureRecognizer:self.my_tapGestureRecognizer];
   self.my_tapGestureRecognizer = nil;
}

-(void)my_onDoubleTap:(UITapGestureRecognizer *)sender {
    ...
}

-(UITapGestureRecognizer)my_tapGestureRecognizer {
    return objc_getAssociatedObject(self, @selector(my_tapGestureRecognizer));
}

-(void)setMy_tapGestureRecognizer:(UITapGestureRecognizer)value {
    objc_setAssociatedObject(self, @selector(my_tapGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end


@interface UIView (Draggable)

@property (nonatomic) UIPanGestureRecognizer * my_panGestureRecognizer;

@end

@implementation UIView (Draggable)

-(void)my_enableDragging() {
   self.my_panGestureRecognizer = ...;
}

-(void)my_disableDragging() {
    ...
}

-(void)my_handlePan:(UIPanGestureRecognizer*)sender {
    ...
}

-(UIPanGestureRecognizer)my_panGestureRecognizer {
    return objc_getAssociatedObject(self, @selector(my_panGestureRecognizer));
}

-(void)setMy_panGestureRecognizer:(UIPanGestureRecognizer)value {
    objc_setAssociatedObject(self, @selector(my_panGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end
like image 40
Ewan Mellor Avatar answered Oct 13 '22 20:10

Ewan Mellor