ios native create event listener in objective-c

I have built an iOS project with Native, using Xcode, incorporating OpenEars for speech recognition. Not as a plugin, just as routines. 

I pass events successfully from the objective-c to my Lua code, all works fine.

What I want to do is pass information back, preferably with raising events that are then caught by my objective-c code.

Is that possible? I don’t see anything useful in the API documentation (or the forums) for creating an event listener in Objective-C, though Objective-C is essentially an event-driven environment. 

Anyone know how to do this – listen for and receive events in Objective-C that have been raised by Lua?

All the documentation seems to be about creating plugins, not enough about just writing Native apps without plugins.

I might be completely not understanding what you need so I’ll state the statement first:

Fire an event in Lua that calls a method in Object-C

First I would just create an event in Lua. This is a button but it could be a timer or whatever.

button:addEventListener("touch", launchSkillZ)

Then will call the code the lua code:

if event.phase == “began” then

showSkillzUI()

end

Show showSkillzUI is a Object-C call:

const luaL\_Reg kVTable[] = { { "init", init }, { "showSkillz", showSkillz }, { "randomNumber", randomNumber }, ... };

The actual method. Notice I am also making a call to Fabric to record the event.

int CoronaSkillZ::showSkillz( lua\_State \*L ) { [[Skillz skillzInstance] launchSkillz]; [Answers logContentViewWithName:@"Skillz UI" contentType:@"External View" contentId:@"SKLZ-001" customAttributes:@{}]; return 0; }

Let me know if this helps.

Not exactly what I had in mind, but it might fit, let me see if I understand.

First, what I had in mind is direct catching of the event in Objective-C – the event listener in Lua irrelevant. As far as I can tell, your example does not do that, you use an intermediary event listener in Lua that then calls the Objective-C. I wanted to create an event listener in Objective-C that can directly receive a Lua event.

But your approach would work fine, if I could understand it, as long as it does not depend on the ‘plugin’ setup. What I do not understand in your code: it seems that the Lua function call showSkillzUI() is picked up by a function call showSkillz on an instance of CoronaSkillZ. How is that mapping happening? Is that just a typo, and the function call in C should be called showSkillzUI, or does appending UI somehow tell the delegate that it is an Objective-C call? I assume not, so am a bit confused.

But even setting aside the name difference, how does the Lua delegate know which showSkillz function to call, that function name could be on many different classes, thus on several instances, and it could be a Lua function name, right? Isn’t it scoped to just CoronaSkillZ, or am I not understanding Objective-C scoping?

I also don’t understand what this line is doing:

    [[Skillz skillzInstance] launchSkillz];

Sorry for the naive questions, I am a beginner in Objective-C.

  1. The difference between the two is a typo. Or a copy and paste error. 

  2. Skillz is eSport api provider. So that launchSkillz launches their UI. My game sixteen dots on ios uses it:  These type of eSport games are not allowed on Google so the Play version is not integrated.

  3. I don’t know of any mechanism that firing an event in Lua would trigger an event immediately in object-C. I have in the past created a generic proxy class that would just translate events between two worlds, but that would still depend on the Lua events on the Lua side.

  4. I also don’t understand what you mean about the plug-in infrastructure. The coronaskillz is just a class /header file combo and i don’t have a “plugin for this”, but it uses the same infrastructure. I still reference the CoronaRuntime.h library.

In any case, I’ll try to create a simple project either today and tomorrow to demonstrate what I do. Then you can decide if this is the approach you want to take.

Thank you, that makes sense, I think I understand, but there is something missing for me still.

With the typo fix, I still don’t understand how you specify in Lua which function call you are calling. Is showSkillz a global function? How was it declared to be a global function so that Lua can call it without context? That is the key point I am missing.

When using the plugin examples, the flashlight example, I have to call flashlight.on() so that on() has the context of the flashlight object. When you call showSkillz, you are not giving any object context, how does the app know what object that function belongs to, where to find it, unless you have declared it ‘global’ in some way?

On the lua side all I have to reference is the library.

local library = require "FireMethodFromLua"

Since unless you create the .lua file the simulator will throw an error I wrap the entire thing:

if system.getInfo("environment") == "device" then local library = require "FireMethodFromLua" timer.performWithDelay( 1000, function() library.doSomeWork( ) end ) end

