CGFloats,浮点数设置为零

aka*_*aru 2 iphone objective-c getter-setter

我有一个自定义类Custom.mm,我试图在我的控制器类MainController中使用setter设置一个浮点值.Custom实例被输入为id,因为它是一个Obj-C++文件,并且在编译时指向正确的类对我来说效果很好.一切正常,实例已经过验证.如果我将amount变量设置为int类型并传递ints,它可以正常工作.与任何其他值或对象相同 - 浮点数除外.出于某种原因,在Custom.mm类中将float(float,CGFloat等)设置为0.这不是NSLog或其他任何问题 - 我用断点检查了数量变量,一切正常但浮动.

    //Custom.h
 @interface Custom : UIView  
{

      CGFloat amount;

}

 @property CGFloat amount;

 @end
Run Code Online (Sandbox Code Playgroud)
    //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;
}
Run Code Online (Sandbox Code Playgroud)
    //MainController.h
@interface MainController : UIViewController 
{
    IBOutlet id customInstance; //IB points to the CustomView class
}
Run Code Online (Sandbox Code Playgroud)
    //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
Run Code Online (Sandbox Code Playgroud)

BJ *_*mer 6

我能够自己重现这个; 你遇到了一个有趣的现象.

您的问题是编译器无法看到该setAmount:方法的定义.因此,它不知道方法所期望的参数的正确类型.在这种情况下,编译器假定所有参数都是"..."类型,返回值的类型为"id".但是你传递的是CGFloat,而不是'......'.

Objective-C是一种动态语言,所以即使编译器不知道目标方法是否存在,它仍然会很高兴地打包参数并尝试调用它.但是,在大多数体系结构中,传递参数的方法取决于参数的类型.整数和指针参数通常在一组寄存器中传递,而浮点参数在另一组寄存器中传递,而结构通常直接在堆栈上传递.(精确的细节取决于您正在运行的体系结构.)由于编译器无法看到setAmount:方法的定义,因此它假定参数是类型的....根据体系结构,可以在不同的寄存器集中传递,也可以在堆栈中传递.

setAmount:然而,当该方法运行时,期望传入的参数在某组寄存器中.当然,调用者没有填充那些,因此仍设置为0.调用者将新值放在一个位置,但接收者查看另一个位置.难怪事情出了问题.

解决方案很简单:#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.)
Run Code Online (Sandbox Code Playgroud)

至少,这是我得到的警告.那是编译器告诉你它在进行调用时不知道在哪里放置参数,所以它只是选择了一些并希望它有效.在这种情况下,它没有.

至于int和其他类型正常工作,编译器对参数传递样式的猜测恰好与接收器期望的匹配.这是一个简单的运气问题.