Подтвердить что ты не робот

Что такое 'where self' в расширении протокола

Я видел так много примеров с форматом ниже

extension Protocolname where Self: UIViewController

Что находится where Self в расширении протокола. Я не мог найти документацию по этому вопросу.

4b9b3361

Ответ 1

Этот синтаксис: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID521

Рассмотрим:

protocol Meh {
    func doSomething();
}

//Extend protocol Meh, where `Self` is of type `UIViewController`
//func blah() will only exist for classes that inherit `UIViewController`. 
//In fact, this entire extension only exists for `UIViewController` subclasses.

extension Meh where Self: UIViewController {
    func blah() {
        print("Blah");
    }

    func foo() {
        print("Foo");
    }
}

class Foo : UIViewController, Meh { //This compiles and since Foo is a `UIViewController` subclass, it has access to all of `Meh` extension functions and `Meh` itself. IE: `doSomething, blah, foo`.
    func doSomething() {
        print("Do Something");
    }
}

class Obj : NSObject, Meh { //While this compiles, it won't have access to any of `Meh` extension functions. It only has access to `Meh.doSomething()`.
    func doSomething() {
        print("Do Something");
    }
}

Ниже приведена ошибка компилятора, поскольку Obj не имеет доступа к функциям расширения Meh.

let i = Obj();
i.blah();

Но ниже будет работать.

let j = Foo();
j.blah();

Другими словами, Meh.blah() доступен только для классов, которые имеют тип UIViewController.

Ответ 2

Вот пример, который объясняет, что в чем смысл использования self: UIViewController

protocol SBIdentifiable {
    static var sbIdentifier: String { get }
}

extension SBIdentifiable where Self: UIViewController {
    static var sbIdentifier: String {
        return String(describing: self)
    }
}

extension UIVieWcontroller: SBIdentifiable { }

class ViewController: UIViewController {
  func loadView() {
  /*Below line we are using the sbIdentifier which will return the 
   ViewController class name.
    and same name we would mentioned inside ViewController 
    storyboard ID. So that we do not need to write the identifier everytime. 
   So here where Self: UIViewController means it will only conform the protocol of type UIViewController*/ 

  let viewController = self.instantiateViewController(withIdentifier: 
    self.sbIdentifier) as? SomeBiewController
  }
}

Ответ 3

Вы можете найти тот же пример здесь: WWDC2015-408, (очень рекомендую посмотреть его, это иллюстрирует причину)

А также, еще один подобный пример - Расширения с общим условием Где

struct Stack<Element> {
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

Предложение where добавляет требование к расширению, так что расширение добавляет метод isTop (_ :) только тогда, когда элементы в стеке уравниваемы.

extension Stack where Element: Equatable {
    func isTop(_ item: Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        return topItem == item
    }
}