In the example “doSomeWork” does nothing. But if you put a breakpoint in the xcode portion where it is supposed to fire it will break there.

Got it. Thank you for the example, I was looking for the CORONA_EXPORT, I thought that is what I needed.

I notice you do have the plugin files, but you said you don’t need it. But I know that build.sh blows up if you don’t have that. Is this the simplest needed, with the PluginLibrary included but not used? I ignore the PluginLibrary in my project also, but would be nice to just remove it.

Thank you again, I can make it work from here, I am pretty sure.

Sorry, I think you can clean up further. I did it quickly. Let me see what else I can remove. BRB.

I deleted the files and it still works. What is build.sh? I just plug in my phone and press the play button in xcode to test and the archive and upload to apple when ready. Delete it from your project you don’t need it. Tell me what error you get.

Sorry, my fault, you are correct. I deleted the files previously without deleting them from the project, I guess. Anyway, deleted them, still works. Having a bit of trouble calling a routine, but something in my code I am still tracking down. Because OpenEars is in the ‘other’ style (@implementation…), I have to translate everything to that format, but I am getting there. Thanks so much for your help.

thank you. I wanted some way to speak the Spanish words in my word search app. Recording 14,000 words weren’t going to happen even between my mom (she is always willing to help) and me. I think I can use this API to say them.

I am having trouble converting from one format to the other. I don’t know at this point which to commit to. 

When I use the @class IGOEController then I have to convert all the OpenEars routines which are written in the @implementation format. I can covert the simple ones, but how do I convert this:

