float variable1, variable2;
float *variable1Pointer, *variable2Pointer;
float *activeNumberPointer;
}
float variable1 = 0;
float variable2 = 0;
float* variable1Pointer = &variable1;
float* variable2Pointer = &variable2;
float* activeNumberPointer = &variable1;
Вы не можете инициализировать переменные экземпляра в классе @interface
. То, что вы на самом деле здесь сделали, объявили две переменные с каждым из этих имен.
Для каждого имени одна переменная является переменной экземпляра, объявленной в {…} сразу после @interface
, а другая - глобальной переменной, объявленной в другом месте заголовка. В частности, вы объявили глобальные переменные в @interface
, но это не имеет значения: глобальные переменные не имеют никакого отношения к какому-либо классу или объекту, и вы можете поместить их в @interface
или без него без возражений компилятора.
Вы инициализировали переменные глобального указателя так, чтобы они указывали на глобальные переменные float
, но внутри тела метода в @implementation
переменные экземпляра опережают глобальные переменные (переменные экземпляра имеют более узкую область действия). Более того, свойства всегда основаны на переменных экземпляра, а не на глобальных переменных. Поэтому в методах вы ссылаетесь (через свойства) на переменные экземпляра, а не на глобальные переменные, которые вы инициализировали.
Переменные экземпляра инициализируются в nil
во время создания экземпляра, поэтому значение переменной экземпляра activeNumberPointer
равно NULL
. Таким образом, утверждения, подобные этому:
*self.activeNumberPointer = *self.activeNumberPointer * 10 + buttonClicked;
чтение и запись в нулевой указатель. Это авария, которую вы видите.
Также стоит отметить, что это:
*self.activeNumberPointer = …
не является присваиванием свойства, то есть оно не отправляет self
a setActiveNumberPointer:
сообщение; это свойство retrieval (отправка получающего сообщения), которое возвращает указатель. Стоит сократить собственность, чтобы не перепутать их здесь.
Решение проблемы заключается в удалении глобальных переменных и инициализации переменных вашего экземпляра в коде. Для этого и используется метод init
. Переопределите init
в обычным способом и установите там свои начальные значения указателя. Доступ к этим переменным экземпляра напрямую (без прохождения через свойство) по всему классу.
Еще лучше, вообще не обходиться с манипулированием указателем. Используйте переменную BOOL
для выбора между ними:
BOOL editingVariable2;
Проверяйте логическое значение всякий раз, когда вам нужно работать с активной переменной. Чтобы не писать надоедливые операторы if-else каждый раз, когда возникает необходимость, вы можете инкапсулировать их в метод с именем setValueOfActiveVariable:switchActive:
, который выполняет то, что говорит первая часть, и затем, если аргумент второй части равен * 1044. *, переключает активную переменную.
Решение с булевыми переменными исключит риск полного доступа к неинициализированному или недействительному указателю float
из этого класса.