Pregunta

Sé de HIG (¡que es bastante útil!), pero qué prácticas de programación utilizas al escribir Objective-C, y más específicamente cuando usas Cocoa (o CocoaTouch).

¿Fue útil?

Solución

He empezado a hacer algunas cosas que no creo que sean estándar:

1) Con la llegada de las propiedades, ya no uso " _ " para prefijar " privado " variables de clase Después de todo, si otras clases pueden acceder a una variable, ¿no debería haber una propiedad para ella? Siempre me ha disgustado el " _ " prefijo para hacer el código más feo, y ahora puedo omitirlo.

2) Hablando de cosas privadas, prefiero colocar las definiciones de métodos privados dentro del archivo .m en una extensión de clase, de este modo:

#import "MyClass.h"

@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end

@implementation MyClass

¿Por qué abarrotar el archivo .h con cosas que los forasteros no deberían preocuparse? El empty () funciona para categorías privadas en el archivo .m, y emite advertencias de compilación si no implementa los métodos declarados.

3) He comenzado a colocar dealloc en la parte superior del archivo .m, justo debajo de las directivas @synthesize. ¿No debería estar en la parte superior de la lista de cosas que quiere pensar en una clase? Esto es especialmente cierto en un entorno como el iPhone.

3.5) En las celdas de la tabla, haga que todos los elementos (incluida la celda) sean opacos para el rendimiento. Eso significa establecer el color de fondo apropiado en todo.

3.6) Al usar un NSURLConnection, como regla, es posible que desee implementar el método de delegado:

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                  willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
      return nil;
}

La mayoría de las llamadas web son muy singulares y es más una excepción que la regla que deseará que las respuestas se almacenen en caché, especialmente para las llamadas de servicios web. Implementar el método como se muestra deshabilita el almacenamiento en caché de respuestas.

También de interés, son algunos buenos consejos específicos para iPhone de Joseph Mattiello (recibidos en una lista de correo de iPhone). Hay más, pero estos fueron los más útiles en general que pensé (tenga en cuenta que algunos bits ahora se han editado ligeramente desde el original para incluir detalles ofrecidos en las respuestas):

4) Use solo precisión doble si tiene que hacerlo, como cuando trabaja con CoreLocation. Asegúrate de terminar las constantes en 'f' para que gcc las almacene como flotadores.

float val = someFloat * 2.2f;

Esto es principalmente importante cuando someFloat puede ser un doble, no necesitas las matemáticas de modo mixto, ya que estás perdiendo precisión en 'val' en el almacenamiento. Si bien los números de punto flotante son compatibles con el hardware en los iPhones, aún puede tomar más tiempo hacer aritmética de doble precisión en lugar de precisión simple. Referencias:

En los teléfonos más antiguos, los cálculos supuestamente funcionan a la misma velocidad, pero puedes tener más componentes de precisión simple en los registros que en los dobles, por lo que para muchos cálculos, la precisión única será más rápida.

5) Establezca sus propiedades como nonatomic . Son atomic por defecto y luego de la síntesis, se creará un código de semáforo para evitar problemas de subprocesos múltiples. Es probable que el 99% de usted no tenga que preocuparse por esto y el código está mucho menos hinchado y es más eficiente en memoria cuando se configura en no atómico.

6) SQLite puede ser una forma muy rápida de almacenar grandes conjuntos de datos. Una aplicación de mapas, por ejemplo, puede almacenar en caché sus mosaicos en archivos SQLite. La parte más cara es la E / S del disco. Evite muchas escrituras pequeñas enviando BEGIN; y COMMIT; entre bloques grandes. Usamos un temporizador de 2 segundos, por ejemplo, que se reinicia en cada nuevo envío. Cuando expira, enviamos COMMIT; , lo que hace que todas tus escrituras vayan en una gran parte. SQLite almacena los datos de la transacción en el disco y al hacer esto, el ajuste Comenzar / Terminar evita la creación de muchos archivos de transacciones, agrupando todas las transacciones en un solo archivo.

Además, SQL bloqueará su GUI si está en su hilo principal. Si tiene una consulta muy larga, es una buena idea almacenar sus consultas como objetos estáticos y ejecutar su SQL en un hilo separado. Asegúrese de envolver todo lo que modifique la base de datos para las cadenas de consulta en los bloques @synchronize () {} . Para consultas cortas, simplemente deje las cosas en el hilo principal para una mayor comodidad.

