I have strange problem with radio button. I used UIButton for radio button and used two image btnCheck.png and btnUnCheck.png in normal case its working properly there is no problem. this is my code on button click
-(IBAction)btnNextClick:(id)sender {
UIImage* selectedImg=[UIImage imageNamed:#"btnCheck.png"];
if ((btnILink.imageView.image == selectedImg || btnTapeIn.imageView.image == selectedImg || btnKeraLink.imageView.image == selectedImg))
{
if (btnTapeIn.imageView.image == selectedImg) {
UIImage* selectedImg1=[UIImage imageNamed:#"btnCheck.png"];
if (!(btn18.imageView.image == selectedImg1 || btn22.imageView.image == selectedImg1)){
[FunctionManager showMessage:#"" withMessage:#"Please Select Length" withDelegage:nil];
return;
}
}
else {
UIImage* selectedImg1=[UIImage imageNamed:#"btnCheck.png"];
if (!(btn16.imageView.image == selectedImg1 || btn18.imageView.image == selectedImg1 || btn22.imageView.image == selectedImg1)){
[FunctionManager showMessage:#"" withMessage:#"Please Select Length" withDelegage:nil];
return;
}
}
}
else {
[FunctionManager showMessage:#"" withMessage:#"Please Select Method" withDelegage:nil];
return;
}
}
its working properly when I click on btnNext, if no any one item is selected then it display message. but problem is When I select the both item and go in background then I comeback in the app and click on next then it display the message, but Check box already selected. why the condition is not true in that case...
Yes It will do so, because you compared UIImage object Like:
UIImage* selectedImg=[UIImage imageNamed:#"btnCheck.png"];
if ((btnILink.imageView.image == selectedImg || btnTapeIn.imageView.image == selectedImg || btnKeraLink.imageView.image == selectedImg))
Every time when its came from background it sets Create new UIImage object So it can not be the same object.
So instead of comparing object(btnILink.imageView.image == selectedImg) take a bool Value it will work fine.
Use Buttons selected property instead of image when click on that button for checking
like
if(btnTapeIn.selected)
{
[btnTapeIn setImage:[UIImage imageNamed:#"btnUnCheck.png"] forState:UIControlStateNormal];
btnTapIn.selected = NO;
}
else
{
[btnTapeIn setImage:[UIImage imageNamed:#"btnCheck.png"]forState:UIControlStateNormal];
btnTapIn.selected = YES;
}
https://github.com/Brayden/UICheckbox
You can implement this and decrease the comparison logic.
You should not compare by the button's set image. Use the button's built in selected property for example.
btnTapeIn.selected = YES;
...
if(btnTapeIn.isSelected)
...
- (IBAction)btn_GenderCheck:(id)sender {
switch ([sender tag])
{
case 1: //-------for Male
[btn_malecheck setImage:[UIImage imageNamed:#"radio_select.png"] forState:UIControlStateNormal];
[btn_femalecheck setImage:[UIImage imageNamed:#"radio.png"] forState:UIControlStateNormal];
isMaletag=1;
break;
case 2: //----------for Female
[btn_malecheck setImage:[UIImage imageNamed:#"radio.png"] forState:UIControlStateNormal];
[btn_femalecheck setImage:[UIImage imageNamed:#"radio_select.png"] forState:UIControlStateNormal];
isMaletag=2;
break;
default:
break;
}
}
// then you can check tag and accordingly alert your message
You can set images in for normal state and selected in XIB and change the state in IBAction
Related
I'm making a matching game in iOS using objective-C
there's a 12 set of cards (3 columns and 4 rows) which is an array of UIButton connected to IBOutletCollection,the problem is when you tap the first card, you can also tap the other cards simultaneously, but the allowable card to tap must be only 2 cards. How can I prevent tapping of cards, if the tapped cards are greater than 1 and less than 2.
//One action for all buttons
-(void)buttonAction:(UIButton*)button
{
//if user select three button at a time, dont do further operations
if (previousButton && currentButton) {
return;
}
//previous button is the first button
if(previousButton==nil)
{
previousButton=button;
}
//current button is the second button
else if(currentButton==nil)
{
currentButton=button;
}
//if button is selected, set button as not selected and vice versa
if([button isSelected]==NO)
{
[button setSelected:YES];
}
else
{
[button setSelected:NO];
}
//if user press the same button again and again
if (currentButton==previousButton)
{
currentButton=nil;
if([previousButton isSelected]==NO)
{
previousButton=nil;
}
return;
}
else if((currentButton!=previousButton)&&(currentButton!=nil))
{
//both button tags are same, that means both selected state images are same
if(previousButton.tag==currentButton.tag)
{
[self performSelector:#selector(delay) withObject:nil afterDelay:0.5];
}
else
{
[self performSelector:#selector(delayTwo) withObject:nil afterDelay:0.5];
}
}
}
-(void)delay
{
//[currentButton setHidden:YES];
//[previousButton setHidden:YES];
currentButton=nil;
previousButton=nil;
score++;
NSLog(#"Score %d",score);
//the final stage, that means left only two buttons
if(score==6)
{
//[self endGame];
}
}
-(void)delayTwo
{
[currentButton setSelected:NO];
[previousButton setSelected:NO];
currentButton=nil;
previousButton=nil;
}
In viewDidLoad, assign all button selected & normal state images or title as you required
I'm not 100% sure what you are getting at here, but you could try having multiple UITapGestureRecognizer instances. You could have one for 1 tap, one for 2, and one for 3+. That way, you can select the cards for 1 or 2 touches, but ignore it if there are 3 or more.
I have a check box designed through a button and i am able to change the checkbox images but i am unable to save that last image that is checked in the checkbox when i click on Save button.
I have a page in which a check box is there and save button action is also there when i click on save the value in the checkbox must be saved and when i again re-enter in that screen the previous whatever the value in the checkbox must be seen, but for me every time when i enter into this screen the checkbox is seen empty.
Hope someone helps me out.
BOOL checked;
- (IBAction)canFollowAction:(id)sender
{
UIButton *tappedButton = (UIButton*)sender;
if([tappedButton.currentImage isEqual:[UIImage imageNamed:#"checkBox.png"]])
{
[sender setImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateNormal];
}
else
{
[sender setImage:[UIImage imageNamed:#"checkBox.png"]forState:UIControlStateNormal];
}
}
- (IBAction)btnSaveAction:(id)sender
{
if(checked)
{
[btnCheckCanFollow setImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateNormal];
}
else
{
[btnCheckCanFollow setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
[self.navigationController popViewControllerAnimated:YES];
[[[iToast makeText:#"Successfully Updated"]setGravity:iToastGravityBottom]show];
}
#kool kims - The term you used Save value. There any many ways to keep persistent data of your application.
Use NSUserDefaults to save values at application level.
Use .plist file
CoreData
SQlite
Document directory
As per your application architecture you can choose from above, which is more relevant and efficient for your application.
EDIT:
The simplest way if there are not more than one checkbox, You can use NSUserDefaults
Save check value when you click on Save button
- (IBAction)btnSaveAction:(id)sender
{
NSNumber *checkValue = [NSNumber numberWithBool:checked];
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
[standardDefaults setObject:checked forKey:#"kCheckBoxValue"];
[standardDefaults synchronize];
if(checked)
{
[btnCheckCanFollow setImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateNormal];
}
else
{
[btnCheckCanFollow setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
[self.navigationController popViewControllerAnimated:YES];
[[[iToast makeText:#"Successfully Updated"]setGravity:iToastGravityBottom]show];
}
Whenever you open that ViewController you get previous values from NSUserDefaults from -viewDidLoad or -viewWillAppear.
- (void)viewDidLoad {
[super viewDidLoad];
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
if ([standardDefaults objectForKey:#"kCheckBoxValue"]) {
NSNumber *checkValue = [standardDefaults objectForKey:#"kCheckBoxValue"];
checked = [checkValue boolValue];
} else {
checked = NO;
}
}
You Must Save the state in NSUSERDEFAULTS!
For Example ON Button Click
if (button.selected)
{
[button setSelected:YES];
[[NSUserDefaults standardUserDefaults]setObject:[NSNumber numberWithBool:YES] forKey:#"REMEMBER_ME"];
}
and check on ViewDidLoad
if([[NSUserDefaults standardUserDefaults] boolForKey:#"REMEMBER_ME"] == YES)
{
[button setSelected:YES];
[button setImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateSelected];
}
else
{
[button setSelected:NO];
[button setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
Take a global variable to strore the status of check box or in NSUserdefaults u can save the status of button. & chek this status on viewdidload method of controller.
According to what I understood Lets take an example
#property (weak, nonatomic) IBOutlet UIButton *yourButton;
and its Implementation Action
- (IBAction)yourMethodName:(UIButton *)sender {
int tag=_yourButton.tag; //if you have tagged your UI button save it to know which button has changed its state.
if(sender.isSelected){ //Checking state of the button whether selected or not.
UIImage *buttonImage=sender.currentImage;//save this image if your selected images randomly.
NSString *buttonText=sender.currentTitle;//gets you current text in button.
}else{
//selected state is NO
//checkBox is Off.
}
}
here I have showed how you can get different values you need only to store your state as I believe your working with one button/checkbox and you can populate your image based on that state.
However if you have multiple checkboxes or UIbutton you may want to Tag each UIButton your using
[_yourButton setTag:1];
and store tag value too inside action method using sender.tag
EDIT:
Just now went through your code
BOOL checked; value is never set or stored.
so everytime if condition fails.
Also If you have multiple UIButtons you may want to store checked state and tag for the UIButton as I have mentioned earlier;
I have eight (8) UIButtons setup in my game. When one is selected it shows that it is selected and if you click it again it will show as unselected. However, I want to make it so that when you select a button and any of the other seven (7) are selected, they become unselected.
I know how to do this through the use of [buttonName setSelected:NO] but the problem is I can't pass buttonOne to buttonTwo if buttonTwo has already been passed to buttonOne because I have already imported buttonTwo's header file in buttonOne. It throws a parse error if I have both headers importing each other. I've been stuck on this for a while now and was hoping that someone might have a solution to my problem.
Thanks for any help.
Get the parent view of the current button and iterate through all the buttons inside, unselecting all of them. Then, select the current one.
// Unselect all the buttons in the parent view
for (UIView *button in currentButton.superview.subviews) {
if ([button isKindOfClass:[UIButton class]]) {
[(UIButton *)button setSelected:NO];
}
}
// Set the current button as the only selected one
[currentButton setSelected:YES];
Note: As suggested on the comments, you could keep an array of buttons and go over it the same way the above code does with the subviews of the parent view. This will improve the performance of your code in case the view containing the buttons has many other subviews inside.
I know its too late to answer this question but I did it in only small lines of code . Here is what i did :
NSArray *arrView = self.view.subviews;
for (UIButton *button in arrView) {
if ([button isKindOfClass:[UIButton class]]) {
[((UIButton *) button) setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
}
}
[button1 setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
Simple way to do.
-(void)buttonSelected:(id)sender{
UIButton *currentButton = (UIButton *)sender;
for(UIView *view in self.view.subviews){
if([view isKindOfClass:[UIButton class]]){
UIButton *btn = (UIButton *)view;
[btn setSelected:NO];
}
}
[currentButton setSelected:YES];
}
I actually created an answer by reading all of your guys input, which I thank you greatly for. The tag property of the UIButton class was unknown to me before this post.
I created own subclass of UIButton, let's call it CustomUIButton.m. I created a NSMutableArray property for use when storing the buttons, which I'll call customButtonArray.
When I created the button, I set the tag property, and added the button to a local array on the parent view controller. After all buttons I wanted were created, I set the customButtonArray, like so:
// Initialize buttonHolderArray
NSMutableArray *buttonHolderArray = [[NSMutableArray alloc] init];
// Create a button
CustomUIButton *newButton = [[CustomUIButton alloc] initWithFrame:CGRectMake(10, 10, 50, 30)];
newButton.tag = 1;
[newButton setImage:[UIImage imageNamed:#"newButtonUnselected" forControlState:UIControlStateNormal]];
[buttonHolderArray addObject:newButton];
// Create additional buttons and add to buttonHolderArray...
// using different numbers for their tags (i.e. 2, 3, 4, etc)
// Set customButtonArray property by iterating through buttonHolderArray
NSInteger buttonCount = [buttonHolderArray count];
for (int i = 0; i < buttonCount; i++)
{
[[buttonHolderArray objectAtIndex:i] setCustomButtonArray:buttonHolderArray];
}
To deselect any other button selected when a different buttons handleTap: is called, I iterated through the customButtonArray in the subclass main file and set the selected property to NO. I also set the correct image from another array property that I manually populated with the images, which I did so the array didn't have to be populated every time a button was pressed. At the end, unselected all other buttons, like so:
// Populate two arrays: one with selected button images and the other with
// unselected button images that correspond to the buttons index in the
// customButtonArray
NSMutableArray *tempSelectedArray = [[NSMutableArray alloc] init];
[tempSelectedArray addObject:[UIImage imageNamed:#"newButtonSelected"]];
// Add the other selected button images...
// Set the property array with this array
[self setSelectedImagesArray:tempSelectedArray];
NSMutableArray *tempUnselectedArray = [[NSMutableArray alloc] init];
[tempUnselectedArray addObject:[UIImage imageNamed:#"newButtonUnselected"]];
// Add the other unselected button images...
// Set the property array with this array
[self setUnselectedImagesArray:tempUnselectedArray];
- (void)handleTap:(UIGestureRecognizer *)selector
{
// Get the count of buttons stored in the customButtonArray, use an if-elseif
// statement to check if the button is already selected or not, and iterate through
// the customButtonArray to find the button and set its properties
NSInteger buttonCount = [[self customButtonArray] count];
if (self.selected == YES)
{
for (int i = 0; i < buttonCount; i++)
{
if (self.tag == i)
{
[self setSelected:NO];
[self setImage:[[self unselectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
}
}
}
else if (self.selected == NO)
{
for (int i = 0; i < buttonCount; i++)
{
if (self.tag == i)
{
[self setSelected:NO];
[self setImage:[[self selectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
}
}
}
for (int i = 0; i < buttonCount; i++)
{
if (self.tag != i)
{
[self setSelected:NO];
[self setImage:[[self unselectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
}
}
}
Thanks for all of the useful information though, figured I should share the final answer I came up with in detail to help anyone else that comes across this problem.
I figured out a pretty easy way to solve this. My example is for 2 buttons but you can easily add more if statements for additional buttons. Connect all buttons to the .h file as properties and name them (I did button1 & button2). Place the following code in your .m file and Connect it (via the storyboard) to all of your buttons. Make sure when you are setting up your button to set an image for BOTH the normal UIControlStateNormal & UIControlStateSelected or this wont work.
- (IBAction)selectedButton1:(id)sender {
if ([sender isSelected]) {
[sender setSelected:NO];
if (sender == self.button1) {
[self.button2 setSelected:YES];
}
if (sender == self.button2) {
[self.button1 setSelected:YES];
}
}
else
{
[sender setSelected:YES];
if (sender == self.button1) {
[self.button2 setSelected:NO];
}
if (sender == self.button2) {
[self.button1 setSelected:NO];
}
}
To answer "It throws a parse error if I have both headers importing each other"...
You should refrain from using #import in .h files as much as possible and instead declare whatever you're wanting to use as a forward class declaration:
#class MyCustomClass
#interface SomethingThatUsesMyCustomClass : UIViewController
#property (nonatomic, strong) MyCustomClass *mcc;
#end
Then #import the header in your .m file:
#import "MyCustomClass.h"
#implementation SomethingThatUsesMyCustomClass
-(MyCustomClass *)mcc
{
// whatever
}
#end
This approach will prevent errors caused by #import cycles.
Though I must say I agree with SergiusGee's comment on the question that this setup feels a bit strange.
The easiest approach here would be to get the parent UIView the buttons are on and iterate through it. Here's a quick example from my code:
for (UIView *tmpButton in bottomBar.subviews)
{
if ([tmpButton isKindOfClass:[UIButton class]])
{
if (tmpButton.tag == 100800)
{
tmpButton.selected = YES;
[tmpButton setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
[tmpButton setTitleColor:[UIColor greenColor] forState:UIControlStateHighlighted];
}else{
tmpButton.selected = NO;
[tmpButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[tmpButton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
}
}
}
Did you try using ReactiveCocoa framework and add some blocks for your code , this is not the most simple approach yet i would say it is the most effective when you have multiple dependencies and very good for scaling
I have created a small project for a solution to your problem using my suggested approach (I tried to adapt it to the good old MVC pattern instead of my preferred MVVM)
you can find it here
https://github.com/MWaly/MWButtonExamples
make sure to install cocoa pods file as we need "ReactiveCocoa" and "BlocksKit" for this sample
we will use two main classes
ViewController => The viewController object displaying the buttons
MWCustomButton => Custom UIButton which handles events
when creating the buttons a weak reference to the viewController is also created using the property
#property (weak) ViewController *ownerViewController ;
events will be handled using the help of blocksKit bk_addEventHandler method and pass it to the block of the ViewController (selectedButtonCallBackBlock)
[button bk_addEventHandler:^(id sender)
{
self.selectedButtonCallBackBlock(button);
} forControlEvents:UIControlEventTouchUpInside];
now in the ViewController for each button touched the callBackButtonBlock will be trigerred , where it will change its currently selected button if applicable
__weak __typeof__(self) weakSelf = self;
self.selectedButtonCallBackBlock=^(MWCustomButton* button){
__typeof__(self) strongSelf = weakSelf;
strongSelf.currentSelectedButton=button;
};
in the MWCustomButton class , it would listen for any changes in the property of "currentSelectedButton" of its ownerViewController and will change its selection property according to it using our good Reactive Cocoa
///Observing changes to the selected button
[[RACObserve(self, ownerViewController.currentSelectedButton) distinctUntilChanged] subscribeNext:^(MWCustomButton *x) {
self.selected=(self==x);
}];
i think this would solve your problem , again your question might be solved in a simpler way , however i believe using this approach would be more scalable and cleaner.
Loop through all views in parent view. Check if it is a UIButton(or your custom button class) and not the sender. Set all views isSelected to false. Once loop is finished, set sender button isSelected to true.
Swift 3 way:
func buttonPressed(sender: UIButton) {
for view in view.subviews {
if view is UIButton && view != sender {
(view as! UIButton).isSelected = false
}
}
sender.isSelected = true
}
Swift 4
//Deselect all tip buttons via IBOutlets
button1.isSelected = false
button2.isSelected = false
button3.isSelected = false
//Make the button that triggered the IBAction selected.
sender.isSelected = true
//Get the current title of the button that was pressed.
let buttonTitle = sender.currentTitle!
I have made 20 Buttons dynamically, and I got the tag values of all Buttons.
But I need to know how to use that tag values.
I need information on every button pressed with tag values.
So, how do I use those tag values?
You need to set target-action of each button.
[button setTarget:self action:#selector(someMethod:) forControlEvents:UIControlEventTouchUpInside];
Then implement someMethod: like this:
- (void)someMethod:(UIButton *)sender {
if (sender.tag == 1) {
// do action for button with tag 1
} else if (sender.tag == 2) {
// do action for button with tag 2
} // ... and so on
}
Why do you need to use the tag to get the button. You can directly get the buttons reference from its action method.
- (void)onButtonPressed:(UIButton *)button {
// "button" is the button which is pressed
NSLog(#"Pressed Button: %#", button);
// You can still get the tag
int tag = button.tag;
}
I hope you have added the target-action for the button.
[button addTarget:self action:#selector(onButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
You can get reference to that your buttons using that tags. For example, you've added UIButtons to UIView *mainView. To get reference to that buttons you should write following:
UIButton *buttonWithTag1 = (UIButton *)[mainView viewWithTag:1];
Set the tags like this :
for (createButtonIndex=0; createButtonIndex<buttonsCount; createButtonIndex++)
{
buttonCaps.tag=createButtonIndex;
}
And add the method to trap the tags :-
-(void)buttonsAction:(id)sender
{
UIButton *instanceButton = (UIButton*)sender;
switch(instanceButton.tag)
{
case 1(yourTags):
//Code
break;
case 2:
//Code
break;
}
}
Hope this Helps !!
- (IBAction)buttonPressed:(id)sender {
UIButton selectedButton = (UIButton *)sender;
NSLog(#"Selected button tag is %d%", selectedButton.tag);
}
usefully we use btn tag if You Write One Function For (more than one) Buttons .in action if we want to write separate Action For button at that situvation we use btn tag.it can get two ways
I) case sender.tag
//if we have four buttons Add,mul,sub,div having Same selector and add.tag=10
mul.tag=20,sub.tag=30,div.tag=40;
-(IBAction) dosomthing:(id)sender
{
int x=10;
int y=20;
int result;
if(sender.tag==10)
{
result=x+y;
}else if(sender.tag==20)
{
result=x*y;
}else if(sender.tag==30)
{
result=x-y;
}else if(sender.tag==40)
{
result=x/y;
}
NSLog(#"%i",result);
}
2)Case
UIButton *btn=[self.view viewWithTag:10];
then you got object of add button uyou can Hide It With btn.hidden=YES;
UIButton *btn = (UIButton *)[mainView viewWithTag:button.tag];
I have an UIButton array like this:
#property (nonatomic, retain) IBOutletCollection(UIButton) NSArray *btn_Impact_Collection;
and I have this function:
- (IBAction)impactAction:(id)sender;
In the XIB file I have nine button, each button is connected to btn_Impact_Collection Array with the Referencing Outlet Collection. Moreover the Touch_inside property of each button is connected to the function ImpactAction.
Now, when a button is clicked the ImpactAction function is called, but inside this function, how can i know which button is pressed?
Thanks in advance for the answer!
Cast sender to UIButton class, and that will give you the instance of the clicked button. I don't have Xcode with me but something like:
if ([sender isMemberOfClass:[UIButton class]])
{
UIButton *btn = (UIButton *)sender;
// Then you can reference the title or a tag of the clicked button to do some further conditional logic if you want.
if([btn.currentTitle isEqualToString:#"title of button"])
{
// do something.
}
else if(etc...)
}
Set tags for each button in interface builder (1-9), then say
if ([sender tag] == 1) {
//First button was pressed, react.
}
else if ([sender tag] == 2) {
//Second button was pressed, react.
}
// Etc...
else {
//Last button was pressed, react.
}
And the same for all the others, or you could put it in a switch.
Rather than do a string check on the title (which is slow and can be tedious) you can:
- (void)buttonPressed:(id)sender
{
for( UIButton *button in self.buttonCollection )
{
if( sender == button )
{
// sender is your button (eg. you can access its tag)
}
}
}
Another option.. Cast sender to check if it's a UIButton, then switch sender.tag:
if ([sender isMemberOfClass:[UIButton class]]) {
switch ([sender tag]) {
case 0:
//do stuff for button with tag 0
break;
case 1:
//do stuff for button with tag 1
break;
case 2:
....
break;
default:
break;
}
}