2

カスタム クラス Custom.mm があり、コントローラー クラス MainController でセッターを使用して float 値を設定しようとしています。Custom インスタンスは、Obj-C++ ファイルであり、コンパイル時に適切なクラスを指しているため、id として型指定されています。すべて正常に動作し、インスタンスが検証されました。amount 変数を int 型として設定し、int を渡すと、正常に動作します。フロートを除く、他の値またはオブジェクトと同じです。Custom.mm クラスでは、何らかの理由で float (float、CGFloat など) が 0 に設定されています。これは NSLog などの問題ではありません。ブレークポイントを使用して amount 変数をチェックしたところ、すべてが動作しましたが、フロートしました。

    //Custom.h
 @interface Custom : UIView  
{

      CGFloat amount;

}

 @property CGFloat amount;

 @end

    //Custom.mm
@implementation Custom
@synthesize  amount;

- (id) initWithCoder:(NSCoder*)coder
{
    if ((self = [super initWithCoder:coder])) 
    {
        //set initial value to 1
        self.amount = 1.0;  //verified as 1.0
    }
    return self;
}

    //MainController.h
@interface MainController : UIViewController 
{
    IBOutlet id customInstance; //IB points to the CustomView class
}

    //MainController.m
@implementation MainController

-(void)viewDidLoad
 {
        [super viewDidLoad];

        //Checking this value in Custom.mm via the debugger shows it as being 0, 
        //when before it was 1.0. 
        [customInstance setAmount:2.0]; 
  }

 @end
4

2 に答える 2

6

これを自分で再現できました。興味深い現象に遭遇しました。

問題は、コンパイラがsetAmount:メソッドの定義を認識できないことです。その結果、メソッドが予期している引数の正しい型がわかりません。このような場合、コンパイラは、すべてのパラメーターが「...」型であり、戻り値が「id」型であると想定します。しかし、「...」ではなくCGFloatを渡しています。

Objective-C は動的言語であるため、コンパイラがターゲット メソッドが存在するかどうかを認識していない場合でも、パラメーターを喜んでパッケージ化し、とにかくそれを呼び出そうとします。ただし、ほとんどのアーキテクチャでは、パラメータを渡す方法はパラメータのタイプによって異なります。通常、整数とポインターのパラメーターは 1 つのレジスター セットで渡され、浮動小数点パラメーターは別のセットで渡され、構造体は通常、スタック上で直接渡されます。(正確な詳細は、実行しているアーキテクチャによって異なります。) コンパイラはsetAmount:メソッドの定義を認識できないため、パラメータの型が であると想定します...。アーキテクチャによっては、これらが異なるレジスタ セットに渡されたり、スタックに渡されたりする場合もあります。

ただし、setAmount:メソッドを実行すると、渡されたパラメーターが特定のレジスターのセットにあることが想定されます。もちろん、それらは呼び出し元によって設定されていないため、まだ 0 に設定されています。呼び出し元は新しい値を 1 つの場所に配置しましたが、受信者は別の場所を調べました。物事がうまくいかないのも不思議ではありません。

#import "Custom.h"これに対する解決策は簡単です:の先頭に追加しMainController.mます。次に、コンパイラはsetAmount:コンパイル時の定義を確認できるためMainController、受信者が期待する場所に新しい値を配置することがわかります。

ちなみに、コンパイル中に警告が表示されたことは間違いありません。何かのようなもの

warning: no '-setAmount:' method found
warning: (Messages without a matching method signature
warning: will be assumed to return 'id' and accept
warning: '...' as arguments.)

少なくとも、それは私が得ている警告です。それは、その呼び出しを行うときにパラメーターをどこに置くべきかわからなかったため、何かを選択して、それが機能することを望んでいたことをコンパイラーが伝えていました。この場合、そうではありませんでした。

int やその他の型が正しく機能していることについては、パラメーターの受け渡しスタイルに対するコンパイラーの推測が、たまたまレシーバーが期待していたものと一致しただけです。それは単純な運の問題でした。

于 2011-02-17T03:35:03.663 に答える
0

MainController のcustomInstance変数に Custom オブジェクトを割り当てていないようですので、nil です。nil に何かを要求すると、0 が返されます。

于 2011-02-16T23:48:27.497 に答える