Accessing forwardInvocation'd methods with ARC

2020-06-26 05:23发布

问题:

I'm writing a clone of OpenStruct in Objective-C, using forwardInvocation:. However, the compiler isn't aware of the forwarding at compile time apparently. Compiling with ARC gives me a ton of warnings.

The code is open source and available on Github, but is currently compiled with -fno-objc-arc. If anyone could take a look at how I could make this ARC compatible, I'd greatly appreciate it.

回答1:

I tried this code:

OpenStruct *myStruct = [[OpenStruct alloc] initWithDictionary:myDictionary];
NSLog(@"%@ says %@", @"Cow",  [myStruct cowSound]);

I get warnings or errors with and without ARC, with LLVM 3.0 or LLVM GCC 4.2. I think you've misunderstood that forwardInvocation: still requires the method to be declared at some level, if only in a category (@interface) of the class you're sending the message to.

For example, when you do:

[someObject doSomething];

Then this will always generate at least a warning ("someObject may not respond to doSomething") if doSomething is not declared anywhere, regardless of whether the someObject class implements forwardInvocation or not. Like you noticed, the compiler is indeed not aware of the forwarding, and it also can't rely that your implementation of forwardInvocation guarantees message delivery. With LLVM 3.0 with or without ARC this may have been changed to generate an error instead, because ARC's development goal was to err on the side of more compiler errors rather than runtime issues.

Now you can still send messages to an object that doesn't implement a method. For example by using Objective-C runtime method objc_msgSend or via NSInvocation. But that voids the simple to use interface that you were planning to create.

Btw, your usage example for OpenStruct does not really justify why it is any simpler to access the dynamic struct via messaging compared to simple accessors like [struct getValueForKey:@"moo"]; … if you think this over then [struct moo] gives users little or no benefit over the first approach. The "moo" method is dynamic either way (a string or forwarded message) and a typo won't be caught at runtime.