- Home /
Button Listener Takes Reference But I Want to Pass Value?
I've got a list of Button objects and I want to give each of them a different return value so that a function will know which button was clicked/what that button corresponds to. To do this I iterate through a List of Buttons and then give each a listener with the index value of the for loop.
The problem (I believe) is that the listener takes the index variable as a reference and passes that to the listener rather than the actual index value. So the result of having a List of 5 Buttons would be that each would return the value of i (which would be 5 at the end of the for loop) rather than returning 0, 1, 2, 3, 4, 5. The below code shows what I'm trying to do.
public List<Button> buttons;
void Start()
{
for(int i=0; i<buttons.Count; i++)
{
buttons[i].onClick.AddListener(() => TellFunc(i));
}
}
void TellFunc(int index)
{
Debug.Log("this is button #" + index);
}
TLDR; Is there any way to make it so that the Button.onClick listeners will take the argument as a value rather than a reference?
Answer by purdyjo · Mar 28, 2015 at 02:50 PM
I believe all you need to do here is create a temporary integer within the for loop to store the integer, and pass that temporary integer into the listener.
integers are passed by value by nature, just as any basic data type and struct, so I am suprised that it doesn't work with just passing i into the listener, but all you should have to do is something like this
for(int i=0; i<buttons.Count; i++)
{
int tempInt = i;
buttons[i].onClick.AddListener(() => TellFunc(tempInt ));
}
and it should work the way you want, having each button return individual numbers instead of all of them returning 5 with a list of 5 buttons as an example
This does not work. Common sense would tell one that tempInt only exists in the scope of the current iteration, but it persists somehow and always gets the last value of i-1 (because the last increase of i is not submitted to it), it behaves like a global variable.
This does work. You should read about closures and what they actually close around. The variable "i" is declared outside of the for loop and is the same for each iteration. That's why the original code does always print the last assigned value because every closure will reference the same variable.
In the solution in this answer the closure will close over the local "tempInt" variable. Each iteration will have a new fresh variable. Don't say it doesn't work when you haven't tested this exact code example.
If it doesn't work for you, you probably have something different which might cause a different behaviour. However such a case doesn't belong into a comment on an answer to a different question. Ask a seperate question if you want to have your case sorted out. Feel free to reference this question
This is what i really looking for. Well actually i want to AddListener with Dictionary full of delegates instances but it doesn't work at all !
I tried to use List and this problem happen to me.. when i try to call
buttons[i].onClick.AddListener(() => TellFunc[i]());
it didn't work ! but when i swap i to tempInt it work like charm ! well my code is not as good as i want if it use Dictionary but hey ! its finally working !
THAN$$anonymous$$ YOU SO $$anonymous$$UCH !!
Your answer
Follow this Question
Related Questions
Creating a button, giving it a delegate (or Action), and giving that delegate a reference parameter 0 Answers
Method added on a button click with a delegate is being called twice. 0 Answers
Any way to pass the function of a listener as a string? 1 Answer
Reference For Button Which Calls OnClick 4 Answers