2014-03-13 96 views
2

我正在处理garmin GDL90协议,它通过二进制方式将各种类型的消息发送到我的IOS设备。我正在尝试处理所有这些消息,但一直在遇到问题。具体的消息字节填充,这样,如果你曾经看到的NSData指针与参考

0x7d 0x5e0x7d 0x5d发生,你必须将它们转换为0x7d or 0x7e

我已经把我的代码了,让我发现了消息类型我解析,然后调用一个函数:

- (void) parseMessage:(NSMutableData *)message

做我的数据解析。我个人的消息解析函数调用父函数[super parseMessage:message];,它处理常见元素的解析以及处理字节填充。每个函数调用都需要一个NSData *,所以不应该在我的超级函数中进行的修改返回相同的数据?

  • 我顶层类得到一个解析的消息调用和NSMutableData指针的地址是:0x170048f10
  • 一旦我踏入父母的parseData打电话给我的地址仍然0x170048f10
  • 后,我进行修改我现在指向内存地址的数据0x17805e840
  • 一旦我从这个函数返回,但是,我回头指向0x170048f10再次输入错误的数据。

我应该使用传递引用还是其他?有什么建议么?

我有我的函数的两个变化 - unstuff1引发错误和unstuff2不起作用。

- (NSMutableData *)unstuff1:(NSMutableData *)mutableData { 
    int dataLength = [mutableData length]; 
    char *bytes = [mutableData bytes]; 

    // Scan bytes ignoring 1st and last byte because they will be 7e's 
    for (int i = dataLength - 1; i > 0; i--) { 
     bytes[i + 1] ^= 0x20; 

     if (i + 1 == dataLength) { 
      NSLog(@"Terminal character padding detected on character %d with length %d", i, dataLength); 
     } else { 
      /* Replace 2 bytes with a single byte should remove the flag when you do this */ 
      [mutableData replaceBytesInRange:NSMakeRange(i, 2) withBytes:&bytes[i + 1] length:1]; 

      dataLength--; 
     } 

    } 
    return mutableData; 
} 

- (NSMutableData *)unstuff2:(NSMutableData *)data { 

    NSMutableData *mutableData = [[NSMutableData alloc] initWithData:data]; 
    int dataLength = [mutableData length]; 
    char *bytes = [mutableData bytes]; 

    // Scan bytes ignoring 1st and last byte because they will be 7e's 
    for (int i = dataLength - 1; i > 0; i--) { 
     bytes[i + 1] ^= 0x20; 

     if (i + 1 == dataLength) { 
      NSLog(@"Terminal character padding detected on character %d with length %d", i, dataLength); 
     } else { 
      /* Replace 2 bytes with a single byte should remove the flag when you do this */ 
      [mutableData replaceBytesInRange:NSMakeRange(i, 2) withBytes:&bytes[i + 1] length:1]; 

      dataLength--; 
     } 

    } 
    return mutableData; 
} 

unstuff2很显然,我正在做一个新的MutableData所以我想这占内存地址变更(即功能我用这给了我指定的错误)。

unstuff1引发以下例外:

- [_ NSInlineData replaceBytesInRange:withBytes:长度:]:无法识别的选择发送到实例0x178250d40

终止应用程序由于未捕获的异常 'NSInvalidArgumentException',原因:' - [_ NSInlineData replaceBytesInRange:withBytes:length:]:发送到实例的无法识别的选择器

+0

你应该显示使用/与你的可变数据实例交互的代码。 – Wain

+0

如果参数是'NSData *',那么被调用的方法就不会以调用者可以看到的方式修改它(合法)(因为NSData是不可变的)。 –

+0

这就是为什么我将所有NSData *转换为NSMutableData *(虽然无法识别的选择器似乎对我来说意味着暗示) – Jeef

回答

1

好吧,看起来我跟踪了这​​个问题。我意识到编译器发出警告:

不相容指针类型初始化“NSMutableData *”与类型的表达式“NSData的*”

原来我有一些代码

NSMutableData *message = [data subdataWithRange:NSMakeRange(5, len - 5)]; 

我需要将其转换为:

NSMutableData *message = [NSMutableData dataWithData:[data subdataWithRange:NSMakeRange(5, len - 5)]]; 

然后事情全部解决。道德故事(读你的警告!!!!)

1

与语言像C++和C#(仅举两个例子),Objective C没有“通过引用传递”的概念。但是,将指针的副本传递给NSMutableData在功能上等同于按引用传递对象。也就是说,如果你将一个NSMutableData(或NSMutableAnything)传递给一个函数,并且该函数修改它,调用函数将会看到它传入的对象中所反映的变化。