Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-17751] iOS8: unable to set object property inside object

GitHub Issuen/a
TypeBug
PriorityMedium
StatusClosed
ResolutionWon't Fix
Resolution Date2014-12-04T16:54:09.000+0000
Affected Version/sRelease 3.3.0, Release 3.4.0
Fix Version/sn/a
ComponentsiOS
LabelsTCSupport, alloy, bug, ios, ipad, object, property
ReporterRicardo Pereira
AssigneeIngo Muschenetz
Created2014-09-17T09:19:50.000+0000
Updated2017-03-30T20:56:42.000+0000

Description

Problem Description

If I have an object (status:{}) inside an object (Ti.UI.View), and I want to edit/add a new property to 'status', in android works perfectly, but on iOS it doesn't change the property, defined on 'Ti.UI.View' creation.

Steps to reproduce

1. Create a new mobile project (Classic Titanium) 2. Paste this sample into app.js:
var win = Titanium.UI.createWindow({  
    backgroundColor:'#000',
    layout:'vertical'
});
 
var APPNAME = {
    "UI":{
        "Buttons":function(props) {
  
            var button = Ti.UI.createView({
                top:100,
                height:200,
                status:{
                    selected:false,
                    inactive:false
                },
                backgroundColor:"white",
                select:function(sttz) {
      
                    if(sttz) {
                         
                        this.status["selected"] = true;
      
                        this.backgroundColor = "red";
                    }
                    else {
                         
                        this.status["selected"] = false;
      
                        this.backgroundColor = "white";
                    }
      
                    console.log("selected status: "+this.status.selected);
      
                }
            });
             
            button.addEventListener("click",function() {
  
                if(!this.status.selected) {
                    this.select(true);
                }
                else {
                    this.select(false);
                }
              
            });
  
            return button;
        }
    }
};
 
var exemple_btn = APPNAME.UI.Buttons();
win.add(exemple_btn);
win.open();
3. Run it in device. 4. Click on the White box. It should turn red. Click in the red box. It should turn white. Repeat.

Expected Results

When you click in the box, it should go from white to red and viceversa.

Actual Results

It's working fine in Android, failing in iOS.

Attachments

FileDateSize
exemple_ipad.zip2014-09-17T09:19:50.000+00003850464

Comments

  1. Ricardo Pereira 2014-09-24

    I noticed that there has been activity around this error, as no one commented yet, is there any alternative that I should try?
  2. Ricardo Pereira 2014-12-02

    Hi, I'm just writing this comment to know if there is someone working on this issue, I've 2 complex apps that it's supposed to run on iPad, and I'm kinda stuck
  3. Tim Poulsen 2014-12-03

    Our general recommendation has always been to not modify the proxy objects (the objects you get back from a Ti.UI.create* method). See the [best practices guide](http://docs.appcelerator.com/titanium/latest/#!/guide/Coding_Best_Practices-section-30082362_CodingBestPractices-Don%27tExtendTitaniumPrototypes) or perhaps the [article I wrote for TiDev.io](http://www.tidev.io/2014/03/27/memory-management/) for background information. In essence, Titanium proxies are not true JavaScript objects and should be treated as immutable (in terms of adding or attempting to override properties and methods). Under the covers, our Android and iOS implementations are different enough, that this works to some extent on Android while it is more likely to cause problems on iOS. From what I see of your app's needs, it seems you could use a separate (true JavaScript) object to maintain state information for your UI components. Then, applyProperties() as needed to update their UI state.
  4. Vishal Duggal 2014-12-04

    Try this
                    
       select:function(sttz) {
           var status = this.status;
           if(sttz) {
               status.selected = true
               this.backgroundColor = "red";
           }
           else {
               status.selected = false;
               this.backgroundColor = "white";
           }
           //IOS proxies are not true JS Objects and any undefined properties need to be 
           //explicitly reset after modification
           this.status = status;
           console.log("selected status: "+this.status.selected);
       }
       
  5. Vishal Duggal 2014-12-04

    Workaround in comments
  6. Ricardo Pereira 2014-12-04

    That works, but I have some objects that have many levels of objects and it will be difficult to applicate that to everything. So instead of pass the properties inside a function and attribute them that way, a create a true javascript object, and work on it. exemple:
       var btn = (props) {
       
          var obj {
             "status":{
                "selected":true,
                "inactive":false
             },
             "element":Ti.UI.createView({
             })
          };
       
          obj.select = function(status) {
             ...
          };
       
          return obj.element;
       };
       
       var test = new btn({
          "title":"test"
       });
       
       test.select(true);
       
       
  7. Lee Morris 2017-03-30

    Closing ticket as "Won't Fix". There has been no update for a while. If there is any problem, please open a new ticket.

JSON Source