Tutorial: Corona Enterprise quickstart (iOS)

Corona Builder
Share on Facebook0Share on Google+2Tweet about this on TwitterShare on LinkedIn0

Today’s tutorial is an introduction to Corona Enterprise development on iOS, showing Corona developers how to extend or create a Corona project that leverages native iOS functionality. Using Enterprise, Corona developers can combine the best of both the native world and the rich feature set of Corona SDK. Sign up for a 30-day trial and get started today.

Note: If you’re interested in using Enterprise for Android, see the Android quickstart tutorial.

Setting Up

First, we recommend that you update to the latest version of Xcode from within the App Store application. Also, ensure that Corona Enterprise is installed in your root OS X Applications directory (/Applications/CoronaEnterprise).

In this tutorial, we’ll begin with the default template located here:

/Applications/CoronaEnterprise/ProjectTemplates/App

Copy this folder to your project folder or another convenient location. Once copied, you can rename the folder to whatever you want. In this tutorial, we’ll discuss how to turn the device’s flashlight on and off, so “Flashlight” may be an appropriate folder name.

Within this folder are two projects: one to compile the plugin library and one to compile the app itself. Unlike Corona SDK, where you simply provide the Lua files and resources for Corona Labs’ build servers to compile your project, Corona Enterprise builds a native library that has bindings to your Corona SDK app.

Let’s start with building the plugin. First, open the iOS folder and you’ll see several files, two of which must be noted:

  • App.xcodeproj
  • Plugin.xcodeproj

These are Xcode Project files which hold various settings for your project. Double-click on Plugin.xcodeproj file to load the file in Xcode. Once loaded, inspect the left hand column — from here, expand the Plugin folder, then the Source folder. Inside, you’ll see the PluginLibrary.mm and PluginLibrary.h files.

For those with a background in C, the .mm extension may seem a bit odd. In Xcode, a .m file is really a .c file, but it stands for “Methods”. This .mm file allows Xcode to mix Objective-C with C++ and it’s where you put your methods and objects. The .h file is the traditional C “header” file where you place the definitions for the objects.

Methods File

Let’s start by opening the methods file (.mm). For this tutorial, your application will need access to the AVFoundation framework. As such, you need to include the appropriate header file just after the UIKit include.

Next, the PluginLibrary class is declared. This is the interface for binding your plugin to Lua:

Most of this you don’t need to touch, except for the final public: block where two methods are defined:

For our Flashlight app, show does’t make much semantic sense. Methods of on and off would be more logical. So, remove the show method and define the on and off methods instead:

In each one, lua_State *L is a data structure/object that represents the Lua engine.

Next, we’ll update some values to better represent the actual project on the Lua side and provide the proper linking:

Next, the PluginLibrary::Open() method needs updating to remove the show method and add the on and off methods:

Now, scroll down until you see the defined show method. Remove it and replace it with this block of code:

The code for the flashlight code came from a posting on StackOverflow, but it’s been modified here to adjust from a toggle to two separate actions.

Following the Objective-C code which manages the device’s LED lamp, there’s some Corona Enterprise code that constructs an event and dispatches it to your Lua app. Let’s examine that code:

This code creates a C object called library. This is the pathway to your Lua app. Next, it calls CoronaLuaNewEvent() and passes it the kEvent object. It then adds the string message and tells Lua it’s the second entry in the table. Finally, it dispatches the event to the library. Later, we’ll discuss the Lua code for handling this event.

The last block of code on the page will be:

Because of the “suffix” _library, the name of the plugin on the Corona side will be library. That name is vague if you decide to build several plugins, so let’s rename the plugin flashlight by changing the code to luaopen_plugin_flashlight:

Header File

In the header file (.h), you must rename the definition to match. In the left column, select PluginLibrary.h and change the CORONA_EXPORT line to the following:

At this point, select Product → Build (Command-B) to build the project. If Xcode does so without errors, you can close this project for now.

App File

Now, from the project directory, open the main project file App.xcodeproj. First, we’ll rename the project to something more sensible by clicking on the project name (App) in the left column. Change the name to Flashlight. Xcode will then show a dialog box indicating all of the names it will change. Click Rename to make the change. Close the project, re-open it, and make the following important setting changes:

When you open a project, the top section of the middle pane, Identity, should show you the Bundle Identifier, Version, Build, etc. You can edit the com.yourname section of the Bundle Identifier but you can’t change the app name.

xcode

In the Deployment Info section below, go through and edit the options such as Deployment Target, Devices, Device Orientation, etc.