Hay más sugerencias de optimización de SQLite aquí, aunque el documento parece desactualizado, probablemente muchos de los puntos aún sean buenos;

http://web.utk.edu/~jplyon/sQLite_optimization_FAQ .html

Otros consejos

No utilice cadenas desconocidas como cadenas de formato

Cuando los métodos o funciones toman un argumento de cadena de formato, debes asegurarte de que tienes control sobre el contenido de la cadena de formato.

Por ejemplo, al registrar cadenas, es tentador pasar la variable de cadena como único argumento a NSLog :

    NSString *aString = // get a string from somewhere;
    NSLog(aString);

El problema con esto es que la cadena puede contener caracteres que se interpretan como cadenas de formato. Esto puede llevar a problemas erróneos de salida, bloqueos y seguridad. En su lugar, debe sustituir la variable de cadena en una cadena de formato:

    NSLog(@"%@", aString);

Use las convenciones y la terminología de nomenclatura y cacao estándar de Cocoa en lugar de lo que esté acostumbrado en otro entorno. Existen muchos desarrolladores de Cocoa, y cuando otro de ellos comience a trabajar con su código, será mucho más accesible si se ve y se parece a otros códigos de Cocoa.

Ejemplos de qué hacer y qué no hacer:

  • No declare id m_something; en la interfaz de un objeto y llámelo un variable miembro o campo ; use algo o _something para su nombre y llámelo una variable de instancia .
  • No nombre a un captador -getSomething ; el nombre correcto de Cocoa es simplemente -algo .
  • No nombre a un establecedor -algo: ; debe ser -setSomething:
  • El nombre del método está entremezclado con los argumentos e incluye dos puntos; es - [NSObject performSelector: withObject:] , no NSObject :: performSelector .
  • Use inter-caps (CamelCase) en nombres de métodos, parámetros, variables, nombres de clases, etc. en lugar de barras de abajo (guiones bajos).
  • Los nombres de clase comienzan con una letra mayúscula, variables y nombres de método con minúsculas.

Cualquier otra cosa que haga, no use la notación húngara al estilo Win16 / Win32. Incluso Microsoft renunció a eso con el cambio a la plataforma .NET.

IBOutlets

Históricamente, la gestión de la memoria de las salidas ha sido deficiente. La mejor práctica actual es declarar los puntos de venta como propiedades:

@interface MyClass :NSObject {
    NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end

El uso de propiedades hace que la semántica de administración de memoria sea clara; también proporciona un patrón consistente si utiliza la síntesis de variables de instancia.

Utilice el analizador estático LLVM / Clang

NOTA: bajo Xcode 4, esto ahora está integrado en el IDE.

Usted utiliza el Clang Static Analyzer para, como era de esperar, analizar su C y su objetivo -Código C (aún no C ++) en Mac OS X 10.5. Es trivial de instalar y usar:

  1. Descargue la última versión desde esta página .
  2. Desde la línea de comandos, cd a su directorio de proyecto.
  3. Ejecute scan-build -k -V xcodebuild .

(Existen algunas restricciones adicionales, etc., en particular, debe analizar un proyecto en su configuración de "depuración" - ver http://clang.llvm.org/StaticAnalysisUsage.html para obtener más información, pero eso es más o menos lo que se reduce a.)

Luego, el analizador produce un conjunto de páginas web que muestran la administración de memoria probable y otros problemas básicos que el compilador no puede detectar.

Esto es sutil pero práctico. Si te estás pasando a ti mismo como delegado a otro objeto, restablece el delegado de ese objeto antes de que dealloc .

- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}

Al hacer esto, se asegura de que no se enviarán más métodos de delegado. Cuando esté a punto de dealloc y desaparezca en el éter, asegúrese de que nada pueda enviarle más mensajes por accidente. Recuerda que self.someObject puede ser retenido por otro objeto (podría ser un singleton o en el grupo de autorelease o lo que sea) y hasta que le digas "¡deja de enviarme mensajes!", Piensa que estás a punto de comenzar. El objeto desasignado es un juego justo.

Adquirir este hábito te salvará de muchos choques extraños que son difíciles de depurar.

El mismo principio se aplica a Key Value Observation, y NSNotifications también.

Editar:

Aún más defensivo, cambio:

self.someObject.delegate = NULL;

en:

if (self.someObject.delegate == self)
    self.someObject.delegate = NULL;

@kendell

En lugar de:

@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end

Uso:

@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end

Nuevo en Objective-C 2.0.

Las extensiones de clase se describen en la Referencia de Objective-C 2.0 de Apple.

" Las extensiones de clase te permiten declarar la API adicional requerida para una clase en ubicaciones diferentes a las del bloque de interfaz principal de la clase primaria "

Así que son parte de la clase real, y NO de una categoría (privada) además de la clase. Diferencia sutil pero importante.

Evitar el autorelease

Debido a que normalmente (1) no tiene control directo sobre su vida útil, los objetos lanzados automáticamente pueden persistir durante un tiempo comparativamente largo y aumentar innecesariamente la huella de memoria de su aplicación. Si bien en el escritorio esto puede tener poca importancia, en plataformas más restringidas puede ser un problema importante. Por lo tanto, en todas las plataformas, y especialmente en las plataformas más restringidas, se considera la mejor práctica evitar el uso de métodos que conduzcan a la publicación automática de objetos y, en cambio, se recomienda utilizar el patrón alloc / init.

Por lo tanto, en lugar de:

aVariable = [AClass convenienceMethod];

donde puedas, deberías usar:

aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];

