Найти вызывающего абонента динамически добавленного прослушивателя нажатия кнопки

Я добавляю в код список кнопок, для которых я хотел бы добавить прослушиватель кликов.

Я могу добавить слушателя, проблема в том, что я хотел бы знать кнопку, которая вызвала слушателя.

Я пробовал следующий метод, но переданное слушателю значение всегда одно и то же:

foreach (...)
{
    var button = (Button)GameObject.Instantiate(...);

    packIndex++;

    button.onClick.AddListener(() => this.OnButtonClick(packIndex));
}

public void OnButtonClick(int idx)
{
    // idx is always the latest value in the above loop
}

TL;DR

Как найти вызывающего абонента по прослушивателю нажатия кнопки?


person rhughes    schedule 16.08.2015    source источник


Ответы (2)


У тебя почти получилось. Чтобы сохранить индекс, вам нужно «захватить» переменную packIndex, сделав копию packIndex внутри цикла for. Вы можете увидеть хорошее объяснение этого феномена «замыкания в цикле for» здесь.

Следующий код должен работать:

foreach (...)
{
    var button = (Button)GameObject.Instantiate(...);

    packIndex++;
    var packIndexCopy = packIndex;

    button.onClick.AddListener(() => this.OnButtonClick(packIndexCopy));
}

public void OnButtonClick(int idx)
{
    // idx is always the latest value in the above loop
}

Обратите внимание, что ответ @Nain также будет работать, потому что в этом случае объект «кнопка» в AddListener(() => this.OnButtonClick(button)); относится к новому объекту, который создается каждый раз в цикле foreach, поэтому компилятор правильно привяжет обработчик OnButtonClick к этой «новой» копии . На самом деле, передача объекта Button напрямую выглядит немного чище, но это зависит от остального кода.

Если вы не знакомы с замыканиями (которые действительно сбивают с толку и требуют много времени для понимания!), это статья имеет хорошее объяснение.

P.S. Я написал небольшой компонент, чтобы проверить это, вот его суть на случай, если это поможет.

person Julia Schwarz    schedule 16.08.2015

Попробуй это

var button = (Button)GameObject.Instantiate(...);
packIndex++;
button.name = "Button" + packIndex;
button.onClick.AddListener(() => this.OnButtonClick(button));

public void OnButtonClick(Button button)
{
// idx is always the latest value in the above loop
}
person Nain    schedule 16.08.2015