Сохранение DeviceToken для последующего использования в службах уведомлений Apple Push Notification

В моем приложении iPhone я получаю токен устройства от Apple, которому я назначаю публичное свойство в файле Delegate, как показано ниже:

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
   self.dToken = [[NSString alloc] initWithData:deviceToken encoding:NSUTF8StringEncoding]; 
}

Свойство dToken объявляется как показано ниже:

NSString *dToken;

@property (nonatomic,retain) NSString *dToken;

Но когда я пытаюсь извлечь токен устройства из другого файла, я получаю нулевое значение.

+(NSString *) getDeviceToken
{
  NSString *deviceToken = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] dToken];

    NSLog(@" getDeviceToken = %@",deviceToken);  // This prints NULL

    return deviceToken; 

}

Что я делаю неправильно?

Ответ 1

Я предлагаю вам преобразовать токен в строку следующим образом:

self.dToken = [[[deviceToken description]
                    stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] 
                    stringByReplacingOccurrencesOfString:@" " 
                    withString:@""];

ОБНОВЛЕНО: Как упоминалось многими людьми, лучше использовать следующий подход для преобразования NSData * в NSString *:

@implementation NSData (Conversion)
- (NSString *)hexadecimalString
{
  const unsigned char *dataBuffer = (const unsigned char *)[self bytes];

  if (!dataBuffer) {
    return [NSString string];
  }

  NSUInteger          dataLength  = [self length];
  NSMutableString     *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];

  for (int i = 0; i < dataLength; ++i) {
    [hexString appendFormat:@"%02lx", (unsigned long)dataBuffer[i]];
  }

  return hexString;
}
@end

Ответ 2

Из обсуждения в Лучший способ сериализации NSData в шестнадцатеричной строке - вот лучший способ сделать это. Это длиннее, но ваш код будет надежным, если Apple изменит способ, которым NSData испускает описания отладчика.

Расширьте NSData следующим образом:

@implementation NSData (Hex)
- (NSString*)hexString {
    unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (self.length*2));
    unsigned char* bytes = (unsigned char*)self.bytes;
    for (NSUInteger i = 0; i < self.length; i++) {
        unichar c = bytes[i] / 16;
        if (c < 10) c += '0';
        else c += 'A' - 10;
        hexChars[i*2] = c;
        c = bytes[i] % 16;
        if (c < 10) c += '0';
        else c += 'A' - 10;
        hexChars[i*2+1] = c;
    }
    NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars
                                                           length:self.length*2 
                                                     freeWhenDone:YES];
    return [retVal autorelease];
}
@end

Ответ 3

Я знаю, что это старый вопрос и что это может быть новая информация, появившаяся с тех пор, но я просто хотел бы указать что-то всем тем, кто утверждает, что использование метода описания является действительно плохая идея. В большинстве случаев вы будете абсолютно правы. Свойство описания обычно используется для отладки, но для класса NSData оно определенно определяется как возвращающее шестнадцатеричное представление содержимого приемников, которое именно то, что здесь необходимо. Поскольку Apple поставила его в своей документации, я думаю, вы достаточно безопасны, насколько они меняют его.

Это можно найти в описании класса NSData: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html