Cuando está escribiendo sus propios métodos que devuelven un objeto recién creado, puede aprovechar convención de nomenclatura de Cocoa para indicar al receptor que debe liberarse antes de añadir el nombre del método con " nuevo ".

Por lo tanto, en lugar de:

- (MyClass *)convenienceMethod {
    MyClass *instance = [[[self alloc] init] autorelease];
    // configure instance
    return instance;
}

podrías escribir:

- (MyClass *)newInstance {
    MyClass *instance = [[self alloc] init];
    // configure instance
    return instance;
}

Dado que el nombre del método comienza con " nuevo " ;, los consumidores de su API saben que son responsables de liberar el objeto recibido (consulte, por ejemplo, NSObjectController's newObject método ).

(1) Puede tomar el control utilizando sus propios grupos locales de autorelease. Para obtener más información sobre esto, consulte Autorelease Pools .

Algunos de estos ya se han mencionado, pero esto es lo que se me ocurre:

  • Siga las reglas de nomenclatura de KVO. Incluso si no usa KVO ahora, en mi experiencia muchas veces sigue siendo beneficioso en el futuro. Y si está utilizando KVO o enlaces, necesita saber que las cosas van a funcionar de la manera en que deben hacerlo. Esto abarca no solo los métodos de acceso y las variables de instancia, sino también las relaciones a muchos, la validación, las claves dependientes de notificación automática, etc.
  • Coloque métodos privados en una categoría. No solo la interfaz, sino también la implementación. Es bueno tener una cierta distancia conceptual entre los métodos privados y no privados. Incluyo todo en mi archivo .m.
  • Coloque los métodos de subproceso en segundo plano en una categoría. Igual que arriba. Descubrí que es bueno mantener una barrera conceptual clara cuando estás pensando en qué hay en el hilo principal y qué no.
  • Use #pragma mark [section] . Por lo general, agrupo por mis propios métodos, las anulaciones de cada subclase y cualquier información o protocolo formal. Esto hace que sea mucho más fácil saltar exactamente a lo que estoy buscando. Sobre el mismo tema, agrupe los métodos similares (como los métodos de delegado de una vista de tabla), no los pegue en cualquier lugar.
  • Prefijo métodos privados & amp; ivars with _. Me gusta su apariencia, y es menos probable que use un ivar cuando me refiero a una propiedad por accidente.
  • No utilice métodos / propiedades de mutador en init & amp; dealloc. Nunca me ha pasado nada malo por eso, pero puedo ver la lógica si cambias el método para hacer algo que depende del estado de tu objeto.
  • Poner IBOutlets en propiedades. En realidad, acabo de leer este aquí, pero voy a empezar a hacerlo. Independientemente de los beneficios de la memoria, parece mejor estilísticamente (al menos para mí).
  • Evita escribir el código que no necesitas absolutamente. Esto realmente cubre muchas cosas, como hacer ivars cuando una #define funcionará, o almacenar una matriz en su lugar. de ordenarlo cada vez que se necesiten los datos. Hay mucho que puedo decir sobre esto, pero la conclusión es que no escriba código hasta que lo necesite, o que el generador de perfiles le indique que lo haga. Hace que las cosas sean mucho más fáciles de mantener a largo plazo.
  • Termina lo que empiezas. Tener un montón de código de buggy a medio terminar es la forma más rápida de aniquilar a un proyecto. Si necesita un método de código auxiliar que esté bien, simplemente indíquelo insertando NSLog (@ " stub ") dentro, o como quiera que haga un seguimiento de las cosas.

Escribir pruebas unitarias. Puedes probar un lote de cosas en Cocoa que podrían ser más difíciles en otros marcos. Por ejemplo, con el código UI, generalmente puede verificar que las cosas estén conectadas como deberían estar y confiar en que funcionarán cuando se utilicen. Y puede configurar el estado y amp; invoque los métodos de delegado fácilmente para probarlos.

Tampoco tiene visibilidad de métodos públicos frente a protegidos frente a métodos privados que impiden la realización de pruebas para sus internos.

Regla de oro: ¡Si alloc entonces release !

ACTUALIZACIÓN: a menos que esté utilizando ARC

No escriba Objective-C como si fuera Java / C # / C ++ / etc.

Una vez vi a un equipo acostumbrado a escribir aplicaciones web Java EE intentar escribir una aplicación de escritorio Cocoa. Como si fuera una aplicación web Java EE. Había una gran cantidad de AbstractFooFactory y FooFactory e IFoo y Foo volando cuando todo lo que necesitaban era una clase de Foo y posiblemente un protocolo de Fooable.

Parte de asegurarse de no hacer esto es entender realmente las diferencias en el idioma. Por ejemplo, no necesita las clases abstractas de fábrica y de fábrica anteriores porque los métodos de clase de Objective-C se distribuyen de forma tan dinámica como los métodos de instancia, y se pueden anular en subclases.

Asegúrese de marcar la página Magia de depuración . Esta debería ser tu primera parada cuando te golpees la cabeza contra una pared mientras intentas encontrar la fuente de un error de Cocoa.

Por ejemplo, te dirá cómo encontrar el método en el que primero asignaste la memoria que luego causa bloqueos (como durante la finalización de la aplicación).

Ordenar las cadenas como el usuario quiere

Cuando ordena cadenas para presentar al usuario, no debe usar el método simple compare: . En su lugar, siempre debe usar métodos de comparación localizados como localizedCompare: o localizedCaseInsensitiveCompare: .

Para obtener más detalles, consulte Búsqueda, comparación y clasificación Cuerdas .

Intente evitar lo que ahora he decidido llamar Newbiecategoryaholism. Cuando los recién llegados a Objective-C descubren categorías, a menudo se vuelven locos, agregando pequeñas categorías útiles a cada clase existente ( " ¿Qué? Puedo agregar un método para convertir un número a números romanos a NSNumber rock on! & Quot; ).

No hagas esto.

Su código será más portátil y más fácil de entender sin docenas de pequeños métodos de categorías sobre dos docenas de clases básicas.

La mayoría de las veces, cuando realmente crees que necesitas un método de categoría para simplificar algunos códigos, verás que nunca terminarás reutilizando el método.

También hay otros peligros, a menos que esté marcando el nombre de sus métodos de categoría (¿y quién además del ddribin completamente insano es?) existe la posibilidad de que Apple, o un complemento, o alguna otra cosa que se ejecute en su espacio de direcciones también definan el mismo método de categoría con el mismo nombre con un efecto secundario ligeramente diferente ....

OK. Ahora que ha sido advertido, ignore la " no haga esta parte " ;. Pero ejerza extrema moderación.

Resiste subclasificando el mundo. En Cocoa, mucho se hace a través de la delegación y el uso del tiempo de ejecución subyacente que en otros marcos se realiza a través de subclases.

Por ejemplo, en Java usas mucho las instancias anónimas de * Listener y en .NET usas mucho las subclases de EventArgs . En Cocoa, tampoco haces & # 8212; en su lugar se utiliza la acción de destino.

Propiedades declaradas

Normalmente, debe usar la característica Propiedades declaradas de Objective-C 2.0 para todas sus propiedades. Si no son públicos, agréguelos en una extensión de clase. El uso de propiedades declaradas hace que la semántica de administración de memoria sea clara de inmediato, y le facilita la verificación del método dealloc. Si agrupa las declaraciones de propiedad, puede escanearlas rápidamente y compararlas con la implementación de su método dealloc.

Debes pensar mucho antes de no marcar las propiedades como 'no atómicas'. Como La Guía del lenguaje de programación de Objective C notas, las propiedades son Atómico por defecto, e incurrir en gastos generales considerables. Además, simplemente hacer que todas sus propiedades sean atómicas no hace que su aplicación sea segura para subprocesos. También tenga en cuenta, por supuesto, que si no especifica "no atómico" e implementa sus propios métodos de acceso (en lugar de sintetizarlos), debe implementarlos de forma atómica.

Piensa en valores nulos

Como notas de esta pregunta , mensajes a nil Son válidos en Objective-C. Si bien esto es con frecuencia una ventaja, lo que lleva a un código más limpio y más natural, la característica puede llevar ocasionalmente a errores peculiares y difíciles de rastrear si obtiene un valor de nil cuando no estaba No lo estoy esperando.

Usa NSAssert y amigos. Uso nil como objeto válido todo el tiempo ... especialmente el envío de mensajes a nil es perfectamente válido en Obj-C. Sin embargo, si realmente quiero asegurarme del estado de una variable, utilizo NSAssert y NSParameterAssert, que ayuda a localizar problemas fácilmente.

Uno simple pero a menudo olvidado. Según especificación:

  

En general, los métodos en diferentes   Clases que tienen el mismo selector.   (el mismo nombre) también debe compartir el   mismos tipos de retorno y argumento. Esta   La restricción es impuesta por el compilador.   para permitir el enlace dinámico.

en cuyo caso, se considerará que todos los mismos selectores con nombre, incluso si se encuentran en clases diferentes , tienen tipos de devolución / argumento idénticos. Aquí hay un ejemplo simple.

@interface FooInt:NSObject{}
-(int) print;
@end

@implementation FooInt
-(int) print{
    return 5;
}
@end

@interface FooFloat:NSObject{}
-(float) print;
@end

@implementation FooFloat
-(float) print{
    return 3.3;
}
@end

int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    
    id f1=[[FooFloat alloc]init];
    //prints 0, runtime considers [f1 print] to return int, as f1's type is "id" and FooInt precedes FooBar
    NSLog(@"%f",[f1 print]);

    FooFloat* f2=[[FooFloat alloc]init];
    //prints 3.3 expectedly as the static type is FooFloat
    NSLog(@"%f",[f2 print]);

    [f1 release];
    [f2 release]
    [pool drain];

    return 0;
}   

Si está utilizando Leopard (Mac OS X 10.5) o posterior, puede usar la aplicación Instruments para encontrar y rastrear pérdidas de memoria. Después de construir su programa en Xcode, seleccione Ejecutar > Comience con la herramienta de rendimiento > Fugas.

Incluso si su aplicación no muestra ninguna fuga, es posible que mantenga los objetos demasiado tiempo. En Instrumentos, puede utilizar el instrumento ObjectAlloc para esto. Seleccione el instrumento ObjectAlloc en su documento de Instrumentos y muestre los detalles del instrumento (si aún no se muestra) seleccionando Ver > Detalle (debe tener una marca de verificación al lado). En " Vida útil de asignación " en el detalle de ObjectAlloc, asegúrese de elegir el botón de opción junto a " Created & amp; Todavía vivo " ;.

Ahora, cuando deje de grabar su aplicación, seleccionando la herramienta ObjectAlloc le mostrará cuántas referencias hay de cada objeto que aún vive en su aplicación en " # Net " columna. Asegúrese de no solo ver sus propias clases, sino también las clases de los objetos de nivel superior de sus archivos NIB. Por ejemplo, si no tiene ventanas en la pantalla y ve referencias a una ventana de NS que aún vive, es posible que no la haya publicado en su código.

Limpiar en dealloc.

Esta es una de las cosas más fáciles de olvidar - esp. cuando la codificación a 150 mph. Siempre, siempre, siempre limpie sus atributos / variables miembro en dealloc.

Me gusta usar los atributos de Objc 2, con la nueva notación de puntos, por lo que la limpieza es indolora. A menudo tan simple como:

- (void)dealloc
{
    self.someAttribute = NULL;
    [super dealloc];
}

Esto se encargará del lanzamiento y establecerá el atributo en NULL (que considero programación defensiva; en caso de que otro método más abajo acceda a la variable miembro en dealloc nuevamente, es raro, pero podría suceder. ).

Con GC activado en 10.5, esto ya no es necesario, pero es posible que aún deba limpiar otros recursos que cree, puede hacerlo en el método de finalización.

Todos estos comentarios son excelentes, pero estoy realmente sorprendido de que nadie haya mencionado Google Guía de estilo de Objective-C que se publicó hace un tiempo. Creo que han hecho un trabajo muy completo.

También, tema semi-relacionado (¡con espacio para más respuestas!):

¿Qué son esos pequeños consejos de Xcode & amp; ¿Trucos que desearías conocer hace 2 años? .

No olvide que NSWindowController y NSViewController liberarán los objetos de nivel superior de los archivos NIB que gobiernan.

Si carga manualmente un archivo NIB, es responsable de liberar los objetos de nivel superior de ese NIB cuando haya terminado con ellos.

Uno bastante obvio para que lo use un principiante: utilice la función de sangría automática de Xcode para su código. Incluso si está copiando / pegando desde otra fuente, una vez que haya pegado el código, puede seleccionar todo el bloque de código, hacer clic derecho sobre él y luego elegir la opción para volver a sangrar todo dentro de ese bloque.

Xcode en realidad analizará esa sección y la sangrará en función de corchetes, bucles, etc. Es mucho más eficaz que pulsar la barra espaciadora o la tecla de tabulación para cada línea.

Sé que pasé por alto esto cuando ingresé por primera vez a la programación de Cocoa.

Asegúrese de que comprende las responsabilidades de administración de memoria con respecto a los archivos NIB. Usted es responsable de liberar los objetos de nivel superior en cualquier archivo NIB que cargue. Lea

Activa todas las advertencias de GCC, luego desactiva las que son causadas regularmente por los encabezados de Apple para reducir el ruido.

También ejecuta el análisis estático de Clang con frecuencia; puede habilitarlo para todas las compilaciones a través del " Run Static Analyzer " configuración de construcción.

Escriba pruebas unitarias y ejecútelas con cada compilación.

Variables y propiedades

1 / Manteniendo sus encabezados limpios, ocultando la implementación
No incluya variables de instancia en su encabezado. Variables privadas puestas en la continuación de la clase como propiedades. Las variables públicas se declaran como propiedades públicas en su encabezado. Si solo se debe leer, declararlo como solo lectura y sobrescribirlo como readwrite en la continuación de la clase. Básicamente no estoy usando variables, solo propiedades.

2 / Dé a sus propiedades un nombre de variable no predeterminado, ejemplo:


@synthesize property = property_;

Motivo 1: detectará los errores causados ??por el olvido de " self. " Al asignar la propiedad. Razón 2: a partir de mis experimentos, Leak Analyzer in Instruments tiene problemas para detectar propiedades con fugas con nombre predeterminado.

3 / Nunca use retener o liberar directamente en las propiedades (o solo en situaciones muy excepcionales). En tu dealloc solo asigna un nulo. Las propiedades de retención están destinadas a manejar la retención / liberación por sí mismas. Nunca se sabe si un colocador no está, por ejemplo, agregando o eliminando observadores. Debe usar la variable directamente solo dentro de su establecedor y captador.

Views

1 / Coloque cada definición de vista en un xib, si puede (la excepción suele ser la configuración dinámica de contenido y capa). Ahorra tiempo (es más fácil que escribir código), es fácil de cambiar y mantiene su código limpio.

2 / No intente optimizar las vistas disminuyendo el número de vistas. No cree UIImageView en su código en lugar de xib simplemente porque desea agregar subvistas en él. Utilice UIImageView como fondo en su lugar. El marco de vista puede manejar cientos de vistas sin problemas.

3 / IBOutlets no tienen que ser retenidos (o fuertes) siempre. Tenga en cuenta que la mayoría de sus IBOutlets son parte de su jerarquía de vistas y, por lo tanto, se mantienen de forma implícita.

4 / Liberar todos los IBOutlets en viewDidUnload

5 / Llame a viewDidUnload desde su método de dealloc. No se llama implícitamente.

Memoria

1 / Autorelease objetos cuando los creas. Muchos errores son causados ??por mover su llamada de lanzamiento a una rama if-else o después de una declaración de retorno. La liberación en lugar del autorelease se debe usar solo en situaciones excepcionales, por ejemplo, cuando está esperando un runloop y no desea que su objeto se lance automáticamente antes.

2 / Incluso si está utilizando el conteo de referencias de Authomatic, debe comprender perfectamente cómo funcionan los métodos de retener y liberar. El uso de la retención manual no es más complicado que el ARC, en ambos casos hay que tener en cuenta las fugas y los ciclos de retención. Considere la posibilidad de utilizar la liberación / liberación manualmente en grandes proyectos o jerarquías de objetos complicados.

Comentarios

1 / Haz que tu código sea autodocumentado. Cada nombre de variable y nombre de método debe indicar lo que está haciendo. Si el código está escrito correctamente (necesita mucha práctica en esto), no necesitará ningún comentario de código (no es lo mismo que comentarios de documentación). Los algoritmos pueden ser complicados, pero el código debería ser siempre simple.

2 / A veces, necesitarás un comentario. Por lo general, para describir un comportamiento de código no aparente o hackear. Si siente que tiene que escribir un comentario, primero intente volver a escribir el código para que sea más sencillo y sin la necesidad de comentarios.

Indentación

1 / No aumentar demasiado la sangría. La mayor parte de su código de método debe estar sangrado en el nivel de método. Los bloques anidados (si, para etc.) disminuyen la legibilidad. Si tiene tres bloques anidados, debe intentar colocar los bloques internos en un método separado. Nunca se deben usar cuatro o más bloques anidados. Si la mayoría de su código de método está dentro de un if, niegue la condición if, por ejemplo:


if (self) {
   //... long initialization code ...
}

return self;


if (!self) {
   return nil;
}

//... long initialization code ...

return self;

Comprenda el código C, principalmente las estructuras C

Tenga en cuenta que Obj-C es solo una capa OOP ligera sobre el lenguaje C. Debe comprender cómo funcionan las estructuras de código básicas en C (enumeraciones, estructuras, matrices, punteros, etc.). Ejemplo:


view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);

