objective-c memory-management appkit

objective c - Al desarrollar en AppKit, ¿por qué IB crea una propiedad que se asigna, en lugar de conservar?



objective-c memory-management (1)

Soy un desarrollador de iOS con experiencia y he decidido probar suerte en algún desarrollo de AppKit. Hay un par de ajustes que estoy haciendo a nivel de API, pero por lo demás estoy encontrando que el desarrollo de OS X es, digamos, "familiar".

He estado construyendo mis UI de AppKit en Interface Builder y noté que cuando uso el editor WYSIWYG para crear propiedades en mis archivos de código, Apple está creando lo siguiente:

@property (assign) IBOutlet NSTableView *tableView;

Encuentro esto muy curioso porque la forma predeterminada de hacer las cosas en iOS me hubiera llevado a hacer esto:

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

Me doy cuenta de que en el desarrollo de Mac no tengo las mismas limitaciones de memoria que tengo en los dispositivos móviles, donde se puede descargar una vista y es posible que se necesiten referencias sólidas a los elementos de la interfaz de usuario.

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

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

¿Me estoy preparando para alguna consecuencia no intencional mediante el uso de referencias sólidas (pero al lanzar adecuadamente en dealloc )? ¿Hay algún patrón aquí que me esté perdiendo?


Como propietario del archivo, debe poseer todos y cada uno de los objetos de nivel superior en la punta. Por lo general, no es necesario que posea ningún objeto dentro de esos objetos, porque un objeto primario será propietario de sus objetos secundarios; Por ejemplo, una ventana será propietaria de sus vistas.

El cargador de plumillas de AppKit retiene implícitamente todos los objetos de nivel superior en nombre del propietario del archivo. (Esto tenía sentido antes de que @property , los @property sintetizados y ARC). Por lo tanto, incluso si las propiedades relevantes son weak o unsafe_unretained (este último es un sinónimo de assign ), el propietario será el propietario de los objetos de nivel superior. Y si va por el otro lado y hace que esas propiedades sean strong (también conocidas como retain ), entonces la FO tiene dos propiedades de cada objeto: la propiedad implícita y la propiedad de la propiedad strong .

Suponiendo que está utilizando el recuento manual de referencias, puede liberar la propiedad implícita en awakeFromNib , pero eso solo ha funcionado. Siempre y cuando no vaya a reemplazar ninguno de esos objetos después de que se cargue la punta (por ejemplo, cambie una vista de tabla por otra vista de tabla), una propiedad unsafe_unretained funcionará bien sin una retención superflua o cualquier trabajo realizado.

unsafe_unretained se nombra con ese nombre (y ese nombre se prefiere sobre assign para las propiedades del objeto), sin embargo, por una razón. Si devuelve el ejemplo de la ventana y sus vistas, suponga que posee una ventana y conoce una de sus vistas. La vista de supervisión de la vista es probablemente su único propietario, por lo tanto, cuando cierre la ventana (o el usuario la cierre), la vista se liberará y, en consecuencia, se desasignará. Si su propiedad para la vista es unsafe_unretained / assign , aún sabe acerca de este objeto ahora muerto, y tratar de enviar un mensaje a la vista puede provocar un bloqueo o una excepción.

Debe cambiar a ARC y declarar la propiedad como weak . De esa manera, no se creará propiedad redundante, y la propiedad se establecerá automáticamente en nil cuando la vista muera, lo que evitará que se produzca un bloqueo por exceso de versión.

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

En iOS, los autores de UIKit sacaron la retenida implícita ahora problemática. Se espera que escribas tus propias propiedades; si quiere ser dueño de un objeto de un plumín o guión gráfico, escribe una propiedad strong , y si solo quiere saberlo, escriba uno weak o unsafe_unretained , exactamente como lo esperaría.

TL; DR: razones histéricas.