Acabo de comenzar a programar Objective-C y, teniendo experiencia en Java, me pregunto cómo las personas que escriben programas Objective-C manejan métodos privados.
Entiendo que puede haber varias convenciones y hábitos y pienso en esta pregunta como un agregador de las mejores técnicas que las personas usan para tratar con métodos privados en Objective-C.
Incluya un argumento para su enfoque cuando lo publique. ¿Por qué es bueno? ¿Qué inconvenientes tiene (que usted sepa) y cómo lidiar con ellos?
En cuanto a mis hallazgos hasta ahora.
Es posible utilizar categorías [por ejemplo, MyClass (Private)] definidas en el archivo MyClass.m para agrupar métodos privados.
Este enfoque tiene 2 problemas:
- Xcode (¿y el compilador?) No comprueba si define todos los métodos en la categoría privada en el bloque @implementation correspondiente
- Debe poner @interface declarando su categoría privada al comienzo del archivo MyClass.m, de lo contrario, Xcode se queja con un mensaje como "self puede no responder al mensaje" privateFoo ".
El primer problema se puede solucionar con una categoría vacía [por ejemplo, MyClass ()].
El segundo me molesta mucho. Me gustaría ver métodos privados implementados (y definidos) cerca del final del archivo; No sé si eso es posible.
fuente
Respuestas:
No hay, como ya han dicho otros, un método privado en Objective-C. Sin embargo, a partir de Objective-C 2.0 (que significa Mac OS X Leopard, iPhone OS 2.0 y posterior) puede crear una categoría con un nombre vacío (es decir,
@interface MyClass ()
llamado Extensión de clase) . Lo único de una extensión de clase es que las implementaciones de los métodos deben ir de la misma manera@implementation MyClass
que los métodos públicos. Entonces estructuro mis clases así:En el archivo .h:
Y en el archivo .m:
Creo que la mayor ventaja de este enfoque es que le permite agrupar las implementaciones de sus métodos por funcionalidad, no por la distinción público / privado (a veces arbitrario).
fuente
if (bSizeDifference && [self isSizeDifferenceSignificant:fWidthCombined])...
Cometí este error y el compilador salió bien hasta que anidé una llamada como esta: Entonces fWidthCombined siempre aparecía como 0.Realmente no existe un "método privado" en Objective-C, si el tiempo de ejecución puede determinar qué implementación usar lo hará. Pero eso no quiere decir que no haya métodos que no sean parte de la interfaz documentada. Para esos métodos, creo que una categoría está bien. En lugar de poner el
@interface
en la parte superior del archivo .m como su punto 2, lo pondría en su propio archivo .h. Una convención que sigo (y he visto en otros lugares, creo que es una convención de Apple, ya que Xcode ahora brinda soporte automático) es nombrar dicho archivo después de su clase y categoría con un + separándolos, por lo que@interface GLObject (PrivateMethods)
se puede encontrar en élGLObject+PrivateMethods.h
. La razón para proporcionar el archivo de encabezado es para que pueda importarlo en sus clases de prueba de unidad :-).Por cierto, en lo que respecta a la implementación / definición de métodos cerca del final del archivo .m, puede hacerlo con una categoría implementando la categoría en la parte inferior del archivo .m:
o con una extensión de clase (lo que llama una "categoría vacía"), simplemente defina esos métodos al final. Los métodos Objective-C se pueden definir y utilizar en cualquier orden en la implementación, por lo que no hay nada que le impida colocar los métodos "privados" al final del archivo.
Incluso con las extensiones de clase, a menudo crearé un encabezado separado (
GLObject+Extension.h
) para poder usar esos métodos si es necesario, imitando la visibilidad de "amigo" o "protegido".Desde que esta respuesta se escribió originalmente, el compilador clang ha comenzado a hacer dos pases para los métodos Objective-C. Esto significa que puede evitar declarar completamente sus métodos "privados", y si el compilador los encontrará por encima o por debajo del sitio de llamada.
fuente
Si bien no soy un experto en Objective-C, personalmente solo defino el método en la implementación de mi clase. Por supuesto, debe definirse antes (arriba) de cualquier método que lo llame, pero definitivamente requiere la menor cantidad de trabajo.
fuente
Definir sus métodos privados en el
@implementation
bloque es ideal para la mayoría de los propósitos. Clang los verá dentro del@implementation
, independientemente del orden de la declaración. No es necesario declararlos en una continuación de clase (también conocida como extensión de clase) o categoría con nombre.En algunos casos, deberá declarar el método en la continuación de la clase (por ejemplo, si usa el selector entre la continuación de la clase y el
@implementation
).static
Las funciones son muy buenas para métodos privados particularmente sensibles o críticos para la velocidad.Una convención para nombrar prefijos puede ayudarlo a evitar anular accidentalmente métodos privados (encuentro el nombre de la clase como un prefijo seguro).
Las categorías con nombre (por ejemplo
@interface MONObject (PrivateStuff)
) no son una idea particularmente buena debido a posibles colisiones de nombres al cargar. En realidad, solo son útiles para métodos protegidos o amigos (que rara vez son una buena opción). Para asegurarse de que se le advierta sobre implementaciones de categoría incompletas, en realidad debería implementarlo:Aquí hay una pequeña hoja de trucos anotada:
MONObject.h
MONObject.m
Otro enfoque que puede no ser obvio: un tipo C ++ puede ser muy rápido y proporcionar un grado de control mucho mayor, al tiempo que minimiza el número de métodos objc exportados y cargados.
fuente
Podría intentar definir una función estática debajo o encima de su implementación que tome un puntero a su instancia. Podrá acceder a cualquiera de sus variables de instancias.
fuente
¿Podrías usar bloques?
Soy consciente de que esta es una vieja pregunta, pero es una de las primeras que encontré cuando estaba buscando una respuesta a esta misma pregunta. No he visto esta solución discutida en ningún otro lado, así que avíseme si hay algo tonto al hacer esto.
fuente
static
). Pero he estado experimentando con la asignación de bloques a ivars privados (desde el método init), un poco estilo JavaScript, que también permite el acceso a ivars privados, algo que no es posible desde las funciones estáticas. Aún no estoy seguro de cuál prefiero.Todos los objetos en el Objetivo C se ajustan al protocolo NSObject, que se mantiene en el método performSelector . También estaba buscando una forma de crear algunos métodos "auxiliares o privados" que no necesitaba exponer a nivel público. Si desea crear un método privado sin gastos generales y sin tener que definirlo en su archivo de encabezado, intente esto ...
defina su método con una firma similar al código siguiente ...
luego, cuando necesite hacer referencia al método, simplemente llámelo como selector ...
esta línea de código invocará el método que creó y no tendrá una advertencia molesta sobre no tenerlo definido en el archivo de encabezado.
fuente
Si desea evitar el
@interface
bloqueo en la parte superior, siempre puede colocar las declaraciones privadas en otro archivo queMyClassPrivate.h
no es ideal pero que no complica la implementación.MyClass.h
MyClassPrivate.h
MyClass.m
fuente
Una cosa más que no he visto aquí: Xcode admite archivos .h con "_private" en el nombre. Digamos que tiene una clase MyClass: tiene MyClass.m y MyClass.h y ahora también puede tener MyClass_private.h. Xcode lo reconocerá y lo incluirá en la lista de "Contrapartes" en el Editor Asistente.
fuente
No hay forma de evitar el problema # 2. Así es como funciona el compilador de C (y, por lo tanto, el compilador de Objective-C). Si usa el editor XCode, la ventana emergente de funciones debería facilitar la navegación por los bloques
@interface
y@implementation
en el archivo.fuente
Hay un beneficio de la ausencia de métodos privados. Puede mover la lógica que pretendía ocultar a la clase separada y usarla como delegado. En este caso, puede marcar el objeto delegado como privado y no será visible desde el exterior. Mover la lógica a la clase separada (quizás varias) hace un mejor diseño de su proyecto. Porque tus clases se vuelven más simples y tus métodos se agrupan en clases con nombres propios.
fuente
Como otras personas dijeron, definir métodos privados en el
@implementation
bloque está bien para la mayoría de los propósitos.Sobre el tema de la organización del código : me gusta mantenerlos juntos
pragma mark private
para facilitar la navegación en Xcodefuente