% d не показывает целое число правильно - PullRequest
0 голосов
/ 10 ноября 2009

Как я пытаюсь написать

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

, где myId равен int, консоль дает некоторое высокое число, например 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

Ответы [ 6 ]

4 голосов
/ 10 ноября 2009

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

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

4 голосов
/ 10 ноября 2009

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

#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);

Что даже не компилируется, выдавая ошибку:

foundation.m:21: error: accessing unknown 'myId' class method
1 голос
/ 11 ноября 2009

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

0 голосов
/ 11 ноября 2009

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

@property(nonatomic) int myId;

к этому:

@property(nonatomic, assign) int myId;

И дайте мне знать ваш результат, я подозреваю, что obj-c делает что-то необычное при назначении старого int новому int?

0 голосов
/ 11 ноября 2009

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

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

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

Бьюсь об заклад, вы найдете эту запись сделки, прежде чем вы увидите журнал для myObject.myID.

0 голосов
/ 10 ноября 2009

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

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

NSLog (@ "% @", [[NSNumber numberFromInt: 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. Для запуска цикла for с более чем 256 итерациями требуется long. С 32-битным int вы не увидите таких проблем и никогда не выработаете привычку отслеживать размер ваших int переменных.

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

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


Редактировать # 2:

где myId - int, консоль дает высокий номер как 70614496.

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...