es lo mismo que:


CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;

Y muchos más

Mantenga su propio documento de estándares de codificación y actualícelo con frecuencia. Trate de aprender de sus errores. Comprenda por qué se creó un error e intente evitarlo utilizando estándares de codificación.

Nuestros estándares de codificación tienen actualmente alrededor de 20 páginas, una combinación de estándares de codificación de Java, estándares de Google Obj-C / C ++ y nuestros propios complementos. Documente su código, use sangría estándar estándar, espacios en blanco y líneas en blanco en los lugares correctos, etc.

Sea más funcional .

Objective-C es un lenguaje orientado a objetos, pero consciente del estilo funcional de Cocoa Framework, y en muchos casos está diseñado con un estilo funcional.

  1. Hay separación de mutabilidad. Utilice las clases inmutables como objeto primario y objeto mutable como secundario. Por ejemplo, use NSArray principalmente, y use NSMutableArray solo cuando lo necesite.

  2. Hay funciones puras. No tantos, comprar muchas de las API de framework están diseñadas como función pura. Mira funciones como CGRectMake () o CGAffineTransformMake () . Obviamente la forma del puntero se ve más eficiente. Sin embargo, los argumentos indirectos con punteros no pueden ofrecer efectos secundarios libres. Diseñar estructuras puramente tanto como sea posible. Separar objetos de estado par. Utilice -copy en lugar de -retain cuando pase un valor a otro objeto. Porque el estado compartido puede influir en la mutación para valorar en otro objeto en silencio. Así que no puede ser libre de efectos secundarios. Si tiene un valor externo desde el objeto, cópielo. Por lo tanto, también es importante diseñar el estado compartido lo más mínimo posible.

Sin embargo, no tengas miedo de usar funciones impuras también.

  1. Hay una evaluación perezosa. Vea algo como la propiedad - [UIViewController view] . La vista no se creará cuando se crea el objeto. Se creará cuando la persona que llama lea ver la propiedad por primera vez. UIImage no se cargará hasta que se esté dibujando. Hay muchas implementaciones como este diseño. Este tipo de diseños son muy útiles para la administración de recursos, pero si no conoce el concepto de evaluación perezosa, no es fácil entender el comportamiento de los mismos.

  2. Hay un cierre. Use bloques de C tanto como sea posible. Esto simplificará tu vida enormemente. Pero lea una vez más sobre la administración de bloque de memoria antes de usarla.

  3. Hay GC semiautomático. NSAutoreleasePool. Utilice -autorelease primario. Utilice el manual -retain / -release cuando realmente lo necesite. (por ejemplo: optimización de memoria, eliminación explícita de recursos)

scroll top