UITextField input every time new iteration - ios

I'm new to Objective-C and Xcode, and I have one problem, I tried looking in the Internet, but didn't find anything.
I have "game" and there I have a screen with two text fields, button and text view.User inputs integer values and taps the button. After tapping the button some functions(or, methods) are called. Method that is called after typing the button:
- (IBAction)okButtonTapped:(id)sender {
int save1=100;
int save2=100;
int save13=1;
int save22=1;
int save12=1;
int save23=1;
while(save13 !=0 && save23 !=0){
[self yourturn:&save1 heap2:&save2];
save12= save1;
save22=save2;
[self compturn:&save12 heap2:&save22];
save13=save12;
save23=save22;
save1=save13;
save2=save23;
}
}
Here some methods are called. And in this methods I use this code to save values from textfields that user inputs:
_heapNumberInt=[self.heapNumberTextField.text intValue];
_thingsNumberInt=[self.thingsNumberTextField.text intValue];
And the question is how to make users input new values in the textfield every time when there is new iteration in while loop?
Sorry for my English(it's not my native language) and for my long question.
All project you can download here
P.S. "game" is very simple: there are 2 heaps with 100 things each, user chooses his turn and then he inputs values: heap number(1 or 2 heap) and number of things he wants to take from the heap. Then there is computer's turn. And looser is someone who can't take things from any heap. It is real game called NIM.(but here I made only 2 heaps(not 3)).

Probably you need to read Event Handling Guide
https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009541
About the question, for setting focus to the input you should use
[self.heapNumberTextField becomeFirstResponder];
UPDATE:
As I understand you need to:
_heapNumberInt = [self.heapNumberTextField.text intValue]; // get value
[self.heapNumberTextField setEditable:NO]; // disable editing to calculate
[self calculate];
self.heapNumberTextField.text = #""; // clean UITextField
[self.heapNumberTextField setEditable:YES]; // allow editing
[self.heapNumberTextField becomeFirstResponder]; // set focus to the textfield

Related

segmented controller hide segment 0

I have a segmented controller that I have made using the interface builder it looks like this
Sometimes I set it to be four using this
[segmentedControl insertSegmentWithTitle:#"Dinner" atIndex:2 animated:YES];
[segmentedControl insertSegmentWithTitle:#"Latenight" atIndex:3 animated:YES];
Which works and is fine, but here is where my problem comes up, sometimes I just want to have breakfast and dinner and late night but no lunch. However I still want dinner to be at index 2 and late night at index 3. So the code I have doesn't need to change multiple times depending on how many indexes there are. I am aware of [segmentedControl setEnabled:NO forSegmentAtIndex:0]; But it doesn't look good and is not what I am trying to do?
Basically is there a way I can hide the lunch index so that dinner is still at index 2, and/ or set the dinner to index 2 even though there is no lunch segment?
Thanks for the help in advance!!! :)
EDIT
-(IBAction)selectMeal:(id)sender{
switch (((UISegmentedControl *) sender) .selectedSegmentIndex) {
case 0:
if ([dayInfo isEqualToString:#"Monday"]) {
deliString = #"//day[#name='monday']/meal[#name='LUNCH']/counter[#name='Deli']/dish/name";
}
case 1:if ([dayInfo isEqualToString:#"Monday"]) {
deliString = #"//day[#name='monday']/meal[#name='Dinner']/counter[#name='Deli']/dish/name";
}
Tried this:
indexBreakfast = -1;
indexLunch = 0;
indexDinner = 1;
[segmentedControl removeSegmentAtIndex:indexBreakfast animated:YES];
[segmentedControl insertSegmentWithTitle:#"Dinner" atIndex:indexDinner animated:YES];
Ew please don't use that approach. I know you want to be able to know which type corresponds with which index without a lookup, but it's just lazy.
Here's another approach. When you determine which options you are going to display, store an array of the options (either wrapped enum values, the string titles, whatever). When your target action is fired, grab the type from the array at the index of the selected segment. Done.
In your class, make a property to store the order
#property (nonatomic, strong) NSArray *mealStrings;
Then when you have determined which meals you want and the order, make an array with the values
self.mealStrings = #[#"Breakfast", #"Lunch"];
... and initialize the UISegmentedControl ...
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:self.mealStrings];
Then when you need to know which meal, you can access the type with
NSString *mealName = self.mealStrings[self.segmentedControl.selectedSegmentIndex];
There is no way to hide a segment. It must either be removed or disabled. And since you want to remove the segment, you need a good way to deal with segment indexes having different meaning depending on the visible segments.
One option would be to define an ivar for each possible segment and set it to the corresponding segment index as you build and adjust the segmented control.
Lets say you have four possible segments - breakfast, lunch, dinner, and late night. Add these four ivars:
NSInteger indexBreakfast, indexLunch, indexDinner, indexLateNight;
Now when you build the segmented control, set these four ivars to match the actual segment index of the corresponding segment. Assign -1 to the ivar if the segment isn't visible.
Now your segment handling code can be like:
-(IBAction)selectMeal:(UISegmentedControl *)control {
NSInteger index = control.selectedSegmentIndex;
if (index == indexBreakfast) {
// handle breakfast
} else if (index == indexLunch) {
// handle lunch
} else if (index == indexDinner) {
// handle dinner
} else if (index == indexLateNight) {
// handle late night
}
}
If you add, remove, or reorder segments as the app runs, simply update the four ivars and the rest of the code will do the right thing.

How to wait for button press in objective c

I have an array of objects (scaleNotes) that are assigned to buttons that I would like to iterate through. I want the app to wait for the first set of buttons to be pressed, then to wait for the second, and so on. However, with the function I currently have the app freezes.
The method that contains the array:
-(void)fingerScale :(UIButton*)button1 :(UIButton*)button2 :(UIButton*)button3 :(UIButton*)button4 :(UILabel*)label {
Note *note = [[Note alloc]init];
for (int i = 0; i < [_scaleNotes count]; i++) {
note = _scaleNotes[i];
label.text = note.noteName;
[note waitForNote:button1 :button2 :button3 :button4 :note];
NSLog(#"Waiting... %i", i);
}
}
The "waitForNote" method:
-(void)waitForNote:(UIButton *)button1 :(UIButton *)button2 :(UIButton *)button3 :(UIButton *)button4 :(Note*)Note {
bool loop = YES;
while (loop) {
switch ([Note.fingering count]) {
case 0:
loop = NO;
break;
case 1:
button1 = Note.fingering[0];
if (button1.touchInside) {
loop = NO;
}
break;
case 2:
button1 = Note.fingering[0];
button2 = Note.fingering[1];
if (button1.touchInside && button2.touchInside) {
loop = NO;
}
break;
case 3:
button1 = Note.fingering[0];
button2 = Note.fingering[1];
button3 = Note.fingering[2];
if (button1.touchInside && button2.touchInside && button3.touchInside) {
loop = NO;
}
break;
default:
break;
}
}
}
I have been told that using addTarget:action:forControlEvents may solve my problem instead of using a while loop, but I am unsure about how to implement that into my code. Please help.
Your while loop is an infinite loop, and that's why your app appears to freeze. Most GUI systems -- iOS included -- won't work that way. You have to give the app's event loop, or run loop, time to gather and process events.
-addTarget:action:forControlEvents: will be part of the solution, but you really need to spend some time learning more about how apps and controls work in general. Briefly, your controls should be connected to appropriate actions; if you want to enforce some order for the buttons you might enable or disable some buttons as necessary.
To expand on Caleb's answer a little bit:
iOS, like most modern interactive OS'es, is event-driven.
You write code that responds to events. The OS detects events, and then invokes the methods in your app that respond to those events.
You do NOT write a while loop that keeps looping, waiting for things to happen.
For buttons, you create methods of type IBAction, and you connect them to your buttons (usually connected to a "touch up inside" event.) Then, when the user taps and releases a button, the system calls your action method.
For a slider, you would write an action method and attach it to the "value changed" event for the slider. Then, when the user changed the value of the slider the system would call you.
So for your buttons you would write an action method and attach it to your buttons. (It's more common to create buttons and attach them to actions in Interface Builder, but you can also create them in code and then attach them using the -addTarget:action:forControlEvents: method you mentioned.)
If you've got multiple buttons that do the same thing but with different values, you might want to attach all the buttons to the same IBAction method, and then put different tag values on each button. Then in your IBAction method, look at the tag on the sender (The button that invoked the action) and use that to figure out which button was pressed.

How can I check if a button is pressed during a specific time interval in iOS?

I'm creating a game for iOS and need some help.
Simply put, random letters will be shown in a label(changing at regular interval), and the user must press the button when they recognise a pattern. If they press the button they earn points, and if they miss it, they lose points.
For example:
let's say they are looking for a letter repeating over one gap. They see the letters "R K W K". On the second K they would press the button. I need to be able to check if the button was pressed while that second K was displayed. I have searched here on stack overflow, but I can't really find anything specific to my situation. Thanks in advance for your responses. I'm new here, so I tried to be as specific as possible.
You can do something like this:
Make a global variable of type bool lets call it isMatch.
While displaying other letters make isMatch = false;
When you display the second 'K' (as your example) make isMatch = true
In you button click method check:
if(isMatch){
point++;
}
else point--;
Make sure you change isMatch = false on displaying other letters.
Hope this helps.. :)
As I understood you are displaying K (say) in UILabel and you might be getting input in UITextField, what you should do is implement ValueChanged IBAction for UITextField and add all letters (K, M, X, H) etc in an array what you have on screen for now. When the text changes it will come in above IBAction, match the UITextField's text with the elements of an array. If there is a match, you are done!
Hope this helps!
Just check in the selector for the button ... (If you're using Interface builder replace void with IBAction)
- (void) buttonWasPressed:(UIButton *) sender {
if ([[[sender titleLabel] text] isEqualToString:#"K"])
point ++;
else
point --;
}
try like this
- (void)buttonTapped:(UIButton *)yourbutton;
{
yourbutton.selected = ![yourbutton isSelected];
}
then this
[self.yourbutton isSelected];

CCLabelTTF changing string causes EXC_BAD_ACCESS

First off, as a disclaimer, I am new to objective-c, xcode, and cocos2d. I have found a way in my app to refresh a screen conveniently, but I don't know if it is bad practice. Here's what I am doing. I have a class called Player with a variable NSString *name. I am displaying this and several other variables on the screen using this code in a function:
label = [CCLabelTTF labelWithString:string fontName:GLOBAL_FONT fontSize:font_size ];
label.color = color_back;
label.position = ccp(x+1, y-1);
[self addChild:label];
When a button is pressed, I am modifying player->name along with several other variables. Because several variable are changing (on this screen and eventually others) when the button is pressed I also set a flag to indicate that the screen needs to be refreshed. I then check this code with a scheduler:
if(panelPrev != currentPanel || refreshScreen) //do we need to initialize the panel?
{
[self removeAllChildrenWithCleanup:true]; //clear all objects from display
//Decide which objects to display
switch (G_display_panel) {
case P_Main:
[Display_Main init_Panel:self];
break;
case P_NewGame:
[Display_New init_Panel:self];
break;
default:
break;
}
refreshScreen = false;
}
My first question: Is this an acceptable way to display things to the screen and refresh them? It seemed much more convenient than updating every variable that is being displayed. The buttons are not being pressed very often so I am not concerned about performance.
Second: If it is ok to do it this way, why is it that when I press a button and change the value of player->name I am getting this: "Thread 1: EXC_BAD_ACCESS (code=1, address=...)"? If I step through with the debugger the value gets assigned to player->name correctly and the screen refresh works. But if I just let it run it gets the EXC_BAD_ACCESS when I try to access player->name and the data looks corrupted (e.g. (NSString *) name = 0x15927f80 when I am expecting (NSString *) name = #"Bob").
Some additional details.
I am not setting refreshScreen to 'true' until after changing the value of player->name
To prevent refreshing before the value was truly changed, I set a delay on the refresh. After the button was pressed I would modify player->name and wait about 10 seconds but I would still see the same problem.
Any ideas? Thanks.
try this:
[self addChild:label];
I figured out the problem. It was a memory management issue. I added a getter and setter for the variable using the example specified here: developer.apple.com/library/mac/documentation/Cocoa/Conceptual/… –

UISteppper connect with textField

How do I connect UIstepper with textField? When I connect it increment and decrement but, when I directly enter number to textfield after that try to increment by using stepper the value will start from the stepper minimum value. I want to continue from the textField value.
There is no binding in iOS development like you want. Basically you have to decide where you want to store your values. You could store your values in the stepper, in the textfield, or in some other variable entirely.
Secondly, but no less importantly, your stepper target function is all wrong. Your problem is that you are re-setting up your stepper each time the stepperPressed1: method is fired. Which I hope is connected to your stepper's valueChanged event, and I'll assume it is.
Let's for the moment assume that you are trying to store your numerical stepped value in the stepper.
You should be setting up your stepper only once, likely in your viewDidLoad method. And then reading the new value when the value changes and writing that to your text field.
For Example:
-(void)viewDidLoad{
[super viewDidLoad];
[self.stepper setMinimumValue:0];
[self.stepper setContinuous:YES];
[self.stepper setWraps:NO];
[self.stepper setStepValue:1];
[self.stepper setMaximumValue:300];
self.txtField.text=[NSString stringWithFormat:#"%g",self.stepper.value];
}
-(IBAction)stepperPressed1:(id)sender{
self.txtField.text=[NSString stringWithFormat:#"%g",self.stepper.value];
}
Now as far as setting the value in the stepper based on what is typed in the textfield. What you need to do is when the user is done typing in a value you want to get that value and assign it to the stepper. You would connect a function to the textField's "Did End On Exit" event. That function would look something like this:
-(IBAction)didEndOnExit:(id)sender {
self.stepper.value = self.txtField.text.doubleValue;
self.txtField.text=[NSString stringWithFormat:#"%g",self.stepper.value];
}

Resources