CGFloats, float устанавливается в ноль - PullRequest
2 голосов
/ 16 февраля 2011

У меня есть собственный класс Custom.mm, в котором я пытаюсь установить значение с плавающей запятой, используя установщик в моем классе контроллера MainController.Пользовательский экземпляр типизируется как идентификатор, потому что это файл Obj-C ++, и указание на соответствующий класс во время компиляции мне помогло.Все отлично работает, экземпляр проверен.Если я установил переменную количества как тип int и передал int, он работает нормально.То же самое с любым другим значением или объектом - кроме плавающих.По некоторым причинам значения типа float (float, CGFloat и т. П.) Установлены в 0 в классе Custom.mm.Это не проблема с NSLog или чем-то еще - я проверил переменную количества с точкой останова, и все работает, но плавает.*

Ответы [ 2 ]

6 голосов
/ 17 февраля 2011

Я смог воспроизвести это самостоятельно; Вы столкнулись с интересным явлением.

Ваша проблема в том, что компилятор не видит определения для метода 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.)

По крайней мере, это предупреждение, которое я получаю. Это был компилятор, который говорил вам, что он не знает, куда поместить параметры при выполнении этого вызова, поэтому он просто выбрал что-то и надеялся, что это сработает. В данном случае это не так.

Что касается правильной работы целых чисел и других типов, предположение компилятора о стиле передачи параметров как раз соответствует тому, что ожидал получатель. Это было просто удача.

0 голосов
/ 17 февраля 2011

Похоже, вы не присвоили пользовательский объект переменной customInstance MainController, поэтому он равен nil Спросите у ноля что-нибудь, и это даст вам 0.

...