Question

I'm converting to ARC, and can't find any way to get rid of this compiler error without breaking the code as well.

I need to pass 2 objects into a selector so I add them both to an array as shown below and send that array to the selector:

LWPagerContent* content = nil;
NSArray* args = [NSArray arrayWithObjects:article, [NSValue valueWithPointer:&content], nil];

[self performSelectorOnMainThread:@selector(initArticlePagerContent:) withObject:args waitUntilDone:YES];

This method accesses the array, but needs to modify the object at the address referenced in the array. It should initialize the LWPagerContent object as shown, and then that object will be used by the original method that called performSelector.

- (void)initArticlePagerContent:(NSArray*)args {
Article* article = [args objectAtIndex:0];

LWPagerContent** contentPtr = [[args objectAtIndex:1] pointerValue];
*contentPtr = [[NSClassFromString([StyleSheet articleContentClass]) alloc] initWithArticle:article];

}

This works fine, but when I try to convert to ARC I'm immediately told that "Implicit conversion of a non-Objective-C type 'void *' to 'LWPagerContent *__strong *' is disallowed with ARC". This error occurs on the line that starts with "LWPagerContent **..." (2nd to last one shown above). I've tried using __bridge and __autoreleasing as recommended in other posts, but nothing seems to work. Any suggestions greatly appreciated.

Was it helpful?

Solution 2

Compiler doesn't know what to do with your raw pointer. You should explicitly state what kind of memory managing strategy you expect. In you case it can be something like

LWPagerContent * __strong *contentPtr = (LWPagerContent * __strong *)[[args objectAtIndex:1] pointerValue];

The type is "pointer to a strong pointer to LWPagerContent". From now *contentPtr will be treated as a strong pointer by ARC.

OTHER TIPS

Use a block to go to the main thread, eliminating the meta-programming implied by the -performSelector: call.

Then use a callback to set the generated content.

I.e.

dispatch_sync(dispatch_get_main_queue(), ^{
    LWPagerContent *newContent = ... do something ...
    [self setPagerContent:newContent];
});

Some notes:

  • methods should not be called init... unless they are initializers

  • pass-by-reference is generally to be avoided

  • meta-programming undermines the compiler's ability to do sanity checks. Avoid it.

Have you tried:

NSValue* contentPtrPtr = [args objectAtIndex:1];
LWPagerContent** contentPtr = [contentPtrPtr pointerValue];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top