Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve "redefinition of enumerator" errors from separate objc frameworks

Both the AuthNet and PayPal mobile payment libraries have the ENV_LIVE enumerator defined. This reults in Xcode errors like:

Redefinition of enumerator 'ENV_LIVE' ...

In cases like this where one cannot afford to simply change the source code of dependent frameworks, what are some workarounds available in objective-c syntax or xcode configuration?

INITIALLY:

#import "PayPal.h"
#import "AuthNet.h"
...
// AuthNet
[AuthNet authNetWithEnvironment:ENV_TEST];

// PayPal
if (STATUS_COMPLETED_SUCCESS == [PayPal initializationStatus]) {
    [PayPal initializeWithAppID:@"APP-XXX" forEnvironment:ENV_SANDBOX];
}

UPDATE (here's what I ended up using as a workaround based on the correct answer):

#import "PayPal.h"
@class AuthNet;
#import "AuthNetWorkaround.h"
...
[AuthNet authNetWithEnvironment:AUTHNET_ENV_TEST];

extern const int AUTHNET_ENV_LIVE;
extern const int AUTHNET_ENV_TEST;

@interface AuthNetWorkaround : NSObject

@end

#import "AuthNetWorkaround.h"
#import "AuthNet.h"

@implementation AuthNetWorkaround

const int AUTHNET_ENV_LIVE = ENV_LIVE;
const int AUTHNET_ENV_TEST = ENV_TEST;

@end
like image 633
pulkitsinghal Avatar asked Mar 22 '12 21:03

pulkitsinghal


2 Answers

This happens because both inclusions happen in the same compilation unit. You can work around this problem by moving the inclusion of one of the enums into a separate compilation unit, at a cost of making the values of that enumerator non-compile-time constants (in fact, they become global variables).

In pp_workaround.h:

extern const int PAYPAL_ENV_LIVE;

In pp_workaround.m:

#import "PayPal.h" // I'm completely making up the name of PayPal's header
// The import of "AuthNet.h" is missing

const int PAYPAL_ENV_LIVE = ENV_LIVE;

Now you can include "pp_workaround.h" instead of "PayPal.h", and use PAYPAL_ENV_LIVE instead of ENV_LIVE. Not everything will work the same, but the compile-time error should be gone.

EDIT If your code lets you import the conflicting headers only in your .m file, you can fix the problem (rather than working around it) by wrapping the connection code in an additional abstraction layer of your own, like this:

In the paypal_init.h:

extern void connect_paypal();

In the paypal_init.m:

#import "PayPal.h"
#import "paypal_init.h"

void connect_paypal() {
    // Use ENV_LIVE from PayPal.h here
}

in the authnet_init.h:

extern void connect_authnet();

in the authnet_init.m:

#import "AuthNet.h"
#import "authnet_init.h"

void connect_authnet() {
    // Use ENV_LIVE from AuthNet.h here
}

In your main file:

#import "authnet_init.h"
#import "paypal_init.h"

void init() {
    connect_paypal();
    connect_authnet();
}
like image 134
Sergey Kalinichenko Avatar answered Nov 19 '22 04:11

Sergey Kalinichenko


I just had this error, and a clean before building fixed the issue for me.

like image 42
Natan R. Avatar answered Nov 19 '22 04:11

Natan R.