the test study spanish questionnaire experiences cognitivo childhood adverse objective-c struct variable-assignment declared-property

objective-c - study - adverse childhood experiences test



myView.frame.origin.x=value; no funciona, pero ¿por qué? (4)

Sé que no puedo usar esto:

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 lo hago todo el tiempo, pero no sé por qué debo hacerlo de esa manera. Me gustaría llenar ese vacío en mi entendimiento. ¿Alguien puede explicar?

Hoy 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".


Aquí se usan dos sintaxis de puntos distintas. Se ven iguales, pero hacen cosas diferentes dependiendo de en qué están operando y qué se está haciendo con ello:

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

En su ejemplo superior de línea única, obtiene una copia del rect y establece su x , pero nunca la 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.


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

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

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


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

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

Y luego hay "". como acceso directo a miembro de estructura (C puro). Asi que

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

Combinar esto en un caso de valor de conjunto como este, no funciona.
Porque ... si pudieras llamar

myView.frame.origin.x = 25.0;

  • La parte "myView.frame" es igual a [myView getFrame] y obtienes un fotograma CGRect copiado (una estructura C)

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

  • El "myView.frame.origin.x = 25.0" le da un CGFloat x del origen y ahora quiere asignarle algo 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 acceso directo, de modo que al final su foto copiada se reinyecta automáticamente en una llamada de setFrame añadida automáticamente, supongo que solo tiene que vivir cómo es.

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

Imagine también que si obtiene un puntero directo al marco de 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.


Un CGRect es una estructura, que es algo del estándar C. Un CGRect no es un objeto Objective C, por lo que cuando se asigna a uno de sus miembros, no se llama a ningún método setter. 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.