2010-03-21 8 views
7

Estoy usando estructuras C en objc y he creado una función que ensambla la estructura como la de Cocoa API. Lo que pasa es que esta estructura no es como NSRect o NSPoint. Esta estructura contiene objetos objc, así que estoy viendo una posible pérdida de memoria aquí. ¿Debo proporcionar una función para "liberar" la estructura?¿Cómo usar las estructuras C que contiene objetos ObjC?

No estoy creando una clase ISKNewsCategory porque no habrá ningún comportamiento pero ¿Crees que este es un buen enfoque o debo definir la clase incluso si no hay comportamiento?

typedef struct ISK_NewsCategory { 
    NSString *name; 
    NSString *code 
} ISKNewsCategory; 

NS_INLINE ISKNewsCategory ISKMakeNewsCategory(NSString *name, NSString *code) { 
    ISKNewsCategory category; 
    category.name = [name retain]; 
    category.code = [code retain]; 
    return category; 
} 

Respuesta

8

En general, sería mucho mejor crear una clase de contenedor simple. De esta forma, toda la administración de la memoria es fácil y puede usar el objeto en las clases de contenedor estándar de Cocoa sin perder el tiempo envolviendo la estructura en un NSValue o lo que sea.

El único momento en que podría ser aceptable utilizar una estructura de esta manera es si tiene un código extremadamente crítico para el rendimiento donde la sobrecarga del objeto podría convertirse en un problema.

@interface ISKNewsCategory : NSObject 
{ 
    NSString *name; 
    NSString *code; 
} 
@property (copy) NSString *name; 
@property (copy) NSString *code; 
@end 

@implementation ISKNewsCategory 
@synthesize name,code; 
- (void)dealloc 
{ 
    self.name = nil; 
    self.code = nil; 
    [super dealloc]; 
} 
@end 
+1

Para expandir su "único tiempo": iterar estructuras es 2-4x más rápido que iterar clases. A medida que los proyectos crecen, esto se está convirtiendo en un problema real (el proyecto actual itera muchos cientos de miles de elementos con frecuencia, tiene que ejecutarse en tiempo real). – Adam

2

Cualquier cosa que conserve debe liberar. Sin embargo, no hay nada que diga que debes retenerlos. Si la estructura es "dueña" de los objetos, entonces sí, debe retenerlos, y luego debe liberarlos. Sin embargo, si los objetos se retienen en otra parte, es posible que desee considerar referencias débiles donde no conserve los objetos.

2

Odio crear clases sin comportamiento también. :/Este es un aspecto triste de Objective-C: las clases son detalladas.

Debe recordar que las estructuras en C se copian cada vez que se pasan. Por lo tanto, si sus estructuras retienen sus objetos y se los da a otra persona, automáticamente se obtendrá un recuento de referencia erróneo para los objetos que contiene.

Si planeas pasar alrededor de tus objetos, creo que deberías convertirlo en una clase completa. Si no lo haces, una estructura simple estará bien.

Por la necesidad de un "destructor", debería tener uno. Siempre debe tener uno si hay una limpieza para su estructura.

+0

En realidad, la copia no causará ninguna retención adicional, como tampoco pasar un objeto directamente, ya que solo se copia el puntero. – cobbal

+0

@cobbal: esto es lo que quise decir. Si pasa su estructura, los punteros a los objetos serán copiados, y si pretende retenerlos para cada estructura en la que viven, no puede hacer eso. – zneak

0

Espero que esta solución sea útil para usted.

typedef struct ISK_NewsCategory { 
    NSString *name; 
    NSString *code; 
} ISKNewsCategory; 

NS_INLINE ISKNewsCategory ISKMakeNewsCategory(NSString *inName, NSString *inCode) { 

    ISKNewsCategory category; 

    [category.name autorelease]; 
    category.name = [inName retain]; 

    [category.code autorelease]; 
    category.code = [inCode retain]; 

    return category; 
} 
Cuestiones relacionadas