array.push() not working on Ti.UI.View custom property

You must Login before you can answer or comment on any questions.

var view = Ti.UI.createView();
var b1 = Ti.UI.createButton();
var b2 = Ti.UI.createButton();
var b3 = Ti.UI.createButton();
view.keys = [b1,b2];
Ti.API.log('keys.length = ' + view.keys.length);
view.keys.push(b3);
Ti.API.log('new keys.length = ' + view.keys.length);
The output of the above code is:

keys.length = 2

new keys.length = 2

It appears as the push() function does nothing. if the variable view is just a simple object, everything works fine. (i.e. var view = {}).

Are we not allowed to set custom properties on Titanium UI Views and Controls? Is this a bug, something not supported or am I doing something wrong?

I know one way for me is to add these buttons to the view by doing view.add() and accessing the view.children property but I don't want these buttons to be in the view hoping it'll render faster. I want an array on the view object to hold all the buttons. I'll be dealing with 200-300 buttons but only 30-40 will be shown at a time. By putting all the buttons in the view, I see performance issues. Thanks in advance.

(this is being run in the iOS iPad simulator)

3 Answers

Accepted Answer

I often add properties to views, but I've never tried setting one to an array and then calling push() on it. I tried your code and got the same results. I can't exactly explain why that happens, but what if you try something like building a CommonJS to "subclass" the view with parasitic inheritance? You can add functions to the view that can reference the array of buttons without actually adding the buttons to the view itself.

Here's a sample implementation:

MyView.js:

function MyView ()
{
    var _self = Ti.UI.createView ();
    var _keys = [];
 
    var b1 = Ti.UI.createButton();
    var b2 = Ti.UI.createButton();
    var b3 = Ti.UI.createButton();
 
    _keys = [b1,b2];
 
    Ti.API.log('keys.length = ' + _keys.length);
 
    _keys.push(b3);
    Ti.API.log('new keys.length = ' + _keys.length);
 
 
    _self.xgetKeys = function ()
    {
        return _keys;   
    }
 
    return _self;   
}
 
module.exports = MyView;
app.js:
var MyView = require ('MyView');
 
var v = new MyView ();
 
var keys = v.xgetKeys ();
 
Ti.API.log ('MyView keys length: ' + keys.length);
results in the output:
[INFO] keys.length = 2
[INFO] new keys.length = 3
[INFO] MyView keys length: 3

It is a known issue with Proxy objects. See Kevin Whinnerys article on Proxy Objects. An Array is a type of Nested Object. You need to do something like:

view.keys = [b1,b2];
Ti.API.log('keys.length = ' + view.keys.length);
var tempArray = view.keys;
tempArray.push(b3);
view.keys = tempArray;
Ti.API.log('new keys.length = ' + view.keys.length);

— answered 11 months ago by Jeff Bonnes
answer permalink
2 Comments
  • Thanks for the recommendation. One thing that concerns me is even though

    tempArray = view.keys;
    view.keys = tempArray;
    should be only a reference copy, it seems Titanium does an actual copy of the array so it should work but would take up more memory

    — commented 11 months ago by Garland Chan

  • b1,b2 and b3 contain complex Objects, it shouldn't clone the Object even when calling var temparray = view.keys.slice(0)

    only the references should be copyied but not the actual Objects, and if Titanium would do an actual copy, should'nt the garbage collector garbagecollect the old Objects, as they arent referenced or used anywhere anymore ?

    — commented 11 months ago by Moritz Roessler

Just:

var view = {
_view : Ti.UI.createView(),
buttons : [Ti.UI.createButton(), ...]
}
this is what should solve your Problem.

Your Answer

Think you can help? Login to answer this question!