objective-c - tutorial - objective c vs swift
Objetivo C: Bloques vs. Selectores vs. Protocolos (2)
La forma "tradicional" de hacer esto es con un protocolo. Se usaron informales antes de que se agregara @protocol al lenguaje, pero eso fue antes de mi tiempo y durante al menos los últimos años se desalentaron los protocolos informales, especialmente dado el especificador @optional. En cuanto a un "delegado" que pasa dos SEL, esto parece más feo que declarar un protocolo formal, y en general no me parece correcto. Los bloques son muy nuevos (especialmente en iOS), como van las cosas, y aunque todavía tenemos que ver el tremendo volumen de documentación / blogs sobre el estilo mejor probado y verdadero, me gusta la idea, y este parece ser uno de Los bloques de cosas son mejores para: nuevas estructuras de flujo de control ordenadas.
Básicamente, lo que trato de decir es que cada uno de estos métodos varía en edad, sin que ninguno sea mejor que el anterior, excepto por el estilo, que obviamente cuenta con muchísima cantidad y, en última instancia, por qué se creó cada una de estas cosas. Básicamente, vaya con la cosa más nueva con la que se sienta cómodo, que debería ser un bloque o un protocolo formal, y que lo más probable es que su confusión provenga de la lectura de fuentes en conflicto porque fueron escritas en diferentes momentos, pero con el tiempo en perspectiva, es Claro para ver que supera a los demás.
[Controller askForSelection:^(id selection){
//blah blah blah
} canceled:^{
//blah blah blah
}];
es probablemente mucho más conciso que definir dos métodos adicionales, y un protocolo para ellos (formalmente o no) o pasar los SEL y almacenarlos en archivos ivars, etc.
Con frecuencia me encuentro escribiendo clases de "utilidad" que se pueden reutilizar a lo largo de mis proyectos.
Por ejemplo, supongamos que tengo una vista de "Libreta de direcciones". Es posible que desee utilizar mi libreta de direcciones para seleccionar a quién se le envía un correo electrónico o tal vez a quién se agrega a una convocatoria de reunión.
Desarrollé este controlador de vista para que lo puedan usar tanto el controlador de correo electrónico como el controlador de reuniones, con algún tipo de mecanismo de devolución de llamada para que la persona que llama sepa que el usuario terminó de seleccionar a alguien de la libreta de direcciones o que canceló.
Parece que básicamente hay cuatro enfoques (razonables) que se podrían tomar en este escenario;
Cree un protocolo "AddressBookDelegate" y una propiedad de delegado correspondiente en el AddressBookController. Luego use los mensajes definidos en el protocolo para comunicar el resultado (similar a UIActionSheetDelegate).
Cree un protocolo "informal" "AddressBookDelegate" y una propiedad de delegado correspondiente en el AddressBookController, pero el tipo de la propiedad de delegado será "id", y comprobará en tiempo de ejecución con "respondsToSelector:" para ver si el delegado implementa los métodos requiere (parece que la mayoría de las cosas del marco han comenzado a ir de esta manera).
Pase al AddressBookController un ID que representa a un delegado, así como dos SEL que especifican los métodos para llamar cuando el usuario selecciona un usuario o cancela la solicitud. El beneficio que veo con esto es; Supongamos que un controlador admite AMBOS mensajes de correo electrónico Y configuración de reuniones (sé que en este ejemplo parece un mal diseño ... pero se puede imaginar una situación más genérica en la que esto parezca perfectamente razonable para una clase de utilidad). En este caso, podría Pase el AddressBookController diferentes SELs dependiendo de si está agregando usuarios a un correo electrónico, o agregando usuarios a una reunión ... una gran mejora con respecto a una iVar para indicar el "estado" del controlador.
Pase el AddressBookController dos bloques; uno para ejecutar cuando el usuario selecciona a alguien de la libreta de direcciones y otro para ejecutar si el usuario cancela la solicitud.
Los bloques han sido tremendamente útiles para mí y, por lo tanto, mucho más elegantes, me encuentro casi confundido sobre cuándo NO usarlos.
Espero miembros más experimentados de la comunidad de StackOverflow de los que pueda ayudar con sus opiniones sobre este tema.
Me gustaría ir con su primer enfoque. Es un patrón probado y verdadero en Cocoa, y parece encajar muy bien en lo que estás haciendo.
Algunos comentarios sobre los otros enfoques:
- Protocolo informal : realmente no veo ninguna ventaja de hacer esto a través de un protocolo formal. Cada vez que los protocolos formales se obtienen
@optional
métodos@optional
, la utilidad de los protocolos informales es mucho menor. - Pasar SELs - No creo que este sea un patrón establecido en Cocoa. Personalmente, no lo consideraría mejor que el enfoque de delegado, pero si se ajusta mejor a su forma de pensar, entonces hágalo. Realmente no te estás deshaciendo del estado; solo te estas transformando en algo mas Personalmente, prefiero tener un ivar que pueda configurar y verificar sin tener que usar tipos de selector.
- Pasar bloques : este es un tipo de enfoque de la nueva era, y tiene cierto mérito. Sin embargo, creo que debes tener cuidado porque, en mi opinión, no se ajusta muy bien. Por ejemplo, si los métodos de fuente de datos y delegado de NSTableView fueran todos bloques, personalmente lo encontraría algo molesto. Imagina que si quisieras establecer 10 bloques diferentes, tu
-awakeFromNib
(o lo que sea) sería bastante grande. Los métodos individuales parecen más apropiados en este caso. Sin embargo, si está seguro de que nunca irá más allá de, digamos, dos métodos, entonces el enfoque de bloque parece más razonable.