1

Some background... I am writing code that interacts with javascript via a ObjC-JS bridge utilizing UIWebView's stringByEvaluatingJavaScriptFromString:. The idea is that the "brains" of the app be in JS which tells Objective-C how to behave. There are multiple benefits to this like reduced binary size, flexible updates, etc. However, there is a case where there is some Objective-C only object that the JS needs to have a reference to (JS instructs ObjC when to use/remove the object). This is being done by placing the native object in a dictionary with a unique identifier which can be passed as a string to JS (over the bridge). My problem stems with coming up with a nice identifier for said native Objective-C object.

Thus, I am trying to convert a reference to an object to a string with no luck. This is what I have:

// anObject is a custom class
NSValue *handle = [NSValue valueWithPointer:(__bridge const void *)anObject]; 
NSData *data = [NSData dataWithValue:handle];
NSString *stringHandle = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

The dataWithValue: function (taken from this SO post):

+ (NSData *)dataWithValue:(NSValue *)value {
    NSUInteger size;
    const char* encoding = [value objCType];
    NSGetSizeAndAlignment(encoding, &size, NULL);

    void* ptr = malloc(size);
    [value getValue:ptr];
    NSData* data = [NSData dataWithBytes:ptr length:size];
    free(ptr);

    return data;
}

Walking through it in the debugger shows me a nil value for stringHandle:

enter image description here

What am I doing wrong?

Community
  • 1
  • 1
Stunner
  • 12,025
  • 12
  • 86
  • 145
  • I really have no idea what are you doing. What is your expected result? How are you going to convert `0x10bc992a0` to string? – Bryan Chen Mar 04 '14 at 04:35
  • 4
    A memory address -- or any other chunk of arbitrary data -- isn't very likely to be valid UTF-8 data. You're trying to get a string containing the pointer value? The address of the original object? That's just `[NSString stringWithFormat:@"%p", anObject];` – jscs Mar 04 '14 at 04:37
  • What you are doing isn't really a great idea. Is "anObject" a known type or any random type? It's already been pointed out that it could be any arbitrary data that isn't necessarily UTF-8. If "anObject" is derived from NSObject, you could always create your version of - (NSString *)description to generate a string that represents the object. – Mobile Ben Mar 04 '14 at 04:43
  • @BryanChen I don't know, you tell me. ;) – Stunner Mar 04 '14 at 04:43
  • @Stunner you are the one asking the question and you don't know the question? i.e. your expected result? – Bryan Chen Mar 04 '14 at 04:44
  • @JoshCaswell Is it recommended I go about storing references via NSValue though? Or is that only for use with collection classes? I have used NSValue to store pointers to objects before, that is why I chose to pursue that route this time. – Stunner Mar 04 '14 at 04:45
  • @MobileBen `anObject` is indeed derived from NSObject and is a known type. – Stunner Mar 04 '14 at 04:46
  • That would depend heavily on what you're planning to do. In general, I think you would just pass the original pointer around. – jscs Mar 04 '14 at 04:49
  • The problem with your strategy is you are essentially getting a "snapshot" of memory. You're converting that byte stream into an NSData object. The approach is based on what you want your desired outcome. For example, if you want a descriptive string, implementing description will do it. I am assuming at this point, you want to handle more than one custom object? Since this is your code you could also always create a class or make the object use a protocol to support a specialized method which outputs things a special way. – Mobile Ben Mar 04 '14 at 04:53
  • BTW, you got the nil because it could not convert the byte data into an NSString ... which I sort of described in my last comment. – Mobile Ben Mar 04 '14 at 04:55
  • Does the use of the phrase "handle" come from experience on a different platform? Are you mixing Objective-C with other languages? – Walt Sellers Mar 04 '14 at 06:04

2 Answers2

3

What you're doing wrong is trying to treat an address as if it's a UTF-8 encoded string. An address -- or any other chunk of arbitrary data -- isn't very likely to be valid UTF-8 data. (If by chance it were, it still wouldn't be the string you expect.)

If you're trying to get a string containing the pointer value, i.e., the address of the original object, that's just [NSString stringWithFormat:@"%p", anObject];

If you really need to do it from the NSValue, then replace anObject with [theValue pointerValue].

If you want to pretty-print arbitrary data, see How to convert an NSData into an NSString Hex string?

Community
  • 1
  • 1
jscs
  • 63,694
  • 13
  • 151
  • 195
0

You can get a string representation by calling the NSObject method "description". You can override the "description" method in a subclass if you need.

An NSValue of a pointer will be an object holding the 4 bytes of the 32-bit pointer. It will not hold any of the data pointed to in RAM.

Walt Sellers
  • 3,806
  • 30
  • 35