2014-03-13 130 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)傳遞給一個函數,並且該函數修改它,調用函數將會看到它傳入的對象中所反映的變化。