Next, scroll down to the Linked Frameworks and Libraries and, at the bottom, click on the + button. Locate AVFoundation.framework, select it, and click Add.

Now, in the uppermost bar of the middle pane, click on the Build Settings tab and scroll down to Linking. For Other Linker Flags, enter -all_load -ObjC -lobjc -lsqlite3.

On to Corona

In the left column of the Xcode project, assuming you’ve expanded the Flashlight tree, you’ll see an Xcode group named Corona (look for the folder icon). If you expand this item tree, you’ll see only main.lua listed, although the actual folder contains other files familiar to Corona developers (build.settings, config.lua, etc.).

Now let’s edit the main.lua file. You can edit it in your preferred editor, or simply edit it directly within Xcode:

The first line loads your plugin into a Corona object called flashlight. The second line require‘s the Corona widget library, and lines 4-6 create a simple white background rectangle.

Next is the function called delegateListener(). This function will be attached to the Runtime event "delegate" and will receive events dispatched from the native side. In this case, it just shows an alert. Basically, this lets you know when your app has been loaded — this sample app won’t use it in a meaningful way.

The next function is the listener that the plugin uses to receive events from the various plugin methods. Again, we simply show an alert.

The rest of the code does the main work from the Corona side. Among other things, we create a widget button that uses the event listener function named handleButtonEvent(). Most importantly, notice that this listener function calls:

  • flashlight.on()
  • flashlight.off()

These are the functions that you wrote in Objective-C within PluginLibrary.mm. Simply call them to activate them.

Test Run

And now for the fun — testing on an actual device!

  1. Assuming you’ve enabled your iPhone as a development device, connect it to your computer with the sync cable.
  2. In the upper-left corner of Xcode, locate the menu of devices, including iPhone Retina (4-inch) and other options. Click on this menu and a popup window should appear with an arrow that lets you scroll up to the actual device that you just connected. Select it and exit the popup.
  3. To the left of that device list, you’ll see a Play button. Click this and Xcode will install the app onto the device and start it up. Because it’s in development mode, it takes a couple of seconds longer to start up.
  4. If everything is working correctly, your screen will turn white and you’ll see the “Turn On” button. Tap it and the flashlight should turn on. Dismiss the alert and tap the button again to turn off the flashlight.
  5. When you’re finished testing, click the Stop button in Xcode.

You may get warnings if you’ve not setup your icons and other project settings.

Conclusion

Clearly this tutorial is just a basic example of what can be done with Corona Enterprise, but hopefully it has shown you what can be accomplished when you combine the nearly unlimited power of native programming with the ease and simplicity of Corona SDK.

Share on Facebook0Share on Google+2Tweet about this on TwitterShare on LinkedIn0
Rob Miracle

Rob Miracle creates mobile apps for his own enjoyment and the amusement of others. He serves the Corona Community in the forums, on the blog, and at local events.

