How to make Swift protocol conformed by a specific

2019-08-18 16:33发布

问题:

I wrote a protocol in Swift:

protocol FooDelegate{
    titleImage:UIImage? {get}
}

I want to make sure that the class that conforms to it must be a UITableViewController type.

In other words:

// ViewController conform FooDelegate is OK,Because ViewController 
// is inherit from UITableViewController!
class ViewController:UITableViewController,FooDelegate /* compile ok */{

}

// OtherVC is failed to conform FooDelegate,Because it is not inherit
// from UITableViewController.
class OtherVC:UIViewController,FooDelegate /* will compile error */{

}

How to do that?

I changed FooDelegate's definition to this:

protocol FooDelegate where Self:UITableViewController {
    var titleImage:UIImage? {get}
}

But it does not seem to work.

* FIX PART *: Use Self:UITableViewController is OK!!!

But when I write below is wrong when compiling :

class StubClass{
    var delegate:FooDelegate!

    func invoke(){
        let idxSet = ...
        delegate.tableView.reloadSections(idxSet, with: .none) //Error:Value of type 'FooDelegate' has no member 'tableView'
    }
}

Please look at the line that Error above. Isn't there any tableView property in delegate? delegate is conform to FooDelegate,and FooDelegate make Self:UITableViewController,and UITableViewController must have tableView property??!!

What's wrong here??? Thanks :)

回答1:

As tableView property is not visible to the protocol declaration you just need to add the tableView property in the protocol. Something like this:

@objc protocol FooDelegate where Self: UITableViewController {
    var tableView: UITableView { get }
}

class SimpleTableView: UITableViewController, FooDelegate {

}

let delegate: FooDelegate? = SimpleTableView()

delegate?.tableView.reloadData()

Remeber to add @objc in protocol declaration.



回答2:

Try this:

protocol FooDelegate: class where Self: UITableViewController {
    // code
}

And if you want certain extensions to be accessible by UITableViewController:

protocol FooDelegate {
    // code
}

extension FooDelegate where Self: UITableViewController {
    // code
}