Adding (Objective-C) code to my game

does any one know how I could add Amazon Mobile Ads SDK to my app ? they use cocoapods for iOS, but im not sure how to go about doing this or where to implement the objective-c code (They don’t have a c++ SDK) would it be in the AppController files or RootViewController?

The easy way to implement Obj-C code is add cpp header and obj-c code files:
Amazon.h:

class Amazon {
public:
//1!
bool someAmazonMethod(bool someParam);

//2!
bool someComplexMethod(int someParam);

//3!
void someMethodWithObjCBlock();
void setSomeCallback(const std::function<void(void)> &callback);
private:
//3!
std::function<void(void)> m_callback;
};

and Amazon.mm

#include "Amazon.h"
#import "Some Obj-C framework.h"

//2!
@interface objcHelper: NSObject  {
    
}
+(objcHelper*)sharedInstance;
+(void)dispose;
-(BOOL)someMethod(int someParam);

@end

@implementation objcHelper

static objcHelper* m_objcHelper = nil;

+(objcHelper*)sharedInstance {
    if (nil == m_objcHelper) {
        m_objcHelper = [[objcHelper alloc] init];
    }
    return m_objcHelper;
}

+(void)dispose {
    [[objcHelper sharedInstance] removeObserver];
}

-(BOOL)someMethod(int someParam) {
   return [someFramework someMethod: someParam];
}

@end

Amazon::Amazon():m_callback(nullptr) {

}

Amazon::~Amazon() {
  [objcHelper dispose];
}

//1!
bool Amazon::someAmazonMethod(bool someParam) {
   return [SomeFramework someMethod];
}

//2!
bool Amazon::someComplexMethod(int someParam) {
  objcHelper* helper = [objcHelper sharedInstance];
  return [helper someMethod: someParam];
}

//3!

void Amazon::someMethodWithObjCBlock() {
  someObjCObject.onSomeServiceAutenticationComplete = ^(void) {
        if (nullptr != m_callback) {
            m_callback();
        }
    };
   [someObjCObject autenticateUser];
}
void Amazon::setSomeCallback(const std::function<void(void)> &callback) {
  m_callback = callback;
}
  1. The easy way - just call some obj-c method on some obj-c object. Return Result;
  2. Sometime compiler wont let to use complex obj-c classes or you need more complex logic (f.e. if framework requires set some delegate methods), then you can use obj-c singleton technique;
  3. If you need to receive some delayed results (from server, long calculations etc), which implement via obj-c block, you can call your c++ std::function inside block body and pass some return params;

I think thats all you need to know to implement almost any obj-c framework in cocos2d-x game.

4 Likes

thank you very much!!

This is the best response to this question I have ever seen. It’s simple and clean.

1 Like

quick question do .mm files compile for android ? I want to do something like this in my game scene

void HelloWorld::ShowInterstitial()
{
if(ios){
// call objective-c method from objective-c class that loads interstitial
}
if(android){
// call java code with jni
}
}

Use an #ifdef instead

1 Like

Ok but will .mm compile in android studio ?

I will not.

See my example for runtime permission (mainly Android). This uses different files in the Classes folder for different platforms. You have to go this way…

How would it be possible then to compile my helloworld scene(where all my gameplay is) on Android, if I have to call an objective-c method in that class, but in order to do that it has to be .mm?

.mm file compiled on iOS or Mac.
Move code that you need to C++ and use it for all platforms except web.

fellow cocos2d-x member helped me with this solution
Well - it is abstract class involved here:

  1. some PlatformProtocol.h
class PlatformProtocol {
public:
virtual void doInAppPurchase() = 0;
};

then, Platform-android.h:

#include "PlatformProtocol.h"

class Platform: public PlatformProtocol {
public:
virtual void doInAppPurchase() override;
};

Platform-android.cpp:

#include "Platform-android.h"

Platform::doInAppPurchase() {
//do android code stuff here
}

then, Platform-ios.hpp:

#include "PlatformProtocol.h"

class Platform: public PlatformProtocol {
public:
virtual void doInAppPurchase() override;
};

Platform-ios.mm:

#import "Platform-ios.h"

Platform::doInAppPurchase() {
//do ios obj-c code stuff here
}
  1. And then,
    Platform.h:
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
#include "Platform-ios.h"
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
#include "Platform-android.h"
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
//class for win32
#elif CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
//class for linux
#endif
  1. And in your source code:
#include "Platform.h"

Platform *p = //new, getInstance, watever you declare in PlatformProtocol and implemented 
//in Platform class, and then
p->doInAppPurchase();

It’s way too much header files. Did you see my example on github? I use one header file and one cpp file for each platform. So you don’t need an abstract class.

2 Likes

yes i looked at it but I don’t see the code to determine if its ios or android ? and no .mm file ?
I need a .mm file in order to call objective-c method, but .mm file will not compile on android so that is the problem im facing , im trying to see how I could make it work with your example @mars3142 do i need to include these statements anywhere in your code ?

#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
#include "Platform-ios.h"
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
#include "Platform-android.h"

Why should I use this preprocessor statements within the header file?

I included only the platform depending file within the build configuration. For Android you will see it in the Android.mk file - today I use cmake for that, but that’s similar. In XCode I only include my iOS file - it could be a cpp or mm file.

Look everywhere in the cocos source. They are using this scheme for every platform specific code. It’s best practice of doing it this way.

2 Likes

when you say “in Xcode I only include my iOS file” is there an equivalent do android.mk ? or where do you inlcude the permission-ios.cpp at since you have all these in your classes folder ?
[Permission-android.cpp]
[Permission-desktop.cpp]
[Permission-ios.cpp]
[Permission.h]