0

Question

How do we hide private class when using it in Objective-C?

For example, as described below PrivateFilter is the class I want to hide. CustomFilter is the class I make, which is open. GPUImageFilter is the class public on Github, which is open, too. And CustomFilter actully wraps the functionallity of PrivateFilter.

@interface CustomFilter : GPUImageFilter
@end

@interface PrivateFilter : GPUImageFilter
@end

Possible Solutions

So there are two solutions:

Solution 1: Class cluster

Have a look at the example A Composite Object: An Example in the Apple document. I followed the steps and make the following code.

// CustomFilter.h
@interface CustomFilter : GPUImageFilter
@end

// CustomFilter.m
@interface CustomFilter()
@property (nonatomic, strong) PrivateFilter *privateFilter;
@end

@implementation CustomFilter
- (instancetype)init
{
    self = [super init];
    if (self) {
        _privateFilter = [[PrivateFilter alloc] init];
    }
    return self;
}

// and then override the most of GPUImageFilter functions...
@end

But somehow it doesn't work, so I try the solution 2.

Solution 2: Init with PrivateFilter

// CustomFilter.h
@interface CustomFilter : GPUImageFilter
@end

// CustomFilter.m
@implementation CustomFilter
- (CustomFilter *)init
{
    self = (CustomFilter *)[[PrivateFilter alloc] init];
    return self;
}

@end

This works, but it's very strange to use alloc in init. So I try the solution 3.

Solution 3: factory class method

// CustomFilter.h
@interface CustomFilter : GPUImageFilter
+ (CustomFilter *)filter;
@end

// CustomFilter.m
@implementation CustomFilter
+ (CustomFilter *)filter
{
    CustomFilter *filter = (CustomFilter *)[[PrivateFilter alloc] init];
    return filter;
}

@end

This works, but it could not be inherited, just like class cluster.

Repeat Question

SO which is the best solution? Or is there other some good solutions?

allenlinli
  • 2,066
  • 3
  • 27
  • 49
  • The first one should work I think, for inherited then you can forward all the implementation to the private property, would need to rewrite every function though – Tj3n Jan 18 '19 at 02:46

1 Answers1

0

I think you need protocol, instead of CustomFilter with factory approach. If you need some GPUImageFilter subclass you can make GPUImageFilter<CustomFilter>

//CustomFilter.h
@protocol CustomFilter

...

@end

typedef GPUImageFilter<CustomFilter> CustomFilter;

//PrivateFilter.h
#import "CustomFilter.h"
@interface PrivateFitler: CustomFilter
...
@end

//GPUImageFilter+CustomFilter.h
@interface GPUImageFilter(CustomFilter)

+ (CustomFilter *)filter;

@end

//GPUImageFilter+CustomFilter.m
#import "PrivateFilter.h"

@implementation GPUImageFilter(CustomFilter)

+ (CustomFilter *)filter
{
    return [[PrivateFilter alloc] init;
}
@end

With such approach Xcode even give you warnings if you forget to implement some methods.

Cy-4AH
  • 4,370
  • 2
  • 15
  • 22
  • For now, I can not let PrivateFitler inherits CustomFilter, because `PrivateFitler` is a third party library. And for `GPUImageFilter` I think maybe `GPUImageFilter` is a better naming? This is a good approach to get the warnings from Xcode, though, thanks! – allenlinli Jan 19 '19 at 03:12
  • @allenlinli you should start from that `PrivateFitler` is class from third party library. You should just create protocol and return it from yours fabric. – Cy-4AH Jan 21 '19 at 09:16