31

私はこれを使用できないことを知っています:

myView.frame.origin.x = 25.0;

代わりにこれを使用する必要があります。

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

そして、私はいつもそれをやっています、しかし私はなぜ私がそれをそのようにしなければならないのか分かりません。私の理解のギャップを埋めたいと思います。誰かが説明できますか?

現在、Xcodeは「表現を割り当てられない」ものを提供します。少し前に、「割り当ての左側のオペランドとして左辺値が必要です」というコンパイルエラーが発生しました。

4

4 に答える 4

41

ここで使用されている2つの異なるドット構文があります。それらは同じように見えますが、操作対象とそれを使用して実行されている内容に応じて、異なる動作をします。

  • 1つ目は、構造体を値で返すメソッド呼び出しmyView.frameの省略形です。[myView frame]CGRect
  • myFrame.origin.x 従来のC方式で通常の構造体メンバーにアクセスしています。
  • 2つ目myView.frameも省略形ですが、ステートメントは割り当てであるため、別のメソッドを呼び出すことになり[myView setFrame:myFrame]ます。

単一行の一番上の例では、rectのコピーを取得して設定しますxが、ビューにコピーして戻すことはありません。メソッド呼び出しを明示的に区別する必要があります。ドット構文シュガーは、メソッド呼び出しを1つの呼び出しに魔法することはできません。

于 2010-06-06T10:56:33.710 に答える
17

これが機能しない理由は、2つの構文が混在しているためです。
まず、「。」があります。アクセサ関数(Objective-C機能)を呼び出すためのショートカットとして。それで

  • abは[agetB]になります。
  • ab =5は[asetB:5]になります。

そして、そこに「。」直接構造体メンバーアクセスとして(純粋なC)。それで

  • abは本当にabです。
  • abは実際にはab=5です。

このようにset-value-caseでこれを組み合わせると、機能しません。
なぜなら...あなたが電話できれば

myView.frame.origin.x = 25.0;
  • 「myView.frame」の部分は[myViewgetFrame]と等しく、コピーされたCGRectフレーム(C構造体)を取得します。

  • 「myView.frame.origin」は、コピーされたCGRectのCGPointオリジン(構造体でもあります)を提供します

  • "myView.frame.origin.x = 25.0"は、原点のCGFloat xを提供します。次に、それに何かを割り当てたいと思います。ここで問題が発生します...

構造体の構造体の変数を設定しようとしましたが、これは問題ありませんが、UIViewから構造体へのポインターがないため、代わりにコピーされます。したがって、コピーしてから設定すると、設定されたアクションがUIViewへの最初の取得を通じて何らかの形で転送されることが期待されますが、これは機能しません。

もちろん、なぜAppleがショートカットを作成しただけではないのか不思議に思うかもしれません。そのため、コピーしたフレームは自動的に自動追加されたsetFrame呼び出しに再注入されます。

したがって、フレームへのポインタを取得すれば機能することを覚えておいてください。ただし、そうではなく、代わりにコピーされた構造体を取得します。
したがって、動作することを期待myView.frame.origin.x = 25.0している場合は、呼び出しが自動的にある種のに変換されることを間接的に期待します
[myView setFrame:[myView getFrame:frame].origin.x = 25.0]
まあ、これは間違っているように見えることを認めることができると思います。

また、CGRectフレームへの直接ポインターを取得し、そのポインターを介して何かを変更した場合、UIViewは、サイズが変更され、それ自体を更新する必要があることをどのように認識しますか?一方、[myView setFrame:newFrame]呼び出しが行われた場合、UIViewは必要なすべての再調整を実行できます。

于 2010-06-06T11:18:56.947 に答える
2

ACGRectは構造体であり、標準Cのものです。ACGRectはObjective Cオブジェクトではないため、そのメンバーの1つに割り当てると、setterメソッドは呼び出されません。セッターメソッドが呼び出されないと、UIKitは何かが変更されたことを知ることができないため、画面表示を更新できません。

編集:指摘されているように、割り当ては構造体のコピーになります。

于 2010-06-06T10:52:52.670 に答える
1

データを直接操作する場合、アクセサーは呼び出されないため、UIはそれ自体を更新できません。または、変更について知りたい他のコンポーネントに通知することもできません。

編集:walkytalkyが指摘しているように、データのコピーを取得するため、データを変更しても元のデータには影響しません。次の例はこれを示しています。

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
于 2010-06-06T10:45:06.263 に答える