I need the user's device token as a hexadecimal string to send push notifications. I used to do this by using the deviceToken 'description', but this doesn't work anymore in iOS13. I found several solutions for this in Objective-C and Swift.
How can I convert my device token (NSData) into an NSString?
The problem however, is that deviceToken.bytes
returns a Pointer
in RubyMotion. And calling bytes[index]
will give a different result compared to doing it in Objective-C. I've tried a lot of different things, but I can't seem to get it to work. The RubyMotion docs about Pointers are also really barebones, so that doesn't help. I found the following regarding the Pointers on SO:
It says that I have to do bytes + index
instead of bytes[index]
. I currently have the following code:
def application(application, didRegisterForRemoteNotificationsWithDeviceToken: device_token)
string = token_to_string(device_token)
end
def token_to_string(device_token)
data_length = device_token.length
if data_length == 0
nil
else
data_buffer = device_token.bytes
token = NSMutableString.stringWithCapacity(data_length * 2)
index = 0
begin
buffer = data_buffer + index
token.appendFormat('%02.2hhx', buffer)
index += 1
end while index < data_length
token.copy
end
end
It's not giving any errors, but the generated device token doesn't seem to be correct. Any advice would be greatly appreciated!
I've been trying to think of a pure RubyMotion solution, but I just don't understand 'Pointers' enough to get it to work. So I've gone a different way: extending the NSData class.
1) Create the folder vendor/NSData+Hex inside your project.
2) Create the file NSData+Hex.h inside the folder and put this inside:
#import <Foundation/Foundation.h>
@interface NSData (Hex)
@property (nonatomic, copy, readonly) NSString *hexString;
@end
3) Now create NSData+Hex.m in the same folder and put this in the file:
#import "NSData+Hex.h"
@implementation NSData (Hex)
- (NSString *) hexString
{
NSUInteger len = self.length;
if (len == 0) {
return nil;
}
const unsigned char *buffer = self.bytes;
NSMutableString *hexString = [NSMutableString stringWithCapacity:(len * 2)];
for (int i = 0; i < len; ++i) {
[hexString appendFormat:@"%02x", buffer[i]];
}
return [hexString copy];
}
@end
4) Add this to your Rakefile:
app.vendor_project('vendor/NSData+Hex', :static)
5) Now you can simply call deviceToken.hexString
within def application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
.
If anyone can think of a pure RubyMotion solution, feel free to answer. For now, it's at least working. :)