在Swift中将协议类型作为参数传递

joa*_*kim 7 protocols ios swift

在objective-C中,我们可以(通过导入语言的运行时头文件)执行以下操作:

//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;
}
Run Code Online (Sandbox Code Playgroud)

我在obj-C中使用它作为"穷人的IOC容器",一个用于注入依赖项的简单注册表.

//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;
}
Run Code Online (Sandbox Code Playgroud)

试图在Swift中复制这种行为,我发现我们无法像在obj-C中那样访问该语言的等效"运行时"API,并且可以理解,因为swift是一项正在进行的工作并且给予了人们这种访问无疑具有风险.

但这也意味着我们不能再以相同的方式使用协议,即在任何协议的意义上.

我想到的第一个可能的解决方法是混合使用泛型,Any和where,但对于过去简单的东西来说,感觉太多了.

所以,我的问题是:在Swift中传递协议(如在任何协议中)的一些提议解决方案是什么?

编辑:我使用Swift中引入的元类型类型取得了一些成功,这在语言设计方面是有意义的,但也没有提供能够提供元数据类型的"字符串"表示的能力,该表达式可用作字典.

这当然是随着语言的成熟而添加的功能.

new*_*cct 1

你尝试了什么?

像这样的事情不起作用:

import Foundation

func registerService(service: NSObjectProtocol, forProtocol prot: Protocol) {
  let protocolName = NSStringFromProtocol(prot)

  if (!service.conformsToProtocol(prot)) {
    println("Service: \(service) does not conform to protocol: \(protocolName)")
    return
  }

  //...
}
Run Code Online (Sandbox Code Playgroud)

  • 它确实有效,但我正在寻找“Pure Swift”TM 方法(如果存在)。谢谢! (3认同)