In objective-C we can (by importing the language's runtime header file) do the following:

//Pass a service (usually an object) and ANY protocol
- (void)registerService:(id)service forProtocol:(Protocol *)protocol
{
    //Grab the protocol's name (that's why we import runtime.h, it contains the protocol_getname mehod)
    NSString *protocolName = [NSString stringWithUTF8String:protocol_getName(protocol)];

    //If the object we passed does not conform to the protocol, inform and break
    if (![service conformsToProtocol:protocol])
    {
        NSLog(@"Service: %@ does not conform to protocol: %@", service, protocolName);
        return;
    }

    //Else add service in a collection (array, dictionary) for later use
    self.services[protocolName] = service;
}

I use this in obj-C as a "poor man's IOC container", a simple registry used for injecting dependencies.

//The interested party uses this method to obtain the dependency it needs by asking for the object that is registered as responsible for conforming to the Protocol parameter
- (id)serviceForProtocol:(Protocol *)protocol
{
    id result;

    NSString *protocolName = [NSString stringWithUTF8String:protocol_getName(protocol)];

    //Look for the service that conforms to the protocol in the registry dictionary,
    result = self.services[protocolName];

    //if there is no object meeting the criteria, inform/alert
    if (result == nil)
    {
        NSLog(@"No class registered for protocol: %@", protocolName);
    }

    //and return the result
    return result;
}

Trying to replicate this behaviour in Swift, I found out that we don't have access to the language's equivalent "runtime" API like we do in obj-C (yet), and understandably so since swift is a work in progress and giving people this kind of access is undoubtedly risky.

But this also means that we can't use Protocol in the same way anymore i.e. in the sense of ANY protocol.

The first possible workaround that comes to mind is a mix of generics, Any and where, but that feels too much for something that used to be simple.

So, my question is: What are some proposed solutions for passing around Protocol (as in ANY Protocol) in Swift?

Related posts

Recent Viewed