This entry has 22 replies

  1. Amazing! So thank you!
    Next step, the very same tutorial for Android?

    Thanks for this one, it was the missing part of the documentation!!

  2. dingo says:

    i am with david there, next android 🙂

    and thanks for the tutorial!

  3. Build failed??? says:

    Sorry this does not build correctly after following the tutorial step by step. I get the following linker error, can you please advise?

    ld: warning: ignoring file /Applications/CoronaEnterprise/Projects/Flashlight/ios/CoronaEnterprise/Corona/ios/lib/libplayer.a, missing required architecture x86_64 in file /Applications/CoronaEnterprise/Projects/Flashlight/ios/CoronaEnterprise/Corona/ios/lib/libplayer.a (2 slices)

    • Rob Miracle says:

      There is likely two causes.

      1. Are you building for your tethered device or the Simulator (4″ 64 bit) or some other Simulator device?
      You cannot build for the 64 bit simulator without making a change to your build settings.

      2. In the build settings screen, there is a list of architectures: armv7, armv7s, arm64. This worked for me, but changing this to leave off arm64 will prevent the 64bit version being built, which might fix the problem.

      Rob

  4. Luis says:

    Excuse me, now I try implemented in file PluginLibrary.mm a method. But I do not understand how I can declare and get data in method with parameter (a table).

    e.g:
    =>Lua (main.lua):
    local variable = require “plugin.library”
    variable.setData( {“170″,”65″,”m”} )

    =>Native & Lua (PluginLibrary.mm):
    public:
    static int init( lua_State *L );
    static int setData( ???? ); // How I declare parameters?

    int PluginLibrary::setData(????)
    {
    // How I get datas from this parameters?
    }

    Thank you for your time and help.

    • Rob Miracle says:

      I would recommend looking at the Enterprise sample /Applications/CoronaEnterprise/Samples/SimpleLuaExtension

      It shows you how to move different data types around.

  5. Luis says:

    Thank you, for you response. And one more question, I need use library ( library build for other ) in “PluginLibrary” file. But, this library (build for other) Is possible add other library in “PluginLibrary” file?

    • Rob Miracle says:

      I’m not sure I follow your question. You might have better luck asking this in the Forums in the Enterprise section.

      Rob

    • Luis says:

      e.g: File “PluginLibrary.mm”


      #import “xxx.h”

      public:
      static int connect( lua_State *L );

      { “connect”, connect },

      int
      PluginLibrary::connect( lua_State *L )
      {
      [[xxx sharedXXX] connect]; <– Show error, I when call method xxx, but if I remove this line code, is perfect run.

      }

      ———–
      [Abstract]
      I need to integrate a third party iOS library which has come with a .a with a Corona app.
      I have been referring to this doc:
      http://docs.coronalabs.com/native/plugin/index.html#ios
      http://coronalabs.com/blog/2014/03/18/tutorial-corona-enterprise-quickstart-ios/

      To create a plugin for Corona, but so far can't understand how to start with it.

      A summary of what I can't understand:

      If I create an application, what folder structure should I create?
      Where should?

  6. Romowski says:

    Hi Rob!
    I have about 40 errors in this code.

    “Undefined symbols for architecture arm64:
    “std::string::find(char const*, unsigned long, unsigned long) const”, referenced from:
    Rtt::ShaderName::ShaderName(char const*) in libplayer.a(Rtt_ShaderName.o)
    “std::string::compare(char const*) const”, referenced from:
    Rtt::ShaderFactory::LoadDependency(Rtt::LuaMap*, std::string, std::map<std::string, Rtt::SharedPtr, std::less, std::allocator<std::pair<std::string const, Rtt::SharedPtr > > >&, bool) in libplayer.a(Rtt_ShaderFactory.o)
    Rtt::ShaderInput::UpdateCache(Rtt::TextureInfo const&, Rtt::RenderData const&) in libplayer.a(Rtt_ShaderInput.o)
    “std::basic_stringbuf<char, std::char_traits, std::allocator >::str() const”, referenced from:
    Rtt::LuaMap::LuaMap(lua_State*, int) in libplayer.a(Rtt_LuaContainer.o)”

    and so on..

    I’m building for my iPhone5S.
    I have tried to exclude arm64 form Build Settings – Valid Architectures (only armv7, armv7s) but getting the same error.

    • Romowski says:

      Handled it. Now the next error:
      “ld: file is universal (4 slices) but does not contain a(n) armv7s slice: /Users/Apple/Documents/Corona Projects/VAYA/Flashlight/ios/CoronaEnterprise/Corona/ios/lib/libplayer.a file ‘/Users/Apple/Documents/Corona Projects/VAYA/Flashlight/ios/CoronaEnterprise/Corona/ios/lib/libplayer.a’ for architecture armv7s
      clang: error: linker command failed with exit code 1 (use -v to see invocation)”

  7. Rob Miracle says:

    We have open sourced our plugins at https://github.com/coronalabs/
    Maybe it’s worth looking at our iOS contract plugin code to see how we handlie it..

    Rob

    • Romowski says:

      There is popup view, but I would like to get an array (LUA table) of contacts.
      Rob, I got it how to get simple table from xCode (from SimpleLuaExtention example).

      Getting simple table with key “compositeName” and value “Alex”
      lua_pushstring( L, (char*)[@”Alex” UTF8String] );
      lua_setfield( L, -2, “compositeName” );

      But.
      I have an NSArray of all my contacts which contain NSDictionaries with keys. So I need to get table which contain another table with contact details.

  8. upen says:

    i am adding Corona Enterprise project to mobileAppTracker framework but i get error like Apple Mach-O Linker Error
    ld: warning: directory not found for option ‘-L”/Users/upendarrao/Desktop/App/ios/CoronaEnterprise/Corona/ios/lib”‘
    ld: library not found for -lplayer
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    please help me

  9. Keng says:

    Where can we find more iOS + Corona Enterprise examples?
    Could you provide more tutorials? Thank you very much.

    • Rob Miracle says:

      If you look on our github repo: http://github.com/coronalabs you will find all of our open source plugins which are great examples to go buy.

      Rob

  10. Hi,
    I need to communicate with swift native libraries
    Can I do that with Corona Enterprise?
    Where can I find ressources?
    Thanks for your help

Leave a reply

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">