How to define a Class instance type conforming to a protocol?

Consider the following Objective-C protocol declaration, which requires only class methods:

@protocol TDWMethoding<NSObject>

+ (void)foo;
+ (void)bar;

@end

Assuming I need to return an instance of a Class which conforms to this protocol from a method, how am I supposed to specify the return type?

- (nullable /*return-type*/)instantiateMethoding {
    Class instance = ... // some implementation
    if ([instance conformsToProtocol:@protocol(TDWMethoding)]) {
        return instance;
    }
    return nil;
}

There are a number of working options I considered so far in regards to how to express the /*return-type*/, but each has its own downsides:

  1. Class - this way it doesn't expose conformance. What kind of Class is it? What does it do? Does it conform to the protocol at all?
  2. Class<TDWMethoding> - this looks like a viable solution and even was suggested a few times by other developers (here and here) but I personally find it inconsistent and misleading: when we have a variable of form Type<Protocol> *instance, it commonly means that protocol class methods should be sent to the instance's class ([[instance class] foo]) not the instance itself ([instance foo]);
  3. id<TDWMethoding> and returning an instance of the class instead - this is consistent, but it requires me to instantiate the class, which is both redundant and prevents me from hiding the constructors of the utility classes which conforms to the protocol with NS_UNAVAILABLE macro.

Is there a better semantic to express such a return-type?

After digging a little deeper into The Objective-C Programming Language documentation, I actually found the exact answer to such a scenario:

Protocols can’t be used to type class objects. Only instances can be statically typed to a protocol, just as only instances can be statically typed to a class. (However, at runtime, both classes and instances respond to a conformsToProtocol: message.)

Which means that it's just not supported and I should implement this differently

There is a class method flavor: +conformsToProtocol:

https://developer.apple.com/documentation/objectivec/nsobject/1418893-conformstoprotocol

From the documentation:

Discussion A class “conforms to” a protocol if it adopts the protocol or inherits from another class that adopts it. Classes adopt protocols by listing them within angle brackets after the interface declaration. For example, here MyClass adopts the (fictitious) AffiliationRequests and Normalization protocols:

@interface MyClass : NSObject <AffiliationRequests, Normalization>

A class also conforms to any protocols included in the protocols it adopts or inherits. Protocols incorporate other protocols in the same way classes adopt them. For example, here the AffiliationRequests protocol incorporates the Joining protocol:

@protocol AffiliationRequests <Joining>

If a class adopts a protocol that incorporates another protocol, it must also implement all the methods in the incorporated protocol or inherit those methods from a class that adopts it. This method determines conformance solely on the basis of the formal declarations in header files, as illustrated above. It doesn’t check to see whether the methods declared in the protocol are actually implemented—that’s the programmer’s responsibility. To specify the protocol required as this method’s argument, use the @protocol() directive:

BOOL canJoin = [MyClass conformsToProtocol:@protocol(Joining)];

Also note:

Performance Considerations

Calling this method in performance sensitive code can cause unwanted performance problems. conformsToProtocol: requires taking the Objective-C runtime lock and traversing the target’s class hierarchy to check for protocol conformance, which can take significant time. Consider the following alternatives in your code: Use respondsToSelector: to check for methods in the protocol instead, especially if you only need to check some of the protocol’s methods.

If you do need to use conformsToProtocol:, cache the result whenever possible, rather than calling this method repeatedly.

Assuming I need to return an instance of a Class which conforms to this protocol from a method, how am I supposed to specify the return type?

Like this...

- (nullable id<TDWMethoding>)instantiateMethoding 
{
    Class instance = ... // some implementation
    if ([instance conformsToProtocol:@protocol(TDWMethoding)]) {
        return instance;
    }
    return nil;
}

If you want to return any object to the caller that conforms to the TDWMethoding protocol. Typically you'd do this if -instantiateMethoding may return objects of different classes but all those classes must conform to the protocol.

If you just want to return an instance of a specific class and don't need it to be that generic just you do this:

-(MyClass*)instantiateMethoding
{ 
    //return it.
}

If MyClass conforms to the TDWMethoding protocol in its public header file you don't need to cast or write

id<TDWMethoding>

... the compiler knows MyClass conforms to TDWMethoding.

Not sure exactly what you're trying to do though. Hope that helps.

How to define a Class instance type conforming to a protocol?
 
 
Q