2010-06-06 25 views
31

sé que no puedo usar esto:myView.frame.origin.x = value; no funciona, pero ¿por qué?

myView.frame.origin.x = 25.0; 

y que tengo que usar esto en su lugar:

CGRect myFrame = myView.frame; 
myFrame.origin.x = 25.0; 
myView.frame = myFrame; 

y estoy haciendo todo el tiempo, pero no lo hago sé por qué debo hacerlo de esa manera. Me gustaría llenar ese vacío en mi entendimiento. ¿Alguien puede explicar?

Hoy en día Xcode le da "Expresión no asignable". Hace algún tiempo, recibiste un error de compilación "Lvalue requerido como operando de asignación izquierdo".

+1

+1 - Me he estado preguntando sobre esto durante bastante tiempo ... – Emil

Respuesta

17

La razón por la que esto no funciona se debe a la mezcla de dos sintaxis.
Primero tiene "." como un atajo para llamar a las funciones de acceso (una característica de Objective-C). Así

  • a.b se convierte en [a getB];
  • a.b = 5 se convierte en [a setB: 5];

Y luego hay "."Como acceso directo struct miembro (C puro) Así

  • ab realmente es ab;.
  • ab realmente es ab = 5;

Combinando esto en un conjunto de valores de los casos como éste , no funciona.
Porque ... si se puede llamar

myView.frame.origin.x = 25.0; 
  • La parte "myView.frame" es igual a [myView GetFrame] y se obtiene un marco CGRect copiado (una estructura C)

  • El "myView.frame.origin" le da un origen CGPoint (también una estructura) de la copiado CGRect

  • el "myView.frame.origin.x = 25,0" le da una CGFloat x del origen y ahora desea asignar algo a ella y aquí viene el problema ...

Intenta establecer una variable de una estructura de una estructura, lo que está bien, pero no hay un puntero desde UIView a la estructura, por lo que se copia en su lugar. Así que copie y luego configure y luego espera que la acción establecida se reenvíe de alguna manera a través del acceso inicial a UIView, y esto simplemente no funciona.

Por supuesto, podría preguntarse por qué Apple no acaba de crear un atajo, de modo que al final su foto copiada se reinyecta automáticamente en una llamada setFrame añadida automáticamente, supongo que solo tiene que vivir cómo es.

Así que recuerda, funcionaría si obtienes un puntero al marco, pero no lo haces, obtienes una estructura copiada.
Si espera que myView.frame.origin.x = 25.0 funcione, espera que su llamada se traduzca automágicamente a algún tipo de
[myView setFrame:[myView getFrame:frame].origin.x = 25.0].
Bueno, supongo que puedes admitir que esto parece estar mal.

Imagine también que si obtiene un puntero directo al marco CGRect y cambia algo a través de ese puntero, ¿cómo sabría la UIView que su tamaño ha cambiado y que debe actualizarse? Si, por otro lado, se realiza una llamada [myView setFrame: newFrame], entonces UIView puede realizar todos los reajustes necesarios.

1

Cuando manipula los datos directamente, no se llama a ningún accesorio, por lo que la interfaz de usuario no puede actualizarse a sí misma o informar a cualquier otro componente que desee conocer los cambios.

Editar: Como señaló walkytalky, obtendrá una copia de los datos, por lo que cambiarlo no tiene ningún efecto en el original de todos modos. El siguiente ejemplo mostrará lo siguiente:

UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(50,50,100,100)]; 
NSLog(@"%f", aView.frame.origin.x); // will give 50 
aView.frame.origin.x = 17; // operates on a copy of the rect only 
NSLog(@"%f", aView.frame.origin.x); // will still give 50 
+0

Creo que debería obtener un "Lvalue requerido como operando de asignación izquierdo" del compilador primero. – Allisone

+0

todavía me entendió. gracias – Allisone

+0

No hay advertencias del compilador aquí ... – Eiko

2

Un CGRect es una estructura, que es algo de la norma C. Un CGRect es no un objeto Objective C, por lo que cuando se asigna a uno de sus miembros, sin colocador método se llama. Sin un método setter llamado, UIKit no podrá saber que algo ha cambiado, y por lo tanto no podrá actualizar la pantalla.

Editar: como se ha señalado, la asignación será a una copia de la estructura.

39

Aquí se utilizan dos sintaxis de puntos distintas. Ellos tienen el mismo aspecto, pero lo hacen diferentes cosas dependiendo de lo que están operando en y lo que se hace con ella:

  • La primera myView.frame es una abreviatura de [myView frame], una llamada al método que devuelve un CGRect estructura por valor.
  • myFrame.origin.x está accediendo a miembros ordinarios de la estructura de la manera tradicional C.
  • El segundo myView.frame es de nuevo una forma abreviada, pero debido a que la declaración es una asignación se traduce en llamar a un método diferente, [myView setFrame:myFrame].

En su ejemplo superior de una línea, obtiene una copia del rect y establece su x, pero nunca lo copia de nuevo a la vista. Tienes que diferenciar explícitamente entre las llamadas al método, la sintaxis de punto sugar no puede convertirlas en una sola llamada.

+2

gran explicación! – reflog

Cuestiones relacionadas