ios - protocolos - que es un protocolo en swift
¿Cómo definir métodos opcionales en el protocolo Swift? (15)
¿Es posible en Swift? Si no es así, ¿hay una solución para hacerlo?
Aquí hay un ejemplo muy simple SOLAMENTE para Clases rápidas, y no para estructuras o enumeraciones. Tenga en cuenta que el método de protocolo es opcional, tiene dos niveles de encadenamiento opcional en juego. También la clase que adopta el protocolo necesita el atributo @objc en su declaración.
@objc protocol CollectionOfDataDelegate{
optional func indexDidChange(index: Int)
}
@objc class RootView: CollectionOfDataDelegate{
var data = CollectionOfData()
init(){
data.delegate = self
data.indexIsNow()
}
func indexDidChange(index: Int) {
println("The index is currently: /(index)")
}
}
class CollectionOfData{
var index : Int?
weak var delegate : CollectionOfDataDelegate?
func indexIsNow(){
index = 23
delegate?.indexDidChange?(index!)
}
}
Creo que antes de preguntar cómo puedes implementar un método de protocolo opcional, deberías preguntarte por qué deberías implementar uno.
Si pensamos en los protocolos rápidos como una interfaz en la programación orientada a objetos clásica, los métodos opcionales no tienen mucho sentido, y tal vez una mejor solución sería crear una implementación predeterminada o separar el protocolo en un conjunto de protocolos (quizás con algunas relaciones de herencia). entre ellos) para representar la posible combinación de métodos en el protocolo.
Para obtener más información, consulte https://useyourloaf.com/blog/swift-optional-protocol-methods/ , que ofrece una excelente visión general sobre este tema.
En Swift 3.0
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
Te ahorrará tiempo.
En Swift 2 y en adelante es posible agregar implementaciones predeterminadas de un protocolo. Esto crea una nueva forma de métodos opcionales en los protocolos.
protocol MyProtocol {
func doSomethingNonOptionalMethod()
func doSomethingOptionalMethod()
}
extension MyProtocol {
func doSomethingOptionalMethod(){
// leaving this empty
}
}
No es una forma realmente agradable de crear métodos de protocolo opcionales, pero le brinda la posibilidad de utilizar estructuras en las devoluciones de llamada de protocolo.
Escribí un pequeño resumen aquí: http://www.avanderlee.com/swift-2-0/optional-protocol-methods/
Las otras respuestas que implican marcar el protocolo como "@objc" no funcionan cuando se usan tipos específicos de swift.
struct Info {
var height: Int
var weight: Int
}
@objc protocol Health {
func isInfoHealthy(info: Info) -> Bool
}
//Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C"
Para declarar protocolos opcionales que funcionan bien con swift, declare las funciones como variables en lugar de func.
protocol Health {
var isInfoHealthy: (Info) -> (Bool)? { get set }
}
Y luego implementar el protocolo de la siguiente manera
class Human: Health {
var isInfoHealthy: (Info) -> (Bool)? = { info in
if info.weight < 200 && info.height > 72 {
return true
}
return false
}
//Or leave out the implementation and declare it as:
//var isInfoHealthy: (Info) -> (Bool)?
}
A continuación, puede utilizar "?" Comprobar si la función ha sido implementada o no.
func returnEntity() -> Health {
return Human()
}
var anEntity: Health = returnEntity()
var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))?
//"isHealthy" is true
Para definir el Protocol
Optional
en swift, debe usar la palabra clave @objc
antes de la Declaración de Protocol
y la declaración de attribute
/ method
dentro de ese protocolo. A continuación se muestra una muestra de propiedad opcional de un protocolo.
@objc protocol Protocol {
@objc optional var name:String?
}
class MyClass: Protocol {
// No error
}
Para ilustrar la mecánica de la respuesta de Antoine:
protocol SomeProtocol {
func aMethod()
}
extension SomeProtocol {
func aMethod() {
print("extensionImplementation")
}
}
class protocolImplementingObject: SomeProtocol {
}
class protocolImplementingMethodOverridingObject: SomeProtocol {
func aMethod() {
print("classImplementation")
}
}
let noOverride = protocolImplementingObject()
let override = protocolImplementingMethodOverridingObject()
noOverride.aMethod() //prints "extensionImplementation"
override.aMethod() //prints "classImplementation"
Ponga el @optional
frente a métodos o propiedades.
Si desea hacerlo en modo Swift puro, la mejor manera es proporcionar un componente de implementación predeterminado si devuelve un tipo Swift como, por ejemplo, estructura con tipos Swift.
ejemplo:
struct magicDatas {
var damagePoints : Int?
var manaPoints : Int?
}
protocol magicCastDelegate {
func castFire() -> magicDatas
func castIce() -> magicDatas
}
extension magicCastDelegate {
func castFire() -> magicDatas {
return magicDatas()
}
func castIce() -> magicDatas {
return magicDatas()
}
}
A continuación, puede implementar el protocolo sin define todas las funciones
Un enfoque Swift puro con herencia de protocolo:
//Required methods
protocol MyProtocol {
func foo()
}
//Optional methods
protocol MyExtendedProtocol: MyProtocol {
func bar()
}
class MyClass {
var delegate: MyProtocol
func myMethod() {
(delegate as? MyExtendedProtocol).bar()
}
}
Un poco alejado del tema de la pregunta original, pero se basa en la idea de Antoine y pensé que podría ayudar a alguien.
También puede hacer que las propiedades computadas sean opcionales para estructuras con extensiones de protocolo.
Puedes hacer una propiedad en el protocolo opcional.
protocol SomeProtocol {
var required: String { get }
var optional: String? { get }
}
Implementar la propiedad computada ficticia en la extensión del protocolo.
extension SomeProtocol {
var optional: String? { return nil }
}
Y ahora puede usar estructuras que tienen o no la propiedad opcional implementada
struct ConformsWithoutOptional {
let required: String
}
struct ConformsWithOptional {
let required: String
let optional: String?
}
También escribí cómo hacer propiedades opcionales en los protocolos de Swift en mi blog , que mantendré actualizado en caso de que las cosas cambien a través de las versiones de Swift 2.
Ya que hay algunas respuestas sobre cómo usar el modificador opcional y el atributo @objc para definir el protocolo de requisitos opcionales, daré una muestra sobre cómo usar las extensiones de protocolo para definir el protocolo opcional.
El siguiente código es Swift 3. *.
/// Protocol has empty default implementation of the following methods making them optional to implement:
/// `cancel()`
protocol Cancelable {
/// default implementation is empty.
func cancel()
}
extension Cancelable {
func cancel() {}
}
class Plane: Cancelable {
//Since cancel() have default implementation, that is optional to class Plane
}
let plane = Plane()
plane.cancel()
// Print out *United Airlines can''t cancelable*
Tenga en cuenta que los métodos de extensión de protocolo no pueden ser invocados por el código de Objective-C y, lo que es peor, el equipo Swift no los solucionará. https://bugs.swift.org/browse/SR-492
Aquí hay un ejemplo concreto con el patrón de delegación.
Configura tu protocolo:
@objc protocol MyProtocol:class
{
func requiredMethod()
optional func optionalMethod()
}
class MyClass: NSObject
{
weak var delegate:MyProtocol?
func callDelegate()
{
delegate?.requiredMethod()
delegate?.optionalMethod?()
}
}
Establecer el delegado a una clase e implementar el Protocolo. Ver que el método opcional no necesita ser implementado.
class AnotherClass: NSObject, MyProtocol
{
init()
{
super.init()
let myInstance = MyClass()
myInstance.delegate = self
}
func requiredMethod()
{
}
}
Una cosa importante es que el método opcional es opcional y necesita un "?" al llamar Mencione el segundo signo de interrogación.
delegate?.optionalMethod?()
Si desea utilizar métodos opcionales, debe marcar su protocolo con el atributo @objc
:
@objc protocol MyProtocol {
@objc optional func doSomething()
}
class MyClass : MyProtocol {
// no error
}
De lo contrario, los protocolos Swift se comportan como interfaces en otros idiomas OO, donde se deben implementar todos los métodos definidos en las interfaces.
- Debe agregar
optional
palabra claveoptional
antes de cada método. - Tenga en cuenta, sin embargo, que para que esto funcione, su protocolo debe estar marcado con el atributo @objc.
- Esto implica además que este protocolo sería aplicable a las clases pero no a las estructuras.