2012-08-30 8 views
16

Soy un experimentado desarrollador de iOS y he decidido probar suerte en algún desarrollo de AppKit. Hay un par de ajustes que estoy haciendo API-wise, pero de lo contrario estoy descubriendo que el desarrollo de OS X es, digamos, "familiar".Al desarrollar en AppKit, ¿por qué IB crea una propiedad que se asigna, en lugar de retener?

He estado construyendo mi AppKit interfaces de usuario en el Interface Builder y se dio cuenta de que cuando se utiliza el editor WYSIWYG para crear propiedades en mis archivos de código, Apple está creando la siguiente:

@property (assign) IBOutlet NSTableView *tableView; 

Me parece muy curioso porque la manera de hacer las cosas por defecto en iOS me habría llevado a hacer esto:

@property (nonatomic, retain) IBOutlet NSTableView *tableView; 

que darse cuenta de que en el desarrollo de Mac no tengo las mismas restricciones de memoria que hago en el móvil, en una vista podría conseguir descargado y puede haber una necesidad de referencia fuerte ences a elementos de UI.

En el caso de AppKit, puedo asumir que mis elementos de la interfaz de usuario siempre estarán allí a menos que juegue con la jerarquía de vistas y la elimine de su vista principal. Parecería prudente tener una referencia fuerte en todo momento con el fin de evitar el acceso involuntario a punteros colgantes.

¿Por qué Apple está creando una referencia débil aquí, en lugar de una fuerte?

¿Me estoy preparando para alguna consecuencia involuntaria mediante el uso de referencias fuertes (pero que se publica correctamente en dealloc)? ¿Hay algún patrón aquí que me falta?

Respuesta

16

Como propietario del archivo, debe ser propietario de todos los objetos de nivel superior del plumín. Por lo general, no es necesario poseer ningún objeto dentro de esos objetos, porque un objeto principal será el propietario de sus objetos secundarios; por ejemplo, una ventana poseerá sus vistas.

AppKit's nib loader implicitly retains all top-level objects on behalf of the File's Owner. (Esto tenía sentido antes @property, accessors sintetizados, y existió ARC). Así, incluso si las propiedades relevantes son weak o unsafe_unretained (siendo este último un sinónimo de assign), el propietario de hecho poseer el objetos de nivel superior. Y si va por el otro lado y hace esas propiedades strong (a.k.a. retain), entonces el FO tiene dos propiedade de cada objeto: la propiedad implícita y el strong -propiedad de la propiedad.

Suponiendo que está utilizando el recuento manual de referencias, puede liberar la propiedad implícita en awakeFromNib, pero eso acaba de hacer el trabajo. Siempre que no vaya a reemplazar ninguno de esos objetos después de que se cargue el plumín (por ejemplo, intercambie una vista de tabla para otra vista de tabla), una propiedad unsafe_unretained funcionará perfectamente sin una retención innecesaria ni ningún trabajo hecho.

unsafe_unretained recibe ese nombre (y ese nombre es preferido sobre assign para las propiedades del objeto) por un motivo. Volviendo al ejemplo de window-and-its-views, supongamos que posee una ventana y conoce una de sus vistas. La supervista de la vista es probablemente su único propietario, por lo tanto, cuando cierra la ventana (o el usuario la cierra), la vista se liberará y, por lo tanto, se desasignará. Si su propiedad para la vista es unsafe_unretained/assign, aún sabe acerca de este objeto ahora muerto, e intentar enviar un mensaje a la vista puede causar un bloqueo o una excepción.

Debería cambiar a ARC y declarar la propiedad como weak. De esta forma, no se crea una propiedad redundante, y la propiedad se establecerá automáticamente en nil cuando la vista muera, lo que evitará que se produzca un bloqueo por liberación excesiva.

(Si usted no es el propietario del archivo, nada de eso se aplica a usted y probablemente debería declarar sus propiedades como mejor le parezca. O bien weak o strong pueden ser una buena opción, dependiendo de cómo vea su jerarquía de propiedad y qué tipo de objeto está haciendo referencia.)

En iOS, los autores de UIKit eliminaron la retención implícita ahora problemática. Se espera que escriba sus propias propiedades; Si quiere poseer un objeto de una punta o guión gráfico, escriba una propiedad strong, y si solo quiere saber al respecto, escriba una weak o unsafe_unretained, exactamente como era de esperar.

TL; DR:Hysterical reasons.

+1

temía que iba a ser la respuesta, pero muy bien explicado, no obstante. –

+0

Entonces, ¿todavía necesitaríamos un '[tableView release]' en 'dealloc'? Si es así, ¿cuándo se llama a esa publicación cuando se usa ARC? – MrMage

+0

@MrMage: Normalmente no sería propietario de una vista de tabla, ya que normalmente la colocaría en una ventana o vista de contenedor en el plumín, no la tendría en el nivel superior del plumín. Tendría la ventana o la vista de nivel superior, y simplemente conocer la vista de tabla. Cualquier cosa que poseas, debes liberarla. –

Cuestiones relacionadas