I'm dealing with the garmin GDL90 protocol which sends across various types of messages in binary to my IOS device. I'm going through and trying to process all these messages but have been running into an issue. Specifically the messages are byte packed so that if you ever see an occurrence of

0x7d 0x5e or 0x7d 0x5d you have to convert them to 0x7d or 0x7e

I've set my code up so that I detect the message type I'm parsing and then call a function:

- (void) parseMessage:(NSMutableData *)message

to do my data parsing. My individual message parsing functions call the parent function [super parseMessage:message]; which handles both the parsing of common elements as well as dealing with my byte-stuffing. Each of these function calls takes an NSData * so shouldn't a modification made in my super function return back out the same data?

  • My top level class gets a parse message call and the NSMutableData pointer's address is: 0x170048f10
  • Once I step into the parent's parseData call my address is still 0x170048f10
  • After I make modifications to the data I'm now pointing at the memory address 0x17805e840
  • Once I return from this function, however, I'm back pointing at 0x170048f10 again with the wrong data.

Should I be using pass by reference or something? Any suggestions?

I have two variations of my function - unstuff1 throws an error and unstuff2 doesn't work.

- (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;
}

In unstuff2 obviously i'm making a new MutableData so I guess that accounts for the memory address change (that is the function i was using that gave me the error specified).

unstuff1 throws the following exception:

-[_NSInlineData replaceBytesInRange:withBytes:length:]: unrecognized selector sent to instance 0x178250d40

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSInlineData replaceBytesInRange:withBytes:length:]: unrecognized selector sent to instance

有帮助吗?

解决方案 2

Ok looks like I tracked down the problem. I realized the compiler was sending out warnings:

incompatible pointer types initializing 'NSMutableData *' with an expression of type 'NSData *'

It turns out I had some code

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

Which i needed to convert into:

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

And then things all work out. Moral of the story (read your warnings!!!!)

其他提示

Unlike languages like C++ and C# (just to name two), Objective C has no concept of "pass by reference". However, passing a copy of a pointer to your NSMutableData is functionally equivalent to passing the object by reference. That is, if you pass in an NSMutableData (or NSMutableAnything for that matter) to a function and that function modifies it, the calling function will see the changes reflected in the object that it passed in.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top