App with Danish payment system Mobile-pay (Swift/Objective-c) [duplicate] - ios

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;
}

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.

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.

__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.

Related

Xcode 8 no warning for assigning NSString to NSInteger?

I'm not sure when this started but it seems like Xcode is not giving me type mismatch warnings/errors like it used to. For example, I just discovered a bug in my code where I was assigning the result of a method that returns NSString * to an NSInteger. The method prototype is correctly defined but the compiler gave no warning. Here is the code:
+ (NSString *)countryDialPrefix;
NSInteger prefix = [CountryCodes countryDialPrefix];
Here are the warnings set for all languages:
This was in "Other Warning Flags" at the Project level:
-w -Xanalyzer -analyzer-disable-checker -Xanalyzer unix
So I removed the -w and that fixed it.

Duplicate symbol error with GoogleCast.framework

I just started porting an Android app to iOS, and am hitting a major roadblock that I can't figure out despite scouring many similar questions.
I am attempting to follow the pattern implemented in the CastVideos sample where the GoogleCast API is encapsulated in a singleton class which I've called CastManager. To use my singleton class, I #import "CastManager.h" in AppDelegate.m. Then in CastManager.h, I #import <GoogleCast/GoogleCast.h> so that I can use classes and protocols from it as part of CastManager's public interface. However, because I'm importing CastManager.h in both CastManager.m and AppDelegate.m, the linker is finding duplicate symbols from the GoogleCast framework.
This is my CastManager.h:
#import <GoogleCast/GoogleCast.h>
#import <Foundation/Foundation.h>
#interface CastManager : NSObject
#property(nonatomic, strong) GCKDeviceScanner *deviceScanner;
+ (instancetype)sharedCastManager;
#end
And corresponding CastManager.m:
#import "CastManager.h"
#implementation CastManager
+ (instancetype)sharedCastManager {
NSLog(#"sharedCastManager");
static CastManager *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
}
- (instancetype)init {
NSLog(#"init()");
if (self = [super init]) {
self.deviceScanner = [[GCKDeviceScanner alloc] init];
}
return self;
}
#end
And this is the main part of my AppDelegate.m:
#import "AppDelegate.h"
#import "CastManager.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CastManager *castManager = [CastManager sharedCastManager];
return YES;
}
However, this results in the following error from the linker when attempting to build the project:
duplicate symbol _kGCKDeviceCapabilityVideoOut in:
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/AppDelegate.o
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/CastManager.o
... many similar errors ommitted for brevity ...
duplicate symbol _kGCKDeviceCapabilityAudioIn in:
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/AppDelegate.o
/Users/nate/Projects/MyCastApp/GoogleCast.framework/GoogleCast(GCKDevice.o)
ld: 8 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As far as I can tell, this exactly copies the pattern as defined in the CastVideos sample, but the sample compiles fine, and mine doesn't, and I've scoured through both projects trying to find what is different, but I just don't see it. Further, I don't see anything really wrong with doing this, and would expect it to work fine. I can't think of any other way to do it, really.
Here are the relevant files from the CastVideos sample for comparison:
ChromecastDeviceController.h
ChromecastDeviceController.m
AppDelegate.m
Other questions point to solutions that don't apply or don't fix it:
I'm not importing a .m file on accident.
I don't have duplicate references to any files in the project.
The "Compile Sources" section of the "Build Phases" project setting doesn't include any duplicates.
I've added the '-ObjC' linker flag as described by the GoogleCast API docs, though it has the same error with or without it.
I've tried deleting the delegate data and doing a clean before building.
This is with Xcode 6.3.1 running on OS X Yosemite 10.10.3 and the GoogleCastSDK-2.6.0 package from the SDK documentation page
I have checked in my sample project with the problem at https://github.com/nshafer/MyCastApp
Any help is greatly appreciated!
Edit: the duplicate is somewhat related, it's definitely about the same symbols, but the answers there didn't help, as I'm not using Object-C++, but rather just Objective-C. I don't have a .mm file, just a .m file.
For me it helped to switch the "No Common Blocks" compiler setting to NO:
It pretty much seems to make sense, the setting is explained here: What is GCC_NO_COMMON_BLOCKS used for?
The linker tells you that you have a variable named kGCKDeviceCapabilityVideoOut in two files, AppDelegate.m and CastManager.m. Since it's not in your source code, it's most likely in the GoogleCast code that you are including.
Either change the GoogleCast.h file, or make sure it is only included in one .m file. Including it from CastManager.h means it is indirectly included in every file that includes CastManager.h, so I would avoid that and only include it from CastManager.m. You'll probably have to add
#class GCKDeviceScanner;
in your CastManager.h file.
I found another fix, which is to edit GCKDevice.h in the GoogleCast.framework/Headers folder. Change the 4 constants from GCK_EXPORT to GCK_EXTERN near the top of the file.
/** Device capability flag for video out. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityVideoOut;
/** Device capability flag for video in. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityVideoIn;
/** Device capability flag for audio out. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityAudioOut;
/** Device capability flag for audio in. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityAudioIn;
I detailed this in a bug report I filed with Google's issue tracker, but it was marked as a duplicate of another somewhat related issue. Either way, it will perhaps get fixed in the next version. Until then, I would suggest going with changing the "No Common Blocks" setting as detailed in Joobik'com's answer, as that doesn't involve changing the 3rd party code.

iOS static library, cannot access some class methods

I'm building a static library in iOS. after importing that library in my project, I added -ObjC in Other linker flags. But when I call the class methods(currently 3 available), 2 of them are being called and executed properly, but the last one is getting this error: "+[RankConferenceLib joinConferenceWithName:]: unrecognized selector sent to class 0x5044dc".
This is my Header file of library
#interface RankConferenceLib : NSObject
+(void)initEnvironment;
+(void)orientationChange;
+(void)joinConferenceWithName:(NSString *)name;
#end
in .m file of library
+ (void)joinConferenceWithName:(NSString *)name
{
//....codes
}
and in my project I'm calling them
- (IBAction)join:(UIButton *)sender {
[RankConferenceLib joinConferenceWithName:#"User"];
}
Please tell me what I'm missing here. This is my first static library. I've searched but could not find any help which is similar as my situation here. Please mention what else you need to know.
Thank you.
I have checked this and for me it's working fine without any linker flags added.
The only one error possibility is something happened inside the + (void)joinConferenceWithName:(NSString *)name
Write a log inside the joinConferenceWithName to printout the parameter name and make sure this is calling and the problem is occurring inside that method.
+ (void)joinConferenceWithName:(NSString *)name
{
NSLog(#"the name is: %#", name);
}
Finally, make sure that you added the latest modified static library into your project.
You can download the working sample from here
Try Running using the -all_load linker flag
Apple Documentation
Stack Overflow Answer

iOS writing unit tests for a library

I'm writing a library that adds syntactic sugar to native iOS framework functions. As such, I am extending native types such as NSString and NSArray. For example:
#implementation NSString (NPB)
-(BOOL) includesCharsInString: (NSString *)charsInString
{
NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:charsInString];
return [self rangeOfCharacterFromSet:charset].location != NSNotFound;
}
#end
In my test framework I include the extended .h files and have the library as a target dependency, and also link against it. However, when I write a test against the library, the tests fail with "unrecognized selector sent to ..." error.
If I include the appropriate .m file in the compile sources list, then it works fine. But if I'm linking against the library, why would I need to do that?
Since the linker can't find any usage of category code, they are, by default, stripped when linking against libraries. In your build settings, add -ObjC to your linker flags.

CF_IMPLICIT_BRIDGING_ENABLED non-functional in xcode5?

The WWDC 2013 lecture slides contain a section that in some cases the explicit bridging casts can be omitted. I wrote this in Xcode 5 (using 10.8 though, not 10.9), and the compiler complains I need a bridging cast. Am I just totally not understanding the concept?
#import <Foundation/Foundation.h>
CF_IMPLICIT_BRIDGING_ENABLED
CFStringRef MyCreateStringFromNothing();
CF_IMPLICIT_BRIDGING_DISABLED
void SomeFunction() {
// compiler requires bridging cast here...
NSString* x = MyCreateStringFromNothing();
}
The reason I ask is I wanted to write:
NSString* s = CFUUIDCreateString(NULL, uuid);
and thought that the new work on implicit bridging should simply enable me to write this. But this also needs a bridging cast.
This appears to be sort of black magic, but from my experiments functions with "Create" in them don't work with implicit bridging.
When I compiled this:
CF_IMPLICIT_BRIDGING_ENABLED
CFStringRef MyCreateStringFromNothing();
CFStringRef MyGetStringFromNothing();
CF_IMPLICIT_BRIDGING_DISABLED
void SomeFunction() {
NSString *const fails1 = MyCreateStringFromNothing();
NSString *const fails2 = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("FOO"));
NSString *const works = MyGetStringFromNothing();
}
The first two fail but the third one "works."
Note that implicit bridging apparently STILL does NOT actually keep the compiler from warning you about converting CFStringRef to NSString *, it just stops requiring you to insert a __bridge as well.
You'll notice that in slide at WWDC2013 in session 404 at 50:30, he uses CFDictionaryGetValue(), which returns a "void *", so it's one of the few functions that won't raise a warning. Any of the CF functions that return an actual type (e.g. CFStringRef, or CFDictionary) are still going to throw warnings, so, meh.
Check the compiler settings on the project and/or target. If this is an older project, you might have a stray option there causing you to use an older compiler. (This tripped me up a few times when I moved to Xcode 5 and wanted to use the latest Obj-C newness.)
These days, I always choose "Default compiler" in my build options.

Resources