【问题标题】:How to convert NSArray of NSNumbers into NSData如何将 NSNumber 的 NSArray 转换为 NSData
【发布时间】:2011-12-07 06:26:49
【问题描述】:

我是 Objective C 的新手,我正在修改一个用于发送 UDP 数据包的 Titanium 框架的 iOS 模块。该模块目前允许您传入要发送的文本字符串,并将其转换为字节并通过 UDP 将其发送到目标 ip 和端口。这很好用,这里是代码:

https://github.com/chrisfjones/titanium_module_udp/blob/master/UDPSocketProxy.m

我想要做的是将一个字节数组而不是一个字符串传递给发送函数,然后让它发送。这是钛代码:

var udp = require('chrisfjones.titanium_module_udp');
var socket = udp.createUDP();
var bytes = [ 100, 15, 132, 53, 14, 246, 0, 0, 0, 0, 196, 209, 1, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 16, 0, 45, 120, 0, 0, 0, 0, 158, 4, 111, 30, 179, 41 ];
socket.send(bytes, "1.2.3.4", 6100);

这是迄今为止的新发送功能:

- (void) sendBytes: (NSArray*) args {

    NSArray *msg       = (NSArray*)[args objectAtIndex: 0];

    NSString *host      = [TiUtils stringValue:[args objectAtIndex: 1]];

    NSInteger port      = [TiUtils intValue:   [args objectAtIndex: 2]];


NSLog(@"%@ send bytes: %@ to %@:%i", self, msg, host, port);


struct sockaddr_in destinationAddress;

    socklen_t sockaddr_destaddr_len = sizeof(destinationAddress);



    memset(&destinationAddress, 0, sockaddr_destaddr_len);

    destinationAddress.sin_len = (__uint8_t) sockaddr_destaddr_len;

    destinationAddress.sin_family = AF_INET;

    destinationAddress.sin_port = htons(port);

    destinationAddress.sin_addr.s_addr = inet_addr([host cStringUsingEncoding: NSUTF8StringEncoding]);



    NSData *destinationAddressData = [NSData dataWithBytes:&destinationAddress length:sizeof(destinationAddress)];



    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:msg];



    CFSocketError socket_error = CFSocketSendData(_socket, (CFDataRef) destinationAddressData, (CFDataRef) data, 10);

    if (socket_error) {

        NSLog(@"socket error: %li", socket_error);

    } else {

        NSLog(@"sent bytes: '%@' to %@:%i", msg, host, port);

    }

}

你会注意到它传入了一个 NSArray。那是因为 Titanium 将我创建的 javascript 数组转换为 NSNumber 对象的 NSArray。我读到这是非常低效的,但它内置在 Titanium 框架中,所以我看不到解决方法,所以我希望得到一个关于如何让它在这个传入的情况下工作的答案,而不是关于如何效率低下。

当我调用新的发送方法时,它并没有发送我传入的 50 个左右的字节,而是在 Wireshark 中看到它实际上传递了超过 1000 个字节。我假设问题在于这一行的转换:

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:msg];

有人可以帮助我发送我传入的字节数组吗?谢谢!

【问题讨论】:

    标签: objective-c ios titanium nsdata titanium-modules


    【解决方案1】:
    - (NSData *)byteArray2Data:(NSArray *)array {
        NSMutableData *data = [NSMutableData data];
        [array enumerateObjectsUsingBlock:^(NSNumber* number, NSUInteger index, BOOL* stop) {
            uint8_t tmp = number.unsignedCharValue;
            [data appendBytes:(void *)(&tmp)length:1];
        }];
    
        return data;
    }
    
    - (NSArray *)byteData2Array:(NSData *)data {
        NSMutableArray *array = [[NSMutableArray alloc] init];
        [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
            unsigned char *dataBytes = (unsigned char*)bytes;
            for (NSInteger i = 0; i < byteRange.length; i++) {
                [array addObject:[NSNumber numberWithInt:(dataBytes[i]) & 0xff]];
            }
        }];
    
        return array;
    }
    

    【讨论】:

      【解决方案2】:

      是的,在这种情况下您不想使用归档程序,因为您只是想将一组字节转换为NSData 的块。根据您传入的是NSNumber 数组还是NSString 数组,您基本上需要遍历数组的内容并将数据附加到NSMutableData

      假设它是NSNumber 的数组,那么这样的东西应该可以工作:

      NSMutableData *data = [[NSMutableData alloc] initWithCapacity: [msg count]];
      for( NSNumber *number in msg) {
          char byte = [number charValue];
          [data appendBytes: &byte length: 1];
      }
      // .... code that uses data ...
      [data release];
      

      如果数字是字符串形式的数值,您可能希望使用NSString-(int)intValue 方法来提取数据,然后将其添加到数据中,基本上将上述更改为:

      NSMutableData *data = [[NSMutableData alloc] initWithCapacity: [msg count]];
      for( NSString *string in msg) {
          char byte = (char)[string intValue];
          [data appendBytes: &byte length: 1];
      }
      // .... code that uses data ...
      [data release];
      

      而且,如果您尝试从字符串中填充字符,则需要使用 [string characterAtIndex: 0] 获取字符并补偿您将收到 unichar 而不是 @987654332 的事实@。

      【讨论】:

      • 效果很好,谢谢!稍微改动一下,第一行和第二行的“args”应该是“msg”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多