iOS 5: Make NSString Category include NSCFConstant

2019-01-25 08:43发布

问题:

I have an NSString category class (NSString+URLEncoding.h). I am running into and unknown selector crash, because the string I am calling the category method has been optimized into an NSCFConstantString by iOS.

-[__NSCFConstantString URLEncodedString]: unrecognized selector sent to instance 0x290174

I learned of the NSCFConstantString vs. NSCFString optimizations in iOS 5 from: http://www.cocoanetics.com/2012/03/beware-of-nsstring-optimizations/

Is anyone aware of how I can get the NSString category to include the Constant strings or even force the var to be an NSString/NSCFString and not an NSCFConstantString?

Cheers, Z

-edit-

  • Linker flags -ObjC -all_load are both already implemented
  • NSString+URLEncoding.m is included in the targets compile sources
  • NSString+URLEncoding.m implements the URLEncodedString method.
  • Checked for zombies.

I am adding a sharing service to ShareKit 2.0

header:

@interface NSString (OAURLEncodingAdditions)

- (NSString *)URLEncodedString;

implementation:

@implementation NSString (OAURLEncodingAdditions)

- (NSString *)URLEncodedString 
{
    NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                           (CFStringRef)self,
                                                                           NULL,
                                                                           CFSTR("!*'();:@&=+$,/?%#[]"),
                                                                           kCFStringEncodingUTF8);
    [result autorelease];
    return result;
}

回答1:

There's an issue with the linker that can cause its dead-code stripping to completely omit any object files that only contain obj-c categories (or that are otherwise unreferenced). Theoretically passing the -ObjC flag to the linker should fix this, but that doesn't seem to always work. You can work around this issue by providing the -all_load linker flag, which will cause the linker to always link in all object files.

Note that you might have to set -all_load on the parent project if your category is part of a sub-project or library that you-re including somewhere.

Update: I believe -ObjC is reliable now and has been for years so you can stop using -all_load for this issue.



回答2:

Just spent 30 minutes figuring out exactly the same issue. After fiddling with linker I found out that the category wasn't present in Compile Sources list in my target's Build Phases. Be sure to check it's there.



回答3:

__NSCFConstantString is a subclass of NSString, so any categories on NSString apply to __NSCFConstantString too.

Either you're not linking in your category, or your category doesn't define a URLEncodedString method in its @implementation.