Search code examples
titaniumappcelerator

Titanium - Listener callback is of a non-supported type: __NSDictionary


I've a problem with Titanium SDK >= 6.1.0 GA and Ti.App.fireEvent under iOS. Until SDK 6.0.4 GA using Ti.App.fireEvent with a JSON dictionary as parameter was working fine, but since 6.1.0 to last GA (6.3.0) I'm receiving the following message:

Listener callback is of a non-supported type: __NSDictionaryM

I've seen this line inside KrollBridge.m that could cause this log message:

- (void)fireEvent:(id)listener withObject:(id)obj remove:(BOOL)yn thisObject:(TiProxy*)thisObject_
{
    if (![listener isKindOfClass:[KrollCallback class]])
    {
        NSLog(@"[ERROR] listener callback is of a non-supported type: %@",[listener class]);
        return;
    }

    KrollEvent *event = [[KrollEvent alloc] initWithCallback:listener eventObject:obj thisObject:thisObject_];
    [context enqueue:event];
    [event release];
}

ONLY fails when I try the app on device, on simulator works fine!.

Adding some NSLogs and running the app:

Console:

Simulator:
[DEBUG] :  Firing app event: event_test
[DEBUG] :  Listener type: KrollCallback
[DEBUG] :  OK

Device:
[DEBUG] :  Firing app event: event_test
[DEBUG] :  Listener type: __NSDictionaryM
[ERROR] :  Listener callback is of a non-supported type: __NSDictionaryM

Code:

Ti.App.addEventListener('event_test', fun);
Ti.App.fireEvent('event_test', data: {"ID": 0, "Value": "Test"});

I have no idea why. I've the feeling that is a bug introduced in 6.1.0 GA and it reproduces until the last GA available.

Any suggestions? Thanks


Solution

  • I guess this is the same issue reported here Ti.App.fireEvent JIRA which is marked as Resolved in SDK 6.3.0.GA

    Do update your Ti SDK to latest 6.3.0.GA as it's quite stable than other 6.x versions.


    Recommended Solution :

    Read here why to avoid using Ti.App.addEventListener & follow below steps to set global event listeners to pass around anything you want.

    1. Create a js file with any name, let's say, events_dispatcher.js in your project's app -> lib folder.
    2. Add this code line in this file : module.exports = _.clone(Backbone.Events);
    3. Now replace this code of yours Ti.App.addEventListener('event_test', fun); with this one :

      var eventHandler = require('events_dispatcher');
      
      eventHandler.on('event_test', fun);
      
      
      // to avoid duplication of adding the same event
      // make sure to remove this event when you close the controller
      // or you are planning to re-create the controller 
      
      eventHandler.off('event_test', fun);
      
    4. Finally replace this code Ti.App.fireEvent('event_test', data: {"ID": 0, "Value": "Test"}); with this one - require('events_dispatcher').trigger('event_test', data: {"ID": 0, "Value": "Test"});

    This code method might seem little more, but it's the most recommended way & optimal solution for all your needs to replace Ti.App.fireEvent. Stick to it & you will have a safe way to call around any method with any kind of data.