Pregunta

Nota: Soy relativamente nuevo en Objective-C y vengo desde Java y PHP

.

Podría alguien explicarme por qué siempre tengo que asignar primero y luego inicializar una instancia?

¿No podría hacerse esto en los métodos de arranque de esta manera:

+ (MyClass*)init {
    MyClass *instance = [MyClass alloc];
    [instance setFoo:@"bla"];

    return instance;
}

+ (MyClass*)initWithString:(NSString*)text {
    MyClass *instance = [MyClass init];
    [instance setFoo:text];

    return instance;
}
...

¿Es sólo un vestigio de los viejos tiempos C o hay algo que no estoy viendo?

Sé que esto no es un problema, ya que así siempre podría llamar alloc e init, pero ya que es un poco tedioso me gustaría al menos saber por qué estoy haciendo.

Me gusto la expresividad de la lengua hasta el momento, pero esto es algo que quiero entender plenamente con el fin de pensar en la forma de Objective-C.

Gracias!

¿Fue útil?

Solución

+ nuevas termina el envío de un mensaje + alloc a la clase y un mensaje de -init a lo que venga detrás de + alloc.

La razón por la que el próximo apartado de convención de usar el nuevo mensaje + (que era una idea Smalltalk) de Stepstone es que desde el principio, se encontraron con situaciones en las que querían ser capaz de inicializar el mismo objeto más de una vez.

Otros consejos

Debido a la creación de una instancia e inicializar una instancia son dos trabajos separados.

Se envía un mensaje de alloc a la clase para obtener una instancia sin inicializar. A continuación, debe inicializar la instancia, y que a menudo tienen varias maneras de hacerlo. Por ejemplo:

myStr = [[NSString alloc] init]; //Empty string
myStr = [[NSString alloc] initWithFormat:@"%@.%@", parentKeyPath, key];
myStr = [[NSString alloc] initWithData:utf16data encoding:NSUnicodeStringEncoding error:&error];
myStr = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];

Cada uno de estos inicializa la cadena de una manera completamente diferente. Cómo inicializar la cadena depende de lo que desea inicializar desde.

Por supuesto, a nadie le gusta escribir alloc y luego init y luego autorelease cada vez, por lo que suelen tener métodos de conveniencia (por ejemplo, stringWithFormat:) que lo hacen los tres pasos para usted.

Editar: Para más información sobre este tema, incluyendo ideas esenciales de los comentaristas, ver mi blog “ reunificación ”.

Ver NSZone.

+alloc es un corte de acceso directo para +allocWithZone:, que es un mecanismo de cacao proporciona para la optimización de la asignación de memoria.

Así que tienes la opción de hacer algo como esto:

foo = [[NSString allocWithZone:MyZone] initWithString:@"Foo"];
foo2 = [foo copyWithZone:MyZone];

La idea detrás de zonas de memoria es que si usted tiene un gran número de objetos similares que con frecuencia son atribuidas y desasignan fuere más eficaz utilizar una zona de memoria independiente para esos objetos.

Para que la zonificación para ser eficaz que te gustaría tener +allocWithZone: disponible para cada subclase NSObject, por lo tanto, lo que necesita la asignación e inicialización separada. Puede crear y utilizar todos los accesos directos que desee, como +new, pero en el fondo todo lo que necesita un método -init que inicializa un objeto que ya ha sido asignado.

"La separación de las fases de asignación e inicialización de creación de la instancia ofrece muchos beneficios. Es posible utilizar cualquier variación del método de clase + alloc asignar una instancia y luego utilizar cualquier inicializador disponible con los nuevos instance.This hace posible crear sus propios métodos de inicialización sin necesidad de proporcionar implementaciones alternativas de todos los métodos de asignación. Nuevos métodos de asignación rara vez se crean debido a que los métodos existentes satisfacen casi todas las necesidades. Sin embargo, uno o más nuevos inicializadores se crean para casi todas las clases. Debido a la separación de fases de asignación e inicialización, inicializador implementaciones sólo se tienen que tratar con las variables de nuevos casos y se puede ignorar por completo la cuestiones que rodea allocation.The separación simplifica el proceso de escribir inicializadores. Además, cacao inicializadores estándar como -initWithCoder: se asignó trabajo con casos independientemente de la memoria camino para la instancia. Una de las consecuencias negativas de la separación de la asignación y la inicialización es la necesidad de estar al tanto de convenios como el initializer.You designado debe saber cuáles son los métodos inicializadores designados y cómo crear documentos nuevos y inicializadores en subclases. A largo plazo, el uso de inicializadores designados simplifica el desarrollo de software, pero no es un argumento para afirmar que el patrón thetwo-etapa de creación se suma a la curva de aprendizaje temprano para los desarrolladores de cacao. "


(c) Cocoa patrones de diseño por Erik M. Buck y Donald A. Yacktman

Usted no tiene que hacerlo. Puede utilizar [MyClass new]. Esto es similar a su método de init hipotético.

Básicamente, Objective-C, que no contaba con la recolección de basura en un principio, separa el concepto de asignación de memoria y la inicialización de clase. Es por eso que hay dos métodos distintos. Cuando se llama a alloc, se están asignando memoria explícitamente.

La mayoría de las clases tienen lo que usted está pidiendo. Usted ha recibido respuestas antes de por qué esto es como es y por qué no siempre se desea utilizar esto todo el tiempo, pero si usted lee la documentación de las clases verá muchos métodos de la clase que actúan de esta manera y se utilizan a menudo.

Para NSString que tienen, por ejemplo:

+ (id)string  // (Empty string)
+ (id)stringWithFormat:...  // Formatted string (like you use)
+ (id)stringWithContentsOfURL:... // String populated with contents of URL

Y así sucesivamente. Y usted entonces usar esto como: NSString *myString = [NSString stringWithFormat:@"Hello %@\n", userName];

La mayoría de las otras clases tienen esta, al igual que NSArray:

+ (id)array
+ (id)arrayWithContentsOfFile:...
+ (id)arrayWithContentsOfURL:...
+ (id)arrayWithObjects:...

Sólo tiene que leer la documentación. :) Y lea las otras respuestas sobre por qué no se desea utilizar esta demasiado.

alloc : La memoria se asigna / dado al objeto-referencia. Ahora referencia tiene la posesión de la memoria, pero no ha hecho nada todavía. Esta memoria esté vacía (el caso más raro) o con un poco de datos anónimos.

alloc e init : La memoria asignada es limpiada / descarga. La memoria se inicia por bit cero.

alloc y initwithdata ... . La memoria asignada se inicia con los datos deseados respetados a las propiedades de la clase

Por ejemplo, cuando usted compra una parcela se obtiene la posesión. Esta parcela se le da a usted, ya que es, ladrillos o en ruinas antigua casa puede estar allí. Este es alloc .

Al limpiar el terreno y eliminar toda la suciedad y la basura. Este es alloc con init.

Cuando se genera eso en alguna casa valioso se vuelve más significativo para usted. Y es alloc initwith ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top