0

Here is the problem: I am passing a pointer to an object to performSelector:withObject via [NSValue valueWithPointer:] for example like this:

// GVertex is NSObject subclass
GVertex *vertex = [[GVertex alloc] initWithX:5.0f andY:4.5f]];
GVertex **vertexPtr = &vertex;
// later in code when I need to process the vertex
[self performSelector:@selector(processVertex:) withObject:[NSValue valueWithPointer:vertexPtr]];

then in my processVertex:(NSValue *)vertexValue method I want to get the passed vertex and I do it like this:

- (void)parseVertex:(NSValue *)vertexValue
{
    GVertex *vertex = (GVertex *)[vertexValue pointerValue];
    ...
    [vertex setFlags:32]; <<-- This gives me EXC_BAD_ACCESS
    ... 
}

I have tried many combinations of (*) and (&) everywhere but can't get it to work. What am I doing wrong ? Thanks.

iska
  • 2,208
  • 1
  • 18
  • 37
  • Have you run zombies on this code? It might be helpful if you see what's being messaged. – Dustin Aug 12 '12 at 19:01
  • 2
    It is hard to imagine why you need to wrap **an object** in an NSValue as a `pointerValue` to be passed as an argument. That has quite a bit of a "code smell" about it. – bbum Aug 13 '12 at 02:06
  • @bbum Yes, it looks that way. I am writing a parser for a custom data format, and it requires multiple instances of `GVertex` objects in several different areas of the code. By passing a pointer, the changes in the `processVertex` method get reflected in all those local calling methods. This way my code got much more compact :) – iska Aug 13 '12 at 02:55
  • Pass by reference like that breaks encapsulation and is extremely fragile. Much better to either make the vertices mutable or to encapsulate them in something else. – bbum Aug 13 '12 at 03:29

2 Answers2

2

Why don't you just pass your vertex object:

[self performSelector:@selector(processVertex:) withObject:vertex];

and change your method declaration to:

- (void)parseVertex:(GVertex *)vertex {
     [vertex setFlags:32];
}
Adam
  • 26,549
  • 8
  • 62
  • 79
  • This would be an alternative but not the solution to the problem. With the current implementation the code would end up much more complex and it will be at least 4-times as large. Besides, for design and flexibility reasons, I don't want to do that. Thanks anyway :) – iska Aug 12 '12 at 18:57
1

The pointer you're putting into the NSValue is a pointer to a pointer (or the address of a pointer), but you're retrieving it as if it's a plain object pointer. Moreover, the pointer whose address you're taking is a local variable -- that address is going to be garbage in the context of a new method.

This should work if you just store the (single) pointer in the NSValue:

[self performSelector:@selector(processVertex:) withObject:[NSValue valueWithPointer:vertex]];

Beware of memory management issues, however -- NSValue does not copy or take ownership of the memory at that pointer.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • thanks for the answer, it solved it. However I have another question if it's ok with you. What am I passing if I do it like this: [self performSelector:@selector(processVertex:) withObject:[NSValue valueWithPointer:&vertex]]; I mean with the "&" before the vertex variable ? – iska Aug 12 '12 at 23:02