CGFloats,浮点数设置为零

发布于 2024-10-17 17:26:31 字数 1192 浏览 6 评论 0原文

我有一个自定义类 Custom.mm,其中我尝试使用控制器类 MainController 中的设置器设置浮点值。 Custom 实例被输入为 id,因为它是一个 Obj-C++ 文件,并且在编译时指向正确的类对我来说效果很好。一切正常,实例已验证。如果我将 amount 变量设置为 int 类型并传递 int,它就可以正常工作。与任何其他值或对象相同——除了浮点数。由于某种原因,Custom.mm 类中的浮点数(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

I have a custom class Custom.mm in which I am trying to set a float value using a setter in my controller class MainController. The Custom instance is typed as an id because it is an Obj-C++ file and pointing to a proper class at compile time has worked well for me. Everything works fine, the instance is verified. If I set up the amount variable as type int and pass ints it works fine. Same with any other value or object--except floats. For some reason floats (float, CGFloat and the like) are set to 0 in the Custom.mm class. This is not an issue with NSLog or anything--I've checked the amount variable with a breakpoint and everything works but floats.

    //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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

哀由 2024-10-24 17:26:31

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

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

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

然而,当 setAmount: 方法运行时,它期望传入的参数位于一组特定的寄存器中。当然,这些值没有被调用者填充,因此仍然设置为 0。调用者将新值放在一个位置,但接收者在另一个位置查找。难怪事情会出错。

解决这个问题的方法很简单:在MainController.m顶部添加#import "Custom.h"然后,编译器将在编译 MainController 时能够看到 setAmount: 的定义,从而知道将新值放在接收者期望的位置。

顺便说一句,我敢打赌,当你编译时,你会收到警告;至少

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

,这就是我收到的警告。那是编译器告诉您它在进行调用时不知道将参数放在哪里,因此它只是选择了一些东西并希望它能起作用。在这种情况下,它没有。

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

I was able to reproduce this on my own; you've run into an interesting phenomenon.

Your problem is that the compiler can't see a definition for the setAmount: method. As a result, it doesn't know the correct type of the arguments that method is expecting. In such cases, the compiler assumes that all parameters are of type '...', and return values are of type 'id'. But you're passing a CGFloat, not a '...'.

Objective-C is a dynamic language, so even when the compiler doesn't know whether the target method exists, it will happily package up the parameters and try to call it anyway. However, on most architectures the method for passing parameters is dependent on the type of the parameters. Integers and pointer parameters are usually passed in one set of registers, while floating point parameters are passed in another, and structs are usually passed directly on the stack. (Precise details depend on which architecture you're running on.) Since the compiler can't see the definition for the setAmount: method, it assumes that the parameters are of type .... Depending on the architecture, those may be passed in a different set of registers, or even on the stack.

When the setAmount: method runs, however, it is expecting the passed-in parameters to be in a certain set of registers. Those weren't populated by the caller, of course, and are thus still set to 0. The caller put the new value in one location, but the receiver looked in another. No wonder things are going wrong.

The solution to this is simple: Add #import "Custom.h" at the top of MainController.m. Then, the compiler will be able to see the definition of setAmount: when it's compiling MainController, and will thus know to put the new values in the place that the receiver is expecting them.

Incidentally, I'll bet that when you were compiling, you were getting a warning; something like

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

At least, that's the warning I'm getting. That was the compiler telling you that it didn't know where to put the parameters when making that call, so it just picked something and hoped it worked. In this case, it didn't.

As for ints and other types working correctly, the compiler's guess at the parameter passing style just happened to match what the receiver was expecting. It was a simple matter of luck.

尤怨 2024-10-24 17:26:31

看起来您还没有将 Custom 对象分配给 MainController 的 customInstance 变量,因此它为零。向 nil 询问任何东西,它都会给你 0。

It looks like you haven't assigned a Custom object to the MainController's customInstance variable, so it's nil. Ask nil for anything and it will give you 0.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文