【问题标题】:Unintended Event Listener result returned意外事件侦听器结果返回
【发布时间】:2013-04-08 00:55:15
【问题描述】:

我正在使用 Titanium 构建 iOS 应用程序。我正在尝试在 tableView 中显示按字母顺序排列的列表。选择特定行时,我想将行信息传递到新窗口。 The code I have displays the list alphabetically in groups with headers and I have an alphabetical scrollbar that when a letter is selected the list moves to that letter. However, when ANY row is selected, they all send the information for the last row in the database.我认为我需要在行中有一个带有文本属性的标题元素,然后我可以有一个 tableview.addEventListener 抓住该标题并将其传递,但​​它不起作用。这是我正在使用的代码,如果有人可以看看我哪里出错了,将不胜感激。

var db = (function() {
var api   = {};
    api.all_item_names = function() {
        var conn = Ti.Database.install('mydb.sqlite','clients');
        var results = [];
        var resultSet = conn.execute('select * from clients order by clientname asc');
        while ( resultSet.isValidRow()) {
            results.push({
            clientname:  resultSet.fieldByName('clientname'),
        });
        resultSet.next();
    }
    resultSet.close();
    return results;
};
return api;
}());

var tvrow;
var curheader   = 'A';
var list    = [];
var index   = [];
var data   = [];
var isAndroid   = (Titanium.Platform.name == 'android');

list = ( db.all_item_names() );

for ( var ipos=0; ipos<list.length;ipos++){
    if( list[ipos].clientname[0] != curheader){
        curheader = list[ipos].clientname[0];

        tvrow = Titanium.UI.createTableViewRow({
            height:    40,
            path:'clientdetail.js' ,
            client: list[ipos],
            header:    curheader 
            });
        index.push({title:curheader, index:ipos});
    } else {
        tvrow = Titanium.UI.createTableViewRow({
            height:40,
            path:'clientdetail.js' ,
            client: list[ipos]});
        }   

var title= Titanium.UI.createLabel({ 
    left:    5, 
    top:     2, 
    height:  40, 
    color:   '#000', 
    font: {fontSize: 16, fontWeight: 'bold', fontFamily: (isAndroid?'sans-serif':'Helvetica Neue')}, 
    text:    list[ipos].clientname });
    tvrow.add(title);
    data.push(tvrow);
}

var tableView = Titanium.UI.createTableView({
    data:            data,
    index:           index,
    backgroundColor:'transparent',
    separatorStyle:  Titanium.UI.iPhone.TableViewStyle.GROUPED,
    top:             1,
    width:           '99%'
});

tableView.addEventListener('click', function(e)
    {
        if (e.rowData.path)
        {
            var win = Ti.UI.createWindow({
                url:e.row.path,
                title:title.text
            });

        var clientlist = title.text;
        win.clientlist = clientlist;
        Ti.UI.currentTab.open(win);
    }
});

win.add(tableView);

【问题讨论】:

    标签: javascript ios database titanium


    【解决方案1】:

    问题在于您使用的循环。您将所有内容分配给索引ipos 处的值,最终是list.length(或最后一个值),这就是为什么您总是得到那个值。为了解决这个问题,通常使用闭包并传入值,如下所示:

    for ( var ipos=0; ipos<list.length;ipos++){
     (function(i){
      if( list[i].clientname[0] != curheader){
       curheader = list[i].clientname[0];
    
       tvrow = Titanium.UI.createTableViewRow({
        height:    40,
        path:'clientdetail.js' ,
        client: list[i],
        header:    curheader 
       });
       index.push({title:curheader, index:i});
      } else {
       tvrow = Titanium.UI.createTableViewRow({
        height:40,
        path:'clientdetail.js' ,
        client: list[i]
       });
      }   
    
      var title= Titanium.UI.createLabel({ 
       left:    5, 
       top:     2, 
       height:  40, 
       color:   '#000', 
       font: {fontSize: 16, fontWeight: 'bold', fontFamily: (isAndroid?'sans-serif':'Helvetica Neue')}, 
       text:    list[i].clientname 
      });
      tvrow.add(title);
      data.push(tvrow);
     })(ipos);
    }
    

    编辑

    我相信您可能在新窗口中得到了错误的标题,并且它访问了最后一个可用的title。但是,您的事件侦听器可以使用暴露的title。我相信它位于e.row.client.clientname(尽管从外观上看它可能在e.rowData..),这意味着您应该在点击时访问当前选择的标题

    var tableView = Titanium.UI.createTableView({
     data:            data,
     index:           index,
     backgroundColor:'transparent',
     separatorStyle:  Titanium.UI.iPhone.TableViewStyle.GROUPED,
     top:             1,
     width:           '99%'
    });
    
    tableView.addEventListener('click', function(e)
    {
     if (e.rowData.path)
     {
      var win = Ti.UI.createWindow({
       url:e.row.path,
       title:e.row.client.clientname
      });
    
      var clientlist = e.row.client.clientname ? e.row.client.clientname : "No client name";
      win.clientlist = clientlist;
      Ti.UI.currentTab.open(win);
     }
    });
    

    【讨论】:

    • 感谢 Travis 的回复,但现在我的名为 title 的标签在函数内部,当我在 tableView.addEventListener 中引用它时,找不到 title 变量。我试图将 tableView 和 Listener 放在函数中,但它也不起作用。抱歉,我对了解我需要做什么太深奥了。你能再帮我一次吗?
    • 很好的编辑。您能否更明确地说明不需要闭包这一事实,并快速建议何时应该使用它以及何时不应该使用它?我担心其他人会来,阅读这个答案,并认为解决方案总是引入闭包。
    • @DawsonToth - 闭包 是 需要关闭 for 循环迭代器。为了在活动期间获得正确的值,还需要进行扩展编辑,并且可能是一个单独的问题,因为它解决了一个单独的问题,而不是最初提出的问题。在这些情况下的解决方案是使用闭包来保留迭代器的值。
    • 没有。没有内部延迟上下文(例如事件侦听器)查看由循环变异的变量。无论有没有闭包,行为都是相同的。他的不当行为来自于查看“var title”,这当然是最后一个值。 (他的示例也缺少一个括号,大概是在“var title”之后和表格视图创建之前。)
    • 我知道我不是,基于对问题和您的答案的多次重读。请查看我的答案,然后运行代码。我对制造火焰战争不感兴趣,所以我不会再发这个问题了。
    【解决方案2】:

    错误的标题完全是由于引用了“title”变量。相反,您应该使用 e.rowData 或 e.index 来确定单击了哪一行。 "title" 将始终是您创建的最后一个标题。

    考虑以下示例,它以更简单的方式演示了您的错误和解决方案。请注意,将创建 for 循环的行包装在函数调用中不会帮助您解决此问题。

    var win = Ti.UI.createWindow({ backgroundColor: '#fff' });
    
    var rows = [], titles = [];
    for (var i = 0; i < 20; i++) {
        var row = Ti.UI.createTableViewRow({ height: 40 });
        titles.push('Title ' + i);
        var title = Ti.UI.createLabel({ text: titles[i], textAlign: 'center', color: '#000' });
        row.add(title);
        rows.push(row);
    }
    
    var table = Ti.UI.createTableView({
        data: rows
    });
    table.addEventListener('click', function(evt) {
        alert('WRONG: You clicked ' + title.text + '\n'
            + 'RIGHT: You clicked ' + titles[evt.index]);
    });
    win.add(table);
    
    win.open();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-14
      相关资源
      最近更新 更多