冗余约束“Self”:“AnyObject”

nai*_*aif 5 uiviewcontroller ios swift

我有这个协议:

protocol Container: class where Self: UIViewController {
    var containerView: UIView! { get }
    var currentChild: UIViewController? { get set }
    func remove(child viewController: UIViewController)
    func add(child viewController: UIViewController)
    func replaceCurrentViewController(with newChild: UIViewController)
}
Run Code Online (Sandbox Code Playgroud)

我面临的问题是它显示以下警告

冗余约束“Self”:“AnyObject”

这是因为我同时使用class & where Self: UIViewController,但我需要两者!原因在于我的协议扩展(见下文),我使用 UIViewController 方法,如果我删除class,我的扩展会显示一个错误,要求添加mutating,它不应该有,因为它是一个仅限类的协议。

extension Container {
    func remove(child viewController: UIViewController) {
        viewController.beginAppearanceTransition(false, animated: true)
        viewController.willMove(toParent: nil)
        viewController.removeFromParent()
        viewController.view.removeFromSuperview()
        viewController.endAppearanceTransition()
        currentChild = nil
    }

    func add(child viewController: UIViewController) {
        viewController.beginAppearanceTransition(true, animated: true)
        addChild(viewController)
        viewController.didMove(toParent: self)
        containerView.addSubview(viewController.view)
        viewController.view.frame = containerView.frame
        viewController.endAppearanceTransition()
        currentChild = viewController
    }

    func replaceCurrentViewController(with newChild: UIViewController) {
        if viewIfLoaded != nil, let currentChild = currentChild {
            if let parent = currentChild.parent, parent == self {
                remove(child: currentChild)
            }
            add(child: newChild)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,有没有更好的解决方案?我可以删除警告吗?

Kam*_*ran 3

实际上,您应该将该where子句放在 an 中extension,并将UIViewController具有默认实现的特定方法放入其中extension,以便只能UIViewController访问这些方法。

protocol Container: class {
    var containerView: UIView! { get }
    var currentChild: UIViewController? { get set }
}

extension Container where Self: UIViewController {
    func remove(child viewController: UIViewController) {
        viewController.beginAppearanceTransition(false, animated: true)
        viewController.willMove(toParent: nil)
        viewController.removeFromParent()
        viewController.view.removeFromSuperview()
        viewController.endAppearanceTransition()
        currentChild = nil
    }

    func add(child viewController: UIViewController) {
        viewController.beginAppearanceTransition(true, animated: true)
        addChild(viewController)
        viewController.didMove(toParent: self)
        containerView.addSubview(viewController.view)
        viewController.view.frame = containerView.frame
        viewController.endAppearanceTransition()
        currentChild = viewController
    }

    func replaceCurrentViewController(with newChild: UIViewController) {
        if viewIfLoaded != nil, let currentChild = currentChild {
            if let parent = currentChild.parent, parent == self {
                remove(child: currentChild)
            }
            add(child: newChild)
        }
    }
} 
Run Code Online (Sandbox Code Playgroud)