【问题标题】:Redundant constraint 'Self' : 'AnyObject'冗余约束'Self':'AnyObject'
【发布时间】:2018-12-12 07:27:18
【问题描述】:

我有这个协议:

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)
}

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

冗余约束 'Self' : 'AnyObject'

这是因为我同时使用了 classwhere 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)
        }
    }
}

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

【问题讨论】:

标签: ios swift uiviewcontroller


【解决方案1】:

swift 4中你可以使用

protocol Container 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)
}

swift 5 中你可以使用

protocol Container: 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)
}

【讨论】:

    【解决方案2】:

    您实际上应该将where 子句放在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)
            }
        }
    } 
    

    【讨论】:

    • 我想过这个,但我想限制我的协议只能由视图控制器实现,所以其他类不能实现这个协议。只是为了让它尽可能正确,尽可能利用静态类型
    • @naif 是的,这是matt 的回答中提到的 Swift 中的一个问题。但是,如果您确实需要设置该限制,则可以通过引入 associatedtype 来实现。
    • 我建议您从协议要求中删除 remove()add()replaceCurrentViewController(),并将它们设为仅扩展方法(而不是默认实现)。真正的协议要求只是containerViewcurrentChild
    • @naif:“我想限制我的协议只能由视图控制器实现,因此其他类无法实现此协议。”这会误解协议,并且不会以任何方式利用静态类型。协议是对需求的描述,而不是对特定实现的需求。如果事物必须UIViewController,那么Container 应该是UIViewController 的子类,而不是协议。 (但协议在这里可能没问题,没有必要按照 Kamran 的示例将其作为视图控制器。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 1970-01-01
    • 2019-10-19
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多