-(void) pocketsphinxDidReceiveHypothesis:(NSString *)hypothesis recognitionScore:(NSString *)recognitionScore utteranceID:(NSString *)utteranceID {

This uses named parameters, and I don’t see how to duplicate that in the C-style function calls. 

If I convert the other way, it does not seem to recognize my functions. Particularly, this structure fails:

    // Functions in library

    const luaL_Reg kVTable[] =

    {

        { “loadOE”, loadOE },

         { “sttOn”, sttOn },

         { “sttOff”, sttOff }

        { NULL, NULL }

    };

The compiler says ‘Use of undeclared identifier’ for each routine, meaning it does not see the routine declarations:

  • (void)sttOn:(lua_State *)L {

    NSLog(@“turn on OE”);

}

  • (void)sttOff:(lua_State *)L {

    NSLog(@“turn off OE”);

}

  • (void)loadOE:(lua_State *)L {

I’ll keep digging into how to do each in the other format, but let me know if you have a recommendation. 

It still seems like so much extra coding to connect to a Lua listener (I only ever raise events with simple calls, not using listeners). I just wish there were a simple way to declare an Objective-C function an event listener, as simple as it is in Lua. Oh, well. 

Why are you converting them? Put a reference to the header file on the top and call them. If there is something that needs to be implemented. Create object C classes and implement them there then add the header file to your file and call it. I think you are making this a lot more complicated than it needs to be, but I might be missing something obvious.

Import:

#import \<Skillz/Skillz.h\>

Call it:

 [[Skillz skillzInstance] initWithGameId:@"xxx" forDelegate: skillzDelegate withEnvironment:SkillzProduction allowExit: YES];

If you need to implement something in object C you can do it either in a separate file or include it in the file. Above call requires a SkillzDelegate. The entire delegate is sitting in the C++ file:

// // Skillz // @interface SkillzDelegate : NSObject\<SkillzDelegate\> @end @implementation SkillzDelegate - (void)tournamentWillBegin:(NSDictionary \*)gameParameters withMatchInfo:(SKZMatchInfo \*)matchInfo { } - (void)skillzWillExit { // This code is called when exiting the Skillz portal //back to the normal game. } - (SkillzOrientation)preferredSkillzInterfaceOrientation { // return SkillzPortrait for portrait based applications // return SkillzLandscape for landscape based applications return SkillzLandscape; } @end static SkillzDelegate\* skillzDelegate = [[SkillzDelegate alloc] init];

If I understand you correctly, build a bridge from the Lua-C code to the OpenEars C++ code? Call the Lua-C code from Lua the way it all works, and then from that routine, call the C++ routine that I want called. Is that right? The Lua->C routines then sit between the Lua calls and the OpenEars routines? So making a direct Lua -> C++ routines is not a good idea, because of too many conversions, right?

Thank you! It all works now, that was the perfect suggestion, and much simpler than what I was trying to do. 

I still think it would be brilliant if Corona could set up to allow C or C++ routines to declare themselves as event listeners. But I am all good to go, thank you again.

I might be completely not understanding what you need so I’ll state the statement first:

Fire an event in Lua that calls a method in Object-C

First I would just create an event in Lua. This is a button but it could be a timer or whatever.

button:addEventListener("touch", launchSkillZ)

Then will call the code the lua code:

if event.phase == “began” then

showSkillzUI()

end

Show showSkillzUI is a Object-C call:

const luaL\_Reg kVTable[] = { { "init", init }, { "showSkillz", showSkillz }, { "randomNumber", randomNumber }, ... };

The actual method. Notice I am also making a call to Fabric to record the event.

int CoronaSkillZ::showSkillz( lua\_State \*L ) { [[Skillz skillzInstance] launchSkillz]; [Answers logContentViewWithName:@"Skillz UI" contentType:@"External View" contentId:@"SKLZ-001" customAttributes:@{}]; return 0; }

Let me know if this helps.

Not exactly what I had in mind, but it might fit, let me see if I understand.

First, what I had in mind is direct catching of the event in Objective-C – the event listener in Lua irrelevant. As far as I can tell, your example does not do that, you use an intermediary event listener in Lua that then calls the Objective-C. I wanted to create an event listener in Objective-C that can directly receive a Lua event.

But your approach would work fine, if I could understand it, as long as it does not depend on the ‘plugin’ setup. What I do not understand in your code: it seems that the Lua function call showSkillzUI() is picked up by a function call showSkillz on an instance of CoronaSkillZ. How is that mapping happening? Is that just a typo, and the function call in C should be called showSkillzUI, or does appending UI somehow tell the delegate that it is an Objective-C call? I assume not, so am a bit confused.

But even setting aside the name difference, how does the Lua delegate know which showSkillz function to call, that function name could be on many different classes, thus on several instances, and it could be a Lua function name, right? Isn’t it scoped to just CoronaSkillZ, or am I not understanding Objective-C scoping?

I also don’t understand what this line is doing:

    [[Skillz skillzInstance] launchSkillz];

Sorry for the naive questions, I am a beginner in Objective-C.

  1. The difference between the two is a typo. Or a copy and paste error. 

  2. Skillz is eSport api provider. So that launchSkillz launches their UI. My game sixteen dots on ios uses it:  These type of eSport games are not allowed on Google so the Play version is not integrated.

  3. I don’t know of any mechanism that firing an event in Lua would trigger an event immediately in object-C. I have in the past created a generic proxy class that would just translate events between two worlds, but that would still depend on the Lua events on the Lua side.

  4. I also don’t understand what you mean about the plug-in infrastructure. The coronaskillz is just a class /header file combo and i don’t have a “plugin for this”, but it uses the same infrastructure. I still reference the CoronaRuntime.h library.

In any case, I’ll try to create a simple project either today and tomorrow to demonstrate what I do. Then you can decide if this is the approach you want to take.

Thank you, that makes sense, I think I understand, but there is something missing for me still.

With the typo fix, I still don’t understand how you specify in Lua which function call you are calling. Is showSkillz a global function? How was it declared to be a global function so that Lua can call it without context? That is the key point I am missing.

When using the plugin examples, the flashlight example, I have to call flashlight.on() so that on() has the context of the flashlight object. When you call showSkillz, you are not giving any object context, how does the app know what object that function belongs to, where to find it, unless you have declared it ‘global’ in some way?

On the lua side all I have to reference is the library.

local library = require "FireMethodFromLua"

Since unless you create the .lua file the simulator will throw an error I wrap the entire thing:

if system.getInfo("environment") == "device" then local library = require "FireMethodFromLua" timer.performWithDelay( 1000, function() library.doSomeWork( ) end ) end

In the example “doSomeWork” does nothing. But if you put a breakpoint in the xcode portion where it is supposed to fire it will break there.

Got it. Thank you for the example, I was looking for the CORONA_EXPORT, I thought that is what I needed.

I notice you do have the plugin files, but you said you don’t need it. But I know that build.sh blows up if you don’t have that. Is this the simplest needed, with the PluginLibrary included but not used? I ignore the PluginLibrary in my project also, but would be nice to just remove it.

Thank you again, I can make it work from here, I am pretty sure.