2009-11-10 3 views
0

Как я пытаюсь написать% d не показывает целое число правильно

NSLog(@"%d", myObject.myId); 

где MyId является int, консоль дает некоторое количество Hight как 70614496. И когда я использую @"%@", я получаю исключение -[CFNumber respondsToSelector:]: message sent to deallocated instance 0x466c910. Почему это так?

Вот определение MyObject:

@interface myObject : NSObject { 
int myId; 
NSString *title; 
} 

@property(nonatomic) int myId; 
@property(nonatomic, retain) NSString *title; 

@end 

@implementation myObject 

@synthesize myId, title; 

- (void)dealloc { 
[title release]; 

[super dealloc]; 
} 

@end 
+0

Если 'myObject.myId' действительно является' int', это должно работать нормально. Первое, что нужно сделать, это дважды проверить это; можете ли вы показать нам интерфейс и/или реализацию любого класса 'myObject' является экземпляром? –

+0

ОК, я обновил код – cocoapriest

+1

Разве это даже компилируется? Попытаться получить переменную экземпляра из объекта класса, я имею в виду. Мой тестовый пример здесь не строился. –

ответ

0

Похоже, что ваш экземпляр myObject был автореализован в какое-то время и больше не действителен. Вот почему вы видите странную проблему NSNumber, когда пытаетесь разыменовать ее как объект. Когда вы просто запрашиваете целое число, вы не получите какой-либо ошибки, он просто отобразит адрес указателя, введенный в целое число.

Чтобы увидеть, когда ваш MyObject получает dealloced, попробуйте добавить что-то вроде этого к методу dealloc в своем классе:

- (void)dealloc 
{ 
    NSLog(@"dealloc called on %@", self); 
    [title release]; 
    [super dealloc]; 
} 

Я уверен, вы найдете это в лог dealloc, прежде чем увидеть журнал для вашего MyObject. мой ID.

+0

Джейсон, это была бы очень хорошая идея! Но нет, мой obj не освобождается где-то до этой проблемы ... – cocoapriest

+0

Вы уверены, что он не получает автореализован или случайно выпущен? –

+0

Почти наверняка - во всяком случае dealloc не вызывается до этого – cocoapriest

4

Вот пример, показывающий, что он должен работать так, как вы первый попробовал, если ваш/объект/переменная экземпляра класса все настроено правильно:

#import <Foundation/Foundation.h> 

@interface MyClass : NSObject 
{ 
    int myId; 
} 

@property int myId; 
@end 

@implementation MyClass 
@synthesize myId; 
@end 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    MyClass *myObject = [[MyClass alloc] init]; 

    myObject.myId = 5; 
    NSLog(@"%d", myObject.myId); 

    [myObject release]; 
    [pool drain]; 
    return 0; 
} 

Ваш код показывает, вы делаете эквивалент этой линии:

NSLog(@"%d", MyClass.myId); 

Что не е ven compile, давая ошибку:

foundation.m:21: error: accessing unknown 'myId' class method 
+0

извините, это была ошибка копирования и вставки. Конечно, я использовал экземпляр. Поэтому моя проблема все еще актуальна. Интересно, что я попробовал это в новом проекте и работает так, как ожидалось. В моем проекте я использую myObject в массиве внутри объекта singleton. Так может ли это проблема памяти? – cocoapriest

+0

Возможно, вы переписываете эту переменную где-то, не замечая ее. Errant 'memcpy()' или что-то, возможно. –

+2

Вы можете установить часы на этой области памяти в gdb. Это заставит программу останавливаться каждый раз, когда будет записана память. http://www.delorie.com/gnu/docs/gdb/gdb_30.html – nall

4

Карл делает все возможное, чтобы получить код для компиляции. Просто другое слово в спецификаторе формата% @, так как ваш вопрос, кажется, подразумевает некоторую путаницу.

Когда вы используете% @ в формате NSLog, вы фактически отправляете аргумент сообщение description и печатаете полученную строку. Если myId является int, а не экземпляром NSObject, он не отвечает на сообщение описания. Используйте% d для значений int и% @ для экземпляров NSNumber.

-1

Просмотрите String Format Specifiers, чтобы узнать, как форматировать инструкции NSLog. Легко лениться с NSLog, потому что объекты имеют встроенный метод -description, который возвращает форматированную строку. Для значений масштабирования вы должны использовать правильный форматтер.

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

NSLog (@ "% @", [[Номер NSNumberFromInt: myObject.myId] stringValue]);

Это будет печатать правильно всегда.


Редактировать # 1: Прошу прощения. Я был лишен сна, когда написал выше. То, что я на самом деле предназначалось, было предостеречь от использования простого int против NSInteger, а также для печати с NSNumber numberWithInteger:.

Рассмотрите следующий запуск на 64-разрядном оборудовании.

int x=pow(2,63); 
NSLog(@"x=%d",x); //prints x=2147483647 

NSInteger n=pow(2,63); 
NSLog(@"n=%d",n); // prints n=-1 
NSLog(@"n=%@",[[NSNumber numberWithInteger:n] stringValue]); // prints n=9223372036854775807 

В старые дни 8-битных систем, вы столкнулись с проблемами, с проблемами с использованием 8-битного «Int» все время. Для запуска цикла с более чем 256 итерациями требуется long. С 32-битным int вы не увидите таких проблем и никогда не будете развивать привычку отслеживать размер ваших int переменных.

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

Написание для iPhone (или других будущих мобильных телефонов/платформ) означает запись на потенциально высоко изменяющемся оборудовании, как и в старые времена. Лучше всего привыкнуть к раннему использованию привычных определений систем и API.


Edit # 2:

where myId is int, console gives some hight number like 70614496.

(1) Если он печатает различное количество каждый раз, когда вы запускаете, то вы, вероятно, назначая указатель на междунар, когда вы установите его. NSLog правильно печатает значение указателя как int.

(2) Если он печатает одно и то же число каждый раз, у вас, вероятно, есть проблема с переполнением, как в моем первом изменении выше.

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

+0

Но тогда, если 'myObject.myId' является' int', то '% d' будет работать нормально, и если это не 'int', этот код не будет печатать правильный результат. –

+0

Зависит от инт. См. Мое редактирование выше. – TechZen

1

Учитывая это второе сообщение об ошибке, я думаю, что %d работает нормально, но где-то еще вы назначаете CFNumber или NSNumber для свойства myID, когда вам следует назначать целое число.

+0

Это была бы хорошая идея, но нет, есть только одно место, где я назначаю это значение, и это int. Я схожу с ума, с «po myObj» Я получаю объект, но с «po myObj.myId» я всегда получаю «*** - [CFNumber replysToSelector:]: сообщение отправлено на освобожденный экземпляр 0x46706e0». – cocoapriest

+1

Еще одно открытие, которое я сделал - когда я переименовал «int в NSNumber», все стало работать должным образом. Что случилось с типом значения здесь ??? – cocoapriest

+0

@ Константин: Можете ли вы показать код, в котором вы установили свойство? – Chuck

-1

Я хотел бы попробовать просто это изменить:

@property(nonatomic) int myId; 

к этому:

@property(nonatomic, assign) int myId; 

И дайте мне знать свой результат, я подозреваю, что Obj-C делает что-то напуганный при назначении старого Int к новому int?

+0

Назначение уже является выбором по умолчанию (и единственно допустимым) для скалярных типов. –

Смежные вопросы