Найти вызывающего абонента динамически добавленного слушателя нажатия кнопки
Я добавляю в код список кнопок, для которых я хотел бы добавить прослушиватель щелчков.
Я могу добавить слушателя, проблема в том, что я хотел бы знать кнопку, вызвавшую слушателя.
Я пробовал следующий метод, но переданное значение слушателю всегда одинаково:
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
Как вы находите звонящего из слушателя нажатия кнопки?
2 ответа
У вас почти есть это. Чтобы сохранить индекс, вам нужно "перехватить" переменную packIndex, сделав копию packIndex
внутри для цикла. Вы можете увидеть хорошее объяснение этого феномена "замыкание в цикле" здесь.
Следующий код должен работать:
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
объект непосредственно выглядит немного чище, но это зависит от остальной части вашего кода.
Если вы не знакомы с замыканиями (которые действительно сбивают с толку и долго разбираются!), Эта статья имеет хорошее объяснение.
PS Я написал небольшой Компонент, чтобы проверить это, вот суть для него на случай, если это поможет.
Попробуй это
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
}