5

I have the following method:

- (FDModel *)_modelForClass: (Class)modelClass 
    withIdentifier: (NSString *)identifier

which should take in a Class and a identifier, create an instance of modelClass, assign the identifier and do some other work based on the fact that it assumed modelClass is a subclass of FDModel.

I can put in a check that raises some error or exception if [modelClass isSubclassOfClass: [FDModel class]] == NO but I was trying to see if there was a way to enforce this at compile time.

EDIT: I understand that some people see this as a obvious factory method but the modelClass parameter is actually passed in by the user of my library through a delegate callback - (Class<FDModel>)modelClassForDictionary: (NSDictionary *)dictionary;. This question was more aimed at making the user of my library return a Class that has a specific subclass.

Reid Main
  • 3,394
  • 3
  • 25
  • 42

2 Answers2

3

I would consider the plain answer to your question being no; there is no way of checking if a class passed as a parameter is of a certain kind.

But I'd like to argue that the essence of your question primarily points to a design issue, i.e. can't your instance-generating method be expressed as a factory method? Like so:

@interface FDModel

+ (instancetype)modelWithIdentifier:(NSString *)identifier;

@end

In the above case you would simply do:

[FDModel modelWithIdentifier:anIdentifier];

The actual class returned (and the initialisation logic) being specified by the factory method implementation through subclassing of the FDModel class:

@implementation FDModelSubclass

+ (instancetype)modelWithIdentifier:(NSString *)identifier
{
    FDModel *model = [super modelWithIdentifier:identifier];
    if (model)
    {
        // do additional init stuff
    }
    return model;
}

@end

Nothing to check, no chance to go wrong.

insys
  • 1,288
  • 13
  • 26
  • the return type here should be `instancetype`, so that the compiler is aware that a subclass' factory method is generating an instance of the subclass, not strictly FDModel – Patrick Goley Feb 19 '14 at 18:39
  • I drastically simplified the description of the method. I keep a list of all FDModel objects ever instantiated through this method and ensure that only one FDModel object with the identifier ever exists. I can (and probably will) use the factory method if a model does not exist but the modelClass is actually provided to this method through a delegate. I ask the user of my data client what Class they would like to be instantiate for a given NSDictionary. This is the current delegate method `- (Class)modelClassForDictionary: (NSDictionary *)dictionary;` which will need to be changed. – Reid Main Feb 19 '14 at 21:48
1

After some research I don't think you can do it at compile time - you have to do it at runtime as you expected.

BOOL classConformsToProtocol = [class conformsToProtocol:@protocol(OKAProtocol)];

OR

BOOL classConformsToProtocol = [self class:[OKAClass class] conformsToProtocol:@"OKAProtocol"];

------

- (BOOL)class:(Class)class conformsToProtocol:(NSString *)protocol;
{
  return [class conformsToProtocol:NSProtocolFromString(protocol)];
}
Oliver Atkinson
  • 7,970
  • 32
  • 43