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

Скрыть принятие протокола быстрым

Мне было интересно, могу ли я сделать скрытое принятие протокола в swift.

В Objective-C, я бы использовал закрытый заголовок в файле m., чтобы скрыть протоколы, которые я не хочу показывать снаружи. Что-то вроде этого возможно в быстром? Ввод "private" до того, как протокол не работает, по-видимому:)

4b9b3361

Ответ 1

Изменить: Найдите простой способ скрыть его. По крайней мере, из быстрой справочной информации xcode: просто введите усыновление и реализацию в расширение вашего класса, и оно не появится там.

Исходный ответ:

Я придумал этот пример, вдохновленный внутренними классами Java. Здесь MyVC не показывает, что он реализует UICollectionViewDelegate для внутренних целей, тогда как реализация делегата имеет доступ к MyVC частным переменным.

public class MyVC: UIViewController {

    private let a = 4 as Int
    private var hiddenDelegate: HiddenDelegateImpl?

    public override func viewDidLoad() {
        super.viewDidLoad()
        hiddenDelegate = HiddenDelegateImpl(outer: self)
        innerCollectionView.delegate = hiddenDelegate
    }
}

private class HiddenDelegateImpl: NSObject, UICollectionViewDelegate {

    private weak var outer: MyVC?

    init(outer: MyVC) {
        self.outer = outer
        super.init()
    }

    private func doStuff() -> Int {
        // can access private variables of outer class
        return outer?.a
    }

    // implement delegate methods here
}

Обратите внимание, что HiddenDelegateImpl также может быть внутренним классом MyVC, я выбрал его для чтения для чтения.

В отличие от экземпляров Java для внутренних классов необходим экземпляр внешнего класса. Так как это не так с Swift, нам необходимо обходное решение outer.

Существует также этот хороший пример, в котором основное внимание уделяется реализации делегата.

Изменить: Сделал делегат переменной экземпляра во внешнем классе, чтобы сохранить его, а ссылка на внешний класс слаба, чтобы избежать сохранения циклов.

Ответ 2

Возможно, язык изменился со времени публикации, но он работает для меня. Это пример того, где я хотел скрыть инициализатор, чтобы контролировать время жизни объекта и выполнять пост-обработку. В этом случае я хотел отслеживать и отправлять аналитику на основе конфигурации вызывающего абонента.

private protocol Reportable {
    init()
    var people:[String:AnyObject] { get }
    var track:[String:AnyObject] { get }
}


public class Analytics {

    public final class Alpha: Reportable {

        var thingOne: String?
        var thingTwo: String?

        private init() {}
        private var people:[String:AnyObject] { return [:] }
        private var track:[String:AnyObject] { return [:] }
    }

    public final class Bravo: Reportable {

        var thingOne: String?
        var thingTwo: String?

        private init() {}
        private var people:[String:AnyObject] { return [:] }
        private var track:[String:AnyObject] { return [:] }
    }


    public static func alpha(configure:Alpha -> ()) {
        return report(configure)
    }

    public static func bravo(configure:Bravo -> ()) {
        return report(configure)
    }


    private static func report<T:Reportable>(configure:T -> ()) {
        let event = T()
        configure(event)
        Analytics.doSomething()
    }


    static func doSomething() {

    }
}

// separate file
func clientCode() {

    Analytics.alpha { event in

        event.track // error

        event.thingOne = "foo"
        event.thingTwo = "bar"  }

    Analytics.bravo { event in
        event.thingOne = "foo"
        event.thingTwo = "bar"  }

}