Respuestas:
Hay algunas cosas que he comenzado a hacer que no creo que sean estándar:
1) Con el advenimiento de las propiedades, ya no uso "_" para prefijar las variables de clase "privadas". Después de todo, si otras clases pueden acceder a una variable, ¿no debería haber una propiedad para ella? Siempre me disgustó el prefijo "_" para hacer que el código sea más feo, y ahora puedo omitirlo.
2) Hablando de cosas privadas, prefiero colocar definiciones de métodos privados dentro del archivo .m en una extensión de clase como esta:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
¿Por qué desordenar el archivo .h con cosas que a los extraños no les debería importar? Empty () funciona para categorías privadas en el archivo .m y emite advertencias de compilación si no implementa los métodos declarados.
3) Me puse a poner 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 en las que quiere pensar en una clase? Eso es especialmente cierto en un entorno como el iPhone.
3.5) En las celdas de la tabla, haga que cada elemento (incluida la celda misma) sea opaco para el rendimiento. Eso significa establecer el color de fondo apropiado en todo.
3.6) Al usar una NSURLConnection, como regla, es posible que desee implementar el método delegado:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
Creo que la mayoría de las llamadas web son muy singulares y es más la excepción que la regla que querrá que las respuestas se almacenen en caché, especialmente para las llamadas de servicio web. La implementación del método como se muestra deshabilita el almacenamiento en caché de las respuestas.
También son interesantes 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, pensé (tenga en cuenta que ahora se han editado algunos bits del original para incluir los detalles ofrecidos en las respuestas):
4) Solo use doble precisión si es necesario, como cuando trabaja con CoreLocation. Asegúrese de terminar sus constantes en 'f' para que gcc las almacene como flotantes.
float val = someFloat * 2.2f;
Esto es principalmente importante cuando en someFloat
realidad puede ser un doble, no necesita las matemáticas de modo mixto, ya que está 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 llevar 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 operan a la misma velocidad, pero puede tener más componentes de precisión individuales en los registros que los dobles, por lo que para muchos cálculos, la precisión simple terminará siendo 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. Probablemente el 99% de ustedes no necesiten preocuparse por esto y el código es mucho menos hinchado y más eficiente en memoria cuando se configura como no atómico.
6) SQLite puede ser una forma muy, muy rápida de almacenar en caché 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 de disco. Evite muchas escrituras pequeñas enviando BEGIN;
y COMMIT;
entre bloques grandes. Usamos un temporizador de 2 segundos, por ejemplo, que se restablece en cada envío nuevo. Cuando caduca, enviamos COMMIT; , lo que hace que todas sus escrituras vayan en una gran parte. SQLite almacena los datos de las transacciones en el disco y al hacer este ajuste de inicio / fin 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 ajustar todo lo que modifique la base de datos para las cadenas de consulta en @synchronize() {}
bloques. Para consultas cortas, simplemente deje las cosas en el hilo principal para mayor comodidad.
Aquí encontrará más sugerencias de optimización de SQLite, aunque el documento parece desactualizado, muchos de los puntos probablemente todavía sean buenos;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
Cuando los métodos o funciones toman un argumento de cadena de formato, debe asegurarse de tener control sobre el contenido de la cadena de formato.
Por ejemplo, al registrar cadenas, es tentador pasar la variable de cadena como único argumento para 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 conducir a resultados erróneos, bloqueos y problemas de seguridad. En su lugar, debe sustituir la variable de cadena en una cadena de formato:
NSLog(@"%@", aString);
Use convenciones y terminología estándar de nomenclatura y formato de Cocoa en lugar de lo que sea que esté acostumbrado de otro entorno. No son muchos desarrolladores de cacao por ahí, y cuando otro de ellos comienza a trabajar con su código, que será mucho más accesible si se ve y se siente similar a otro código de cacao.
Ejemplos de qué hacer y qué no hacer:
id m_something;
en la interfaz de un objeto ni lo llame variable o campo miembro ; use something
o _something
por su nombre y llámelo variable de instancia .-getSomething
; el nombre correcto de Cocoa es justo -something
.-something:
; debería ser-setSomething:
-[NSObject performSelector:withObject:]
, no NSObject::performSelector
.Hagas lo que hagas, no uses la notación húngara estilo Win16 / Win32. Incluso Microsoft renunció a eso con el cambio a la plataforma .NET.
Históricamente, la gestión de la memoria de los puntos de venta ha sido deficiente. La mejor práctica actual es declarar salidas como propiedades:
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
El uso de propiedades aclara la semántica de administración de memoria; También proporciona un patrón consistente si utiliza la síntesis de variables de instancia.
NOTA: En Xcode 4, esto ahora está integrado en el IDE.
Utiliza el Analizador estático de Clang para, como era de esperar, analizar su código C y Objective-C (todavía no C ++) en Mac OS X 10.5. Es trivial instalar y usar:
cd
al directorio de su proyecto.scan-build -k -V xcodebuild
.(Existen algunas restricciones adicionales, etc., en particular, debe analizar un proyecto en su configuración "Depurar"; consulte http://clang.llvm.org/StaticAnalysisUsage.html para obtener más detalles, pero eso es más o menos a lo que se reduce.)
Luego, el analizador produce un conjunto de páginas web para usted que muestra la administración probable de la memoria y otros problemas básicos que el compilador no puede detectar.
Este es uno sutil pero práctico. Si te estás pasando como delegado a otro objeto, reinicia el delegado de ese objeto antes que tú dealloc
.
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
Al hacer esto, se asegura de que no se envíen más métodos de delegado. Cuando esté a punto de dealloc
desaparecer en el éter, debe asegurarse de que nada pueda enviarle más mensajes por accidente. Recuerde self.someObject podría ser retenido por otro objeto (podría ser un singleton o en el grupo de liberación automática o lo que sea) y hasta que le diga "¡deja de enviarme mensajes!", Piensa que es un objeto a punto de ser desalojado Es un juego justo.
Entrar en este hábito lo salvará de muchos accidentes extraños que son difíciles de depurar.
El mismo principio se aplica a la Observación del valor clave y a las Notificaciones NS también.
Editar:
Aún más defensivo, cambio:
self.someObject.delegate = NULL;
dentro:
if (self.someObject.delegate == self)
self.someObject.delegate = NULL;
Memory Management Programming Guide for Cocoa
: Additional cases of weak references in Cocoa include, but are not restricted to, table data sources, outline view items, notification observers, and miscellaneous targets and delegates. In most cases, the weak-referenced object is aware of the other object’s weak reference to it, as is the case for circular references, and is responsible for notifying the other object when it deallocates.
nil == NULL
. Son exactamente iguales excepto que nil
es un id
y NULL
es un void *
. Tu afirmación no es cierta.
@kendell
En vez de:
@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end
Utilizar:
@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 le permiten declarar API adicionales requeridas para una clase en ubicaciones que no estén dentro del bloque de clase primaria @interface"
Entonces son parte de la clase real, y NO una categoría (privada) además de la clase. Sutil pero importante diferencia.
()
lugar de (Private)
(o algún otro nombre de categoría): puede volver a declarar propiedades como readwrite mientras que para el público solo son de lectura. :)
Dado que normalmente (1) no tiene control directo sobre su vida útil, los objetos liberados automáticamente pueden persistir durante un tiempo relativamente largo y aumentar innecesariamente la huella de memoria de su aplicación. Mientras que en el escritorio esto puede tener pocas consecuencias, 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 una mejor práctica evitar el uso de métodos que conduzcan a objetos que se liberen automáticamente y, en su lugar, se le recomienda usar el patrón alloc / init.
Por lo tanto, en lugar de:
aVariable = [AClass convenienceMethod];
donde sea posible, en su lugar debería usar:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
Cuando escribe sus propios métodos que devuelven un objeto recién creado, puede aprovechar la convención de nomenclatura de Cocoa para indicarle al receptor que debe liberarse anteponiendo 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;
}
Como el nombre del método comienza con "nuevo", los consumidores de su API saben que son responsables de liberar el objeto recibido (ver, por ejemplo, el newObject
método NSObjectController ).
(1) Puede tomar el control utilizando sus propios grupos locales de liberación automática. Para obtener más información al respecto, consulte Grupos de lanzamiento automático .
NSAutoreleasePool
. Pero solo después de confirmar que esto realmente es un problema. Optimización prematura y todo eso ...
Algunos de estos ya se han mencionado, pero esto es lo que puedo pensar de la parte superior de mi cabeza:
#pragma mark [section]
. Por lo general, me agrupo por mis propios métodos, las anulaciones de cada subclase y cualquier información o protocolos formales. Esto hace que sea mucho más fácil saltar a exactamente lo que estoy buscando. Sobre el mismo tema, agrupe métodos similares (como los métodos delegados de una vista de tabla), no los pegue en ningún lado.#define
sea necesario o almacenar en caché una matriz en lugar de ordenarla cada vez que se necesitan los datos. Hay muchas cosas que podría decir sobre esto, pero la conclusión es que no escriba código hasta que lo necesite, o el perfilador le diga que lo haga. Hace que las cosas sean mucho más fáciles de mantener a largo plazo.NSLog( @"stub" )
dentro, o como quiera hacer un seguimiento de las cosas.Finish what you start
, también puede usar // TODO:
para marcar el código para completar que se mostrará en el menú desplegable.
Escribir pruebas unitarias. Puede probar muchas cosas en Cocoa que podrían ser más difíciles en otros marcos. Por ejemplo, con el código de la interfaz de usuario, generalmente puede verificar que las cosas estén conectadas como deberían y confiar en que funcionarán cuando se usen. Y puede configurar métodos de delegado de estado e invocar fácilmente para probarlos.
Tampoco tiene visibilidad de método público versus protegido versus privado que se interpone en el camino de escribir pruebas para sus internos.
Regla de oro: ¡Si tú, alloc
entonces tú release
!
ACTUALIZACIÓN: a menos que esté utilizando ARC
copy
, mutableCopy
, new
o retain
.
No escriba Objective-C como si fuera Java / C # / C ++ / etc.
Una vez vi a un equipo acostumbrado a escribir aplicaciones web Java EE que intentaban escribir una aplicación de escritorio Cocoa. Como si fuera una aplicación web Java EE. Había un montón de AbstractFooFactory y FooFactory e IFoo y Foo volando cuando todo lo que realmente necesitaban era una clase Foo y posiblemente un protocolo Fooable.
Parte de garantizar que no hagas esto es comprender realmente las diferencias en el idioma. Por ejemplo, no necesita la fábrica abstracta y las clases de fábrica anteriores porque los métodos de clase Objective-C se envían tan dinámicamente como los métodos de instancia, y pueden anularse en subclases.
Asegúrese de marcar la página Debugging Magic . Esta debería ser tu primera parada cuando te golpees la cabeza contra la pared mientras intentas encontrar la fuente de un error de cacao.
Por ejemplo, le dirá cómo encontrar el método en el que asignó la memoria por primera vez que luego causa bloqueos (como durante la finalización de la aplicación).
Trate de evitar lo que ahora he decidido llamar adicción a la categoría de Newbie. Cuando los recién llegados a Objective-C descubren categorías, a menudo se vuelven locos, agregando pequeñas categorías útiles a todas las clases existentes ( "¿Qué? ¡Puedo agregar un método para convertir un número a números romanos en NSNumber rock on!" ).
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ía distribuidos sobre dos docenas de clases básicas.
La mayoría de las veces, cuando realmente cree que necesita un método de categoría para ayudar a simplificar el código, encontrará que nunca termina reutilizando el método.
También hay otros peligros, a menos que esté espaciando los nombres de sus métodos de categoría (¿y quién además del ddribin completamente loco es?) Existe la posibilidad de que Apple, o un complemento, o algo más que se ejecute en su espacio de direcciones también definan la misma categoría método con el mismo nombre con un efecto secundario ligeramente diferente ...
OKAY. Ahora que has sido advertido, ignora el "no hagas esta parte". Pero ejerza una moderación extrema.
Resiste subclasificar el mundo. En Cocoa se hace mucho 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 la subclasificación.
Por ejemplo, en Java usa *Listener
muchas instancias de subclases anónimas y en .NET usa mucho sus EventArgs
subclases. En Cocoa, tampoco lo haces; en su lugar, se utiliza la acción objetivo.
Cuando ordena las cadenas para presentarlas al usuario, no debe usar el compare:
método simple . 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 de cadenas .
Por lo general, 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 verificar su método dealloc; si agrupa sus declaraciones de propiedad, puede escanearlas rápidamente y compararlas con la implementación de su método dealloc.
Debe pensar mucho antes de no marcar las propiedades como 'no atómicas'. Como señala The Objective C Programming Language Guide , las propiedades son atómicas por defecto y generan una sobrecarga considerable. 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 manera atómica.
Como señala esta pregunta , los 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 natural, la característica ocasionalmente puede generar errores peculiares y difíciles de rastrear si obtiene un nil
valor cuando no lo esperaba.
Use 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, uso NSAssert y NSParameterAssert, que ayuda a localizar problemas fácilmente.
Simple pero a menudo olvidado. De acuerdo a las especificaciones:
En general, los métodos en diferentes clases que tienen el mismo selector (el mismo nombre) también deben compartir los mismos tipos de retorno y argumento. El compilador impone esta restricción para permitir el enlace dinámico.
en cuyo caso todos los selectores con el mismo nombre, incluso si están en clases diferentes , se considerará que tienen tipos idénticos de retorno / argumento. 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 usa Leopard (Mac OS X 10.5) o posterior, puede usar la aplicación Instrumentos para buscar y rastrear pérdidas de memoria. Después de compilar su programa en Xcode, seleccione Ejecutar> Comenzar con la herramienta de rendimiento> Fugas.
Incluso si su aplicación no muestra ninguna fuga, es posible que tenga objetos alrededor demasiado tiempo. En Instrumentos, puede usar el instrumento ObjectAlloc para esto. Seleccione el instrumento ObjectAlloc en su documento 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 "Duración de la asignación" en los detalles de ObjectAlloc, asegúrese de elegir el botón de opción junto a "Creado y aún vivo".
Ahora, cuando deje de grabar su aplicación, al seleccionar la herramienta ObjectAlloc le mostrará cuántas referencias hay para cada objeto vivo en su aplicación en la columna "# Net". Asegúrese de no solo mirar 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 NSWindow que aún está viva, 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, especialmente. cuando codifica a 150 mph. Siempre, siempre, siempre limpia tus atributos / variables miembro en dealloc.
Me gusta usar los atributos de Objc 2, con la nueva notación de puntos, por lo que esto hace que la limpieza sea indolora. A menudo tan simple como:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
Esto se encargará de la publicación y establecerá el atributo en NULL (lo que considero programación defensiva, en caso de que otro método más abajo en dealloc acceda nuevamente a la variable miembro, raro pero podría suceder).
Con GC activado en 10.5, esto ya no es necesario, pero es posible que aún necesite limpiar otros recursos que cree, puede hacerlo en el método de finalización.
-init
y -dealloc
métodos aquí: mikeash.com/?page=pyblog/…
Todos estos comentarios son geniales, pero estoy realmente sorprendido de que nadie haya mencionado la Guía de estilo Objective-C de Google que se publicó hace un tiempo. Creo que han hecho un trabajo muy completo.
Además, tema semi-relacionado (¡con espacio para más respuestas!):
¿Cuáles son esos pequeños consejos y trucos de Xcode que desearías saber hace 2 años? .
Uno bastante obvio para 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 realmente analizará esa sección y aplicará sangría en función de corchetes, bucles, etc. Es mucho más eficiente que presionar la barra espaciadora o la tecla de tabulación para cada línea.
Sé que pasé por alto esto cuando me metí por primera vez en la programación de Cocoa.
Asegúrese de comprender 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 la documentación de Apple sobre el tema.
Encienda todas las advertencias de GCC, luego apague las que regularmente causan los encabezados de Apple para reducir el ruido.
También ejecute el análisis estático de Clang con frecuencia; puede habilitarlo para todas las compilaciones a través de la configuración de compilación "Ejecutar analizador estático".
Escriba pruebas unitarias y ejecútelas con cada compilación.
Variables y propiedades
1 / Mantener sus encabezados limpios, ocultando la implementación
No incluya variables de instancia en su encabezado. Variables privadas puestas en continuación de clase como propiedades. Las variables públicas se declaran como propiedades públicas en su encabezado. Si solo debe leerse, declararlo como de solo lectura y sobrescribirlo como readwrite en la continuación de clase. Básicamente no estoy usando variables en absoluto, solo propiedades.
2 / Dé a sus propiedades un nombre de variable no predeterminado, por ejemplo:
@synthesize property = property_;
Motivo 1: detectará los errores causados por olvidar "self". al asignar la propiedad. Razón 2: De mis experimentos, el Analizador de fugas en los instrumentos tiene problemas para detectar propiedades con fugas con nombre predeterminado.
3 / Nunca use retener o liberar directamente en propiedades (o solo en situaciones muy excepcionales). En su dealloc solo les asigna un cero. Las propiedades de retención están destinadas a manejar la retención / liberación por sí mismas. Nunca se sabe si un setter no está, por ejemplo, agregando o quitando observadores. Debe usar la variable directamente solo dentro de su setter y getter.
Puntos de vista
1 / Ponga cada definición de vista en un xib, si puede (la excepción suele ser el contenido dinámico y la configuración de la 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 solo porque desea agregarle subvistas. Utilice UIImageView como fondo en su lugar. El marco de vista puede manejar cientos de vistas sin problemas.
3 / IBOutlets no tiene que ser siempre retenido (o fuerte). Tenga en cuenta que la mayoría de sus IBOutlets son parte de su jerarquía de vistas y, por lo tanto, se retienen implícitamente.
4 / Libere todos los IBOutlets en viewDidUnload
5 / Llame a viewDidUnload desde su método dealloc. No se llama implícitamente.
Memoria
1 / Objetos de liberación automática cuando los crea. Muchos errores son causados al mover su llamada de liberación a una rama if-else o después de una declaración de devolución. La liberación en lugar de la liberación automática se debe usar solo en situaciones excepcionales, por ejemplo, cuando está esperando un runloop y no desea que su objeto se libere automáticamente demasiado pronto.
2 / Incluso si está utilizando el recuento de referencia automático, debe comprender perfectamente cómo funcionan los métodos de liberación retenida. El uso de retención de liberación manual no es más complicado que ARC, en ambos casos tiene que preocuparse por las fugas y los ciclos de retención. Considere la posibilidad de utilizar la liberación retenida manualmente en grandes proyectos o jerarquías de objetos complicadas.
Comentarios
1 / Haga su código 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 los comentarios de documentación). Los algoritmos pueden ser complicados, pero el código siempre debe ser simple.
2 / A veces, necesitarás un comentario. Por lo general, para describir un comportamiento o pirateo de código no aparente. Si siente que tiene que escribir un comentario, primero intente reescribir el código para que sea más simple y sin la necesidad de comentarios.
Sangría
1 / No aumente demasiado la sangría. La mayor parte del código de su método debe tener sangría en el nivel del 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 parte del código de su 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;
Comprender el código C, principalmente estructuras C
Tenga en cuenta que Obj-C es solo una capa ligera de OOP sobre 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. Intenta aprender de tus 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 unas 20 páginas, una combinación de estándares de codificación Java, estándares Google Obj-C / C ++ y nuestras propias adiciones. Documente su código, use sangría estándar estándar, espacios en blanco y líneas en blanco en los lugares correctos, etc.
Se más funcional .
Objective-C es un lenguaje orientado a objetos, pero Cocoa Framework es consciente del estilo funcional y, en muchos casos, está diseñado en un estilo funcional.
Hay separación de mutabilidad. Use clases inmutables como primarias y objetos mutables como secundarios. Por ejemplo, use NSArray principalmente y use NSMutableArray solo cuando lo necesite.
Hay funciones puras. No tantos, comprar muchas de las API de framework están diseñadas como una función pura. Mira las funciones como CGRectMake()
o CGAffineTransformMake()
. Obviamente, la forma del puntero parece más eficiente. Sin embargo, el argumento indirecto con punteros no puede ofrecer efectos secundarios libres. Diseñe estructuras lo más puramente posible. Separe incluso los objetos de estado. Use en -copy
lugar de -retain
cuando pasa un valor a otro objeto. Porque el estado compartido puede influir en la mutación del valor en otro objeto en silencio. Por lo tanto, no puede estar libre de efectos secundarios. Si tiene un valor externo desde un objeto, cópielo. Por lo tanto, también es importante diseñar un estado compartido lo más mínimo posible.
Sin embargo, no tengas miedo de usar funciones impuras también.
Hay una evaluación perezosa. Ver algo como -[UIViewController view]
propiedad. La vista no se creará cuando se cree el objeto. Se creará cuando la persona que llama lea la view
propiedad por primera vez. UIImage
no se cargará hasta que se dibuje realmente. Hay muchas implementaciones como este diseño. Este tipo de diseños son muy útiles para la gestión de recursos, pero si no conoce el concepto de evaluación perezosa, no es fácil comprender su comportamiento.
Hay cierre. Use bloques C tanto como sea posible. Esto simplificará mucho tu vida. Pero lea una vez más sobre la administración de memoria de bloque antes de usarlo.
Hay GC semiautomático. NSAutoreleasePool. Uso -autorelease
primario. Use el manual -retain/-release
secundario cuando realmente lo necesite. (ej .: optimización de memoria, eliminación explícita de recursos)
autorelease
que mantendrá la memoria por más tiempo en general, y el manual retain/release
puede reducir el consumo de memoria en el caso. Sin embargo, debe ser una guía para la optimización de casos especiales (¡incluso si se siente siempre!), No puede ser la razón para generalizar la optimización prematura como práctica . Y de hecho, su sugerencia no es opuesta a la mía. Lo mencioné como caso de necesidad realmente :)