在协议扩展中将nil传递给带有可选的一般约束参数的函数

时间:2018-07-18 09:35:45

标签: ios swift generics swift3

我遇到这样的情况:我在协议中声明了两个函数,其中一个带有一个可选的通用约束参数,另一个函数没有任何参数,但是需要在扩展中实现为默认函数,在该函数中调用一个带有参数并传递nil。但是我收到此错误:

  

传递给不带参数的调用的参数

我的代码:

public protocol MenuAccessible {
    var menuEntryViewController: UIViewController { get }
}

public protocol MenuTabBarControllerProtocol {
    func reloadTabs<T>(from uiProvider: T?) where T: MenuAccessible
    func reloadTabs()
}

public extension MenuTabBarControllerProtocol {
    func reloadTabs() {
        reloadTabs(from: nil) // error here, can't infer type
    }
}

很显然,编译器无法推断类型。例如,如果我传递所需类型的nilOptional),则编译器很高兴。例如:

struct MenuAccessibleObject: MenuAccessible {
    var menuEntryViewController: UIViewController { return UIViewController() }
}

public extension MenuTabBarControllerProtocol {
    func reloadTabs() {
        let menuAccessible: MenuAccessibleObject? = nil
        reloadTabs(from: menuAccessible) // passes nil, but compiler is happpy
    }
}

是否可以在默认函数实现中传递nil而不用创建该虚拟对象?

1 个答案:

答案 0 :(得分:1)

如果您将类型定义为T,我不明白您为什么在这里使用泛型MenuAccessible

以下只是编译器,没有任何问题

public protocol MenuAccessible {
    var menuEntryViewController: UIViewController { get }
}

public protocol MenuTabBarControllerProtocol {
    func reloadTabs(from uiProvider: MenuAccessible?)
    func reloadTabs()

}

public extension MenuTabBarControllerProtocol {
    func reloadTabs() {
        reloadTabs(from: nil)
    }

}

public extension MenuTabBarControllerProtocol {
    func reloadTabs(from uiProvider: MenuAccessible?)  {
        fatalError() // implement me
    }
}

编辑

我不知道这对您是否有用,但是请尝试

public protocol MenuAccessible {
    var menuEntryViewController: UIViewController { get }
}


public class UIProvider:NSObject {

}

public protocol MenuTabBarControllerProtocol {

    func reloadAllTheItems<T>(from uiProvider: T?) where T: UIProvider, T: MenuAccessible
    func reloadTabs()
}

public extension MenuTabBarControllerProtocol {

    func reloadTabs() {
        self.reloadAllTheItems(from: Temp())
    }

    func reloadAllTheItems (provider:(UIProvider &  MenuAccessible)) {

    }


}

class Temp: (UIProvider &  MenuAccessible) {
    var menuEntryViewController: UIViewController {
        return UIViewController()
    }

}