suzuki - swift(lenguaje de programación)




Ocultar la adopción del protocolo en veloz. (2)

Me preguntaba si podría hacer una adopción oculta de un protocolo de forma rápida.

En Objective-C, usaría un encabezado privado en el archivo m para ocultar los protocolos que no quiero que queden expuestos al exterior. ¿Es algo así posible en veloz? Poner un "privado" antes del protocolo no funciona, aparentemente :)


Tal vez el idioma ha cambiado desde el post, pero funciona para mí. Este es un ejemplo de dónde quise ocultar un inicializador para controlar la vida útil de un objeto y realizar el procesamiento posterior. En este caso, quería rastrear y enviar análisis, basados ​​en la configuración de la persona que llama.

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

}

Edición: Encontré una forma sencilla de ocultarlo. Al menos a partir de la información de ayuda rápida de xcode: simplemente ponga la adopción y la implementación en una extensión de su clase y no se mostrará allí.

Respuesta original:

Se me ocurrió este ejemplo, inspirado en clases internas en Java. Aquí MyVC no expone que implementa UICollectionViewDelegate para propósitos internos, mientras que la implementación delegada tiene acceso a las variables privadas de 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
}

Tenga en cuenta que HiddenDelegateImpl también podría ser una clase interna de MyVC, elegí ponerlo fuera para facilitar la lectura.

En contraste con Java, las instancias de clases internas necesitan una instancia de la clase externa para existir. Dado que este no es el caso con Swift, necesitamos tener la solución outer .

También hay un buen ejemplo que se centra en la implementación de delegados.

Edición: convirtió al delegado en una variable de instancia en la clase externa para retenerla y la referencia a la clase externa débil para evitar retener ciclos.





swift