2012-05-06 16 views
10

Vengo de un fondo de Java y estoy aprendiendo Objective C. Estoy intentando crear una clase que tenga una matriz de cadenas y una función miembro para modificar la matriz. Mi código se veía así:¿Cómo inicializar un NSMutableArray en Objective C?

@implementation TAWChapter 

@synthesize mSubject; 

@synthesize mItems; 

- (id) init{ 
    self.mItems = [[NSMutableArray alloc] init]; 
    return self; 
} 

- (void) setSubject:(NSString *)subject{ 
    self.mSubject = subject; 
} 

- (void) addItem:(NSString *)item{ 
    [self.mItems addObject:@"asdf"]; 
} 

@end 

los cuales no funcionaba. Obtuve un "[__NSArrayI addObject:]: unrecognized selector sent to instance " y un "NSInvalidArgumentException". Después de buscar en Internet, cambié la línea individual en el constructor a:

self.mItems = [self.mItems init]; 

Funcionó, pero ¿por qué? Desde el punto de vista de un desarrollador de Java, el primero tiene más sentido que el segundo. Y tengo otra línea, es la misma que la primera, pero está funcionando (no en un constructor). ¿Alguien me puede explicar esto por favor?

+1

Las respuestas probablemente han abordado la cuestión, pero no podemos estar seguros hasta que veamos la declaración de la propiedad 'mItems'. –

Respuesta

27
  1. Primera de todos, debe cumplir con las convenciones de codificación de Objective-C. En Objective-C, las clases no tienen constructores, tienen inicializadores. En Objective-C, inicializadores invocar el inicializador de la superclase, por lo que debe tener este aspecto:

    - init 
    { 
        self = [super init]; 
        if (!self) return nil; 
    
        // set up other stuff here 
    
        return self; 
    } 
    
  2. En segundo lugar, a menos que esté utilizando ARC, usted podría tener una pérdida de memoria. La primera línea de su inicializador le asigna un objeto que usted posee a una propiedad que también es probable que asuma la propiedad. Debe utilizar ya sea:

    // property takes care of ownership 
    self.mItems = [NSMutableArray array]; 
    

    o:

    // assign to instance variable directly with owned object 
    mItems = [[NSMutableArray alloc] init]; 
    

    de Apple a veces desalentar el uso de métodos de acceso en inicializadores, ya que puede jugar con cosas como MVA, pero el uso constante de métodos de acceso garantiza la propiedad objeto propio y gestión de memoria.

  3. Al cambiar su línea en su initialiser a:

    self.mItems = [self.mItems init]; 
    

    hace nada .Cuando se llama a su método de inicialización (que suele ser justo después de haberlo asignado), todas las variables de instancia se establecen automáticamente en cero. Así que lo que está haciendo es simplemente:

    self.mItems = [nil init]; 
    

    que es justo:

    self.mItems = nil; 
    

    y, no utilice init sin asignar primero una instancia, y nunca utilizar init más de una vez.

  4. Si no dejas que la superclase se inicialice sola, puede manifestarse como un problema en otras áreas. Realice una compilación & Analice y asegúrese de haber resuelto todos los problemas señalados por el analizador.

+0

Muy buena respuesta :) – MJB

+0

Gracias, gracias :-) – YannickSteph

2

Debe llamar super y asignar su resultado a self en su método init:

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     self.mItems = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 
6

Desde Objective-C es un superconjunto de C, que es básicamente c con un poco de azúcar sintaxis "OO". Antes de poder crear (¡o usar!) Un objeto, debe asignarle espacio en el montón. haces esto con [Class alloc]. El siguiente paso es la inicialización de ese espacio. alloc devuelve un puntero a ese espacio en el montón, que inicializa con init;)

Así que llama al Class *myObjc = [[Class alloc] init];.

Si usa la herencia (lo que hace desde que hereda de NSOBject), debe asegurarse de que su superclase haya inicializado todo correctamente, esa es la llamada a super. Para asegurarse de que usted no recibe un error de ejecución, la verificación de auto = nil, lo que lo hace implícitamente si (auto)

self.mItems = [self.mItems init]; // doesn't do anything, since you call the getter for mItems with self.mItems and try to init. then you try to set mItmes to itself. 

uso este código:

@implementation TAWChapter 

@synthesize mSubject, mItems; 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     mItems = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (void) setSubject:(NSString *)subject{ 
    mSubject = subject; 
} 

- (void) addItem:(NSString *)item{ 
    [mItems addObject:item]; 
} 

@end 
0

La otra forma podría ser la creación de NSMutableArray NSArray:

NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray]; 
Cuestiones relacionadas