protocol inside example delegate and protocols swift

protocols - inside - swift protocol and delegate example



Cómo pasar un protocolo como parámetro en Swift (5)

En Objective-C, sé cómo pasar un protocol como parámetro:

- (void)MyMethod:(Protocol *)myparameter

Pero en Swift no hay más tipo de Protocol .

¿Cómo puedo pasar un protocolo como parámetro sin saber cuál es?


Diseñó una manera hoy (Xcode 6.1):

En primer lugar, el protocolo debe estar marcado como @objc para que cualquier comprobación funcione. Luego use un molde "if let" para verificar la conformidad.

@objc protocol MyProtocol { var protocolValue: Int { get set } } if let conformingObject = someObject as? MyProtocol { // conformingObject is now someObject cast to MyProtocol conformingObject.protocolValue = 3 }


En Swift 2.0, lo uso así antes:

classA.conformsToProtocol(XXXProtocol.self as! Protocol)

No funciona bien ...

Mira la definición de Protocol:

// All methods of class Protocol are unavailable. // Use the functions in objc/runtime.h instead. @available(iOS 2.0, *) public class Protocol { }

Todos no están disponibles ... y no sé cuál usar en objc / runtime.h

Así que tengo que usar este método:

if ClassA is protocol<XXXProtocol> { // do something }

Actualmente funciona ...


En uno de tus comentarios dices:

"Quiero crear un método que devuelva una matriz de tipo de clase que implemente un protocolo deseado".

¿Has probado algo como lo siguiente?

//notice the use of @objc here @objc protocol AlertProtocol { func getMyName()->String } class Class1 : AlertProtocol { let name = "Object 1" func getMyName() -> String { return name } } class Class2 : AlertProtocol { let name = "Object 2" func getMyName() -> String { return name } } //borrowing from and refactoring siLo''s answer func classesConformingToProtocol(proto:Protocol) -> [AnyClass] { let availableClasses : [AnyClass] = [ Class1.self, Class2.self ] var conformingClasses = Array<AnyClass>() for myClass : AnyClass in availableClasses { if myClass.conforms(to: proto) { conformingClasses.append(myClass) } } return conformingClasses }

Luego usa la estructura anterior como esta:

let classes = classesConformingToProtocol(AlertProtocol.self)

La parte difícil que hace el trabajo es el "@objc" que expone el protocolo al tiempo de ejecución objetivo y nos permite pasar cualquier "Tipo de protocolo" como parámetro.

Probablemente en algún momento en el futuro podamos hacer esto de una manera "pura" y rápida.


Esto es lo que he intentado:

@objc protocol Walker { func walk() } @objc protocol Runner { func run() } @objc class Zombie : Walker { func walk () { println("Brains...") } } @objc class Survivor : Runner { func run() { println("Aaaah, zombies!") } } func classesConformingToProtocol(proto:Protocol) -> AnyClass[] { let availableClasses : AnyClass[] = [ Zombie.self, Survivor.self ] var conformingClasses = Array<AnyClass>() for myClass : AnyClass in availableClasses { if myClass.conformsToProtocol(proto) { conformingClasses.append(myClass) } } return conformingClasses } // This does not work let walkers = classesConformingToProtocol(Walker.self) let runners = classesConformingToProtocol(Runner.self)

No he podido convertir la información Metatype de Swift en un objeto de Protocol .


Si no permite el uso de @objc (porque sus protocolos tienen propiedades, por ejemplo), la única solución que encontré es con el cierre. Luego, necesita usar un cierre para usar un protocolo y devolver un valor.

protocol Proto { } protocol Proto2 { } class Foo: Proto { } class Bar: Proto, Proto2 { } class Baz: Proto2 { } class Qux { } func printConforms(classList: [AnyClass], protoCond: (AnyClass) -> Any?) { for i in classList { print(i, terminator: " -> ") if protoCond(i) != nil { print("is subscriber") } else { print("NOT IS subscriber") } } } let myClasses: [AnyClass] = [Foo.self, Bar.self, Baz.self, Qux.self] printConforms(classList: myClasses, protoCond: { $0 as? Proto.Type })

Ejemplo más completo: https://gist.github.com/brunomacabeusbr/eea343bb9119b96eed3393e41dcda0c9

Editar

Otra solución mejor es usar genéricos, por ejemplo:

protocol Proto { } class Foo: Proto { } class Bar: Proto { } class Baz { } func filter<T>(classes: [AnyClass], byConformanceTo: T.Type) -> [AnyClass] { return classes.filter { $0 is T } } filter(classes: [Foo.self, Bar.self, Baz.self], byConformanceTo: Proto.Type.self) // return [Foo.self, Bar.self]