View is not updating when the button is clicked - ios

The problem is that when the button is clicked, it is not updating! it is not hiding or showing the objects like it's written in the code. What am I missing?
viewcontroller.h
#interface ViewController : UIViewController {
BOOL clicked1;
BOOL clicked2;
}
#property (strong, nonatomic) IBOutlet UIImageView *buttonbg1;
#property (strong, nonatomic) IBOutlet UIImageView *buttonbg11;
#property (strong, nonatomic) IBOutlet UIImageView *buttonbg111;
#property (strong, nonatomic) IBOutlet UIButton *exaa1;
#property (strong, nonatomic) IBOutlet UIButton *exab2;
- (IBAction)exaa1:(id)sender;
- (IBAction)exab2:(id)sender;
#end
viewcontroller.m
- (IBAction)exaa1:(id)sender {
clicked1 = YES;
}
- (IBAction)exab2:(id)sender {
clicked2 = YES;
}
- (void)example1 {
[_exaa1 setTitle:#"1111" forState:UIControlStateNormal];
[_exab2 setTitle:#"2222" forState:UIControlStateNormal];
if (clicked1) {
_buttonbg111.hidden = NO;
_buttonbg11.hidden = YES;
_buttonbg1.hidden = YES;
NSLog(#"1");
} else if(clicked2) {
_buttonbg11.hidden = NO;
_buttonbg1.hidden = YES;
_buttonbg111.hidden = YES;
NSLog(#"2");
}
}

*- (IBAction)exaa1:(id)sender {
clicked1 = YES;
[self example1];
}
- (IBAction)exab2:(id)sender {
clicked2 = YES;
[self example1];
}
- (void)example1 {
[_exaa1 setTitle:#"1111" forState:UIControlStateNormal];
[_exab2 setTitle:#"2222" forState:UIControlStateNormal];
if (clicked1) {
_buttonbg111.hidden = NO;
_buttonbg11.hidden = YES;
_buttonbg1.hidden = YES;
NSLog(#"1");
} else if(clicked2) {
_buttonbg11.hidden = NO;
_buttonbg1.hidden = YES;
_buttonbg111.hidden = YES;
NSLog(#"2");
}
}*

You just forget to call your method example1 in your both IBActions Method. YOu just write down [self example1] into both of the IBActions method. And you will get your exact output.

you forgot to call example1 method in both button IBAction methods

Please refer the following corrected code
- (IBAction)exaa1:(id)sender {
clicked1 = YES;
clicked2 = NO;
[self example1];
}
- (IBAction)exab2:(id)sender {
clicked2 = YES;
clicked1 = NO;
[self example1];
}
- (void)example1 {
[_exaa1 setTitle:#"1111" forState:UIControlStateNormal];
[_exab2 setTitle:#"2222" forState:UIControlStateNormal];
if (clicked1) {
_buttonbg111.hidden = NO;
_buttonbg11.hidden = YES;
_buttonbg1.hidden = YES;
NSLog(#"1");
} else if(clicked2) {
_buttonbg11.hidden = NO;
_buttonbg1.hidden = YES;
_buttonbg111.hidden = YES;
NSLog(#"2");
}
}

Related

My custom UIButton can't be used to replace leftBarButtonItem

I created a custom UIButton subclassing from UIControl (It is called "OZCustomButton"). It works fine in Storyboard, however when I was trying to use it to replace the leftBarButtonItem back button programmatically, it had a problem with its layout.
Here is the code I use to replace the leftBarButtonItem.
OZCustomButton *customBackButton = [[OZCustomButton alloc] initWithFrame:CGRectZero];
customBackButton.buttonImage = [UIImage imageNamed:#"BackArrow"];
customBackButton.buttonText = #"Back";
[customBackButton sizeToFit];
NSLog(#"this size: %#", NSStringFromCGRect(customBackButton.frame));
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customBackButton];
self.navigationItem.leftBarButtonItem = item;
But nothing is showing on the left side of the navigation bar.
Navigation bar:
And the Dubug View Hierarchy tool shows these warning messages:
It seems the customBackButton is in the View Hierarchy, but the layout is not correct.
This is the code for my OZCustomButton.
OZCustomButton.h:
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
IB_DESIGNABLE
#interface OZCustomButton : UIControl <NSCoding>
#property (assign, nonatomic) IBInspectable CGFloat borderWidth;
#property (assign, nonatomic) IBInspectable CGFloat borderRadius;
#property (strong, nonatomic) IBInspectable UIColor *borderColor;
#property (strong, nonatomic) IBInspectable UIColor *fillColor;
#property (strong, nonatomic) IBInspectable UIColor *tintColor;
#property (strong, nonatomic) IBInspectable NSString *buttonText;
#property (assign, nonatomic) IBInspectable CGFloat textSize;
#property (assign, nonatomic) IBInspectable BOOL isTextBold;
#property (strong, nonatomic) UIFont *textFont;
#property (nullable, strong, nonatomic) IBInspectable UIImage *buttonImage;
#property (nullable, strong, nonatomic) NSArray *gradientColors;
#end
NS_ASSUME_NONNULL_END
OZCustomButton.m
#import "OZCustomButton.h"
#import "UIColor+Custom.h"
#import "CAGradientLayer+Utilities.h"
#interface OZCustomButton ()
#property (strong, nonatomic) UILabel *buttonLabel;
#property (nullable, strong, nonatomic) UIImageView *buttonImageView;
#property (nullable, strong, nonatomic) CAGradientLayer *gradientLayer;
#property (nullable, strong, nonatomic) UIStackView *stackView;
#end
#implementation OZCustomButton
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupDefaults];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self setupDefaults];
}
return self;
}
- (void)layoutLabelAndImageView {
_buttonLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_buttonLabel.numberOfLines = 1; // need to set to 1
_buttonLabel.textAlignment = NSTextAlignmentCenter;
//_buttonLabel.backgroundColor = [UIColor redColor];
_buttonImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
_buttonImageView.contentMode = UIViewContentModeScaleAspectFit;
//_buttonImageView.backgroundColor = [UIColor redColor];
_stackView = [[UIStackView alloc] init];
_stackView.axis = UILayoutConstraintAxisHorizontal;
_stackView.alignment = UIStackViewAlignmentCenter;
_stackView.distribution = UIStackViewDistributionFillProportionally;
_stackView.spacing = 8;
_stackView.userInteractionEnabled = NO;
[_stackView addArrangedSubview:_buttonImageView];
[_stackView addArrangedSubview:_buttonLabel];
_stackView.translatesAutoresizingMaskIntoConstraints = false;
[self addSubview:_stackView];
[[_stackView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES];
[[_stackView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor] setActive:YES];
}
- (void)layoutGradientLayer {
_gradientLayer = [CAGradientLayer createGradientLayerWithBounds:self.bounds
colors:nil
direction:GradientFromLeftTopToRightBottom
locations:#[#0.0, #1.0]];
_gradientLayer.anchorPoint = CGPointMake(0, 0);
[self.layer insertSublayer:_gradientLayer below:_stackView.layer];
}
- (void)setupDefaults {
_borderWidth = 0.0f;
_borderRadius = 0.0f;
_borderColor = [UIColor blackColor];
_fillColor = [UIColor whiteColor];
_buttonText = #"Button";
_tintColor = [UIColor blackColor];
_textSize = 17.0f;
_isTextBold = false;
_textFont = _isTextBold ? [UIFont fontWithName:#"AlteHaasGrotesk_Bold" size:_textSize] : [UIFont fontWithName:#"AlteHaasGrotesk" size:_textSize];
_gradientColors = nil;
_buttonImage = nil;
[self layoutLabelAndImageView];
[self updateView];
}
- (void)updateView {
self.layer.borderColor = _borderColor.CGColor;
self.layer.borderWidth = _borderWidth;
self.layer.cornerRadius = _borderRadius;
self.layer.masksToBounds = true;
self.layer.backgroundColor = _fillColor.CGColor;
// update button text label
_buttonLabel.text = _buttonText;
_buttonLabel.textColor = _tintColor;
_textFont = _isTextBold ? [UIFont fontWithName:#"AlteHaasGrotesk_Bold" size:_textSize] : [UIFont fontWithName:#"AlteHaasGrotesk" size:_textSize];
_buttonLabel.font = _textFont;
_buttonLabel.textAlignment = NSTextAlignmentCenter;
[_buttonLabel sizeToFit];
// update button image
if (_buttonImage != nil) {
_buttonImageView.hidden = NO;
_buttonImageView.image = [_buttonImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_buttonImageView.tintColor = _tintColor;
[_buttonImageView sizeToFit];
} else {
_buttonImageView.image = nil;
_buttonImageView.hidden = YES;
[_buttonImageView sizeToFit];
}
// update gradient layer
if (_gradientColors != nil) {
// if gradient layer is not initialized, call layoutGradientLayer()
if (_gradientLayer == nil) {
[self layoutGradientLayer];
}
// transform the UIColor to CGColorRef
NSMutableArray *colors = [NSMutableArray arrayWithCapacity:_gradientColors.count];
for (UIColor *color in _gradientColors) {
[colors addObject:(id)[color CGColor]];
}
if (colors.count > 0) {
_gradientLayer.colors = [colors copy];
}
}
}
#pragma mark - setters
- (void)setTextSize:(CGFloat)textSize {
if (_textSize != textSize) {
_textSize = textSize;
_textFont = _isTextBold ? [UIFont fontWithName:#"AlteHaasGrotesk_Bold" size:_textSize] : [UIFont fontWithName:#"AlteHaasGrotesk" size:_textSize];
[self updateView];
}
}
- (void)setBorderColor:(UIColor *)borderColor {
if (_borderColor != borderColor) {
_borderColor = borderColor;
[self updateView];
}
}
- (void)setBorderWidth:(CGFloat)borderWidth {
if (_borderWidth != borderWidth) {
_borderWidth = borderWidth;
[self updateView];
}
}
- (void)setBorderRadius:(CGFloat)borderRadius {
if (_borderRadius != borderRadius) {
_borderRadius = borderRadius;
[self updateView];
}
}
- (void)setFillColor:(UIColor *)fillColor {
if (_fillColor != fillColor) {
_fillColor = fillColor;
[self updateView];
}
}
- (void)setTintColor:(UIColor *)tintColor {
if (_tintColor != tintColor) {
_tintColor = tintColor;
[self updateView];
}
}
- (void)setButtonText:(NSString *)buttonText {
if (_buttonText != buttonText) {
_buttonText = buttonText;
[self updateView];
}
}
- (void)setTextFont:(UIFont *)textFont {
if (_textFont != textFont) {
_textFont = textFont;
[self updateView];
}
}
- (void)setGradientColors:(NSArray *)gradientColors {
if (_gradientColors != gradientColors) {
_gradientColors = gradientColors;
[self updateView];
}
}
- (void)setButtonImage:(UIImage *)buttonImage {
if (_buttonImage != buttonImage) {
_buttonImage = buttonImage;
[self updateView];
}
}
- (void)setIsTextBold:(BOOL)isTextBold {
if (_isTextBold != isTextBold) {
_isTextBold = isTextBold;
[self updateView];
}
}
#pragma mark - UIControl actions
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
fadeAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
fadeAnimation.duration = 0.2f;
if (highlighted) {
fadeAnimation.toValue = #0.6f;
} else {
fadeAnimation.toValue = #1.0f;
}
self.buttonLabel.layer.opacity = [fadeAnimation.toValue floatValue];
self.layer.opacity = [fadeAnimation.toValue floatValue];
[self.buttonLabel.layer addAnimation:fadeAnimation forKey:#"textFadeAnimation"];
[self.layer addAnimation:fadeAnimation forKey:#"backgroundFadeAnimation"];
}
- (void)setEnabled:(BOOL)enabled {
[super setEnabled:enabled];
if (enabled) {
self.layer.backgroundColor = self.fillColor.CGColor;
self.buttonLabel.textColor = self.tintColor;
} else {
self.layer.backgroundColor = [UIColor lighterColorForColor:self.fillColor].CGColor;
self.buttonLabel.textColor = [UIColor lightGrayColor];
}
}
#pragma mark - Override functions
- (void)layoutSubviews {
[super layoutSubviews];
[self updateView];
}
- (CGSize)sizeThatFits:(CGSize)size {
CGFloat minWidth = _buttonImageView.frame.size.width + 8 + _buttonLabel.frame.size.width;
CGFloat minHeight = MAX(_buttonImageView.frame.size.height, _buttonLabel.frame.size.height);
return CGSizeMake(minWidth + 6, minHeight + 4);
}
#end
I found one solution. Instead of setting the centenX anchor and centerY anchor, I change it to using left, right, top and bottom anchors:
[[_stackView.topAnchor constraintEqualToAnchor:_stackView.superview.topAnchor] setActive:YES];
[[_stackView.bottomAnchor constraintEqualToAnchor:_stackView.superview.bottomAnchor] setActive:YES];
[[_stackView.leftAnchor constraintEqualToAnchor:_stackView.superview.leftAnchor] setActive:YES];
[[_stackView.rightAnchor constraintEqualToAnchor:_stackView.superview.rightAnchor] setActive:YES];
Then it got the layout correctly.
If you have any other methods to solve the problem, please let me know.

iOS Objective-C block callback issue

I am trying to use pure code to create UI practice block pass value between viewController. But the callback block didn't work. The NSLog method didn't print anything on debug area. Here's the code. Give me some tips, thank you.
VC.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController
#property (copy, nonatomic) void (^callBack)(NSString *text);
#end
VC.m
- (UITextField *)textField {
if (!_textField) {
_textField = [[UITextField alloc] init];
_textField.backgroundColor = [UIColor whiteColor];
}
return _textField;
}
- (UIButton *)button {
if (!_button) {
_button = [[UIButton alloc] init];
_button.backgroundColor = [UIColor blueColor];
[_button addTarget:self action:#selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
}
return _button;
}
- (void)setupUI {
[self.view addSubview:self.textField];
[self.view addSubview:self.button];
[self.textField mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(200);
make.height.mas_equalTo(50);
make.centerX.mas_equalTo(self.view.mas_centerX);
make.centerY.mas_equalTo(self.view);
}];
[self.button mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(200);
make.height.mas_equalTo(50);
make.centerX.mas_equalTo(self.view);
make.centerY.mas_equalTo(self.view).offset(100);
}];
}
- (void)buttonAction {
NSString *str = self.textField.text;
if (self.callBack != nil) {
self.callBack(str);
NSLog(#"This statement didnt print in log");
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor redColor];
}
update code
VC2.m
- (void)viewWillAppear:(BOOL)animated{
self.callBack = ^(NSString *text){
};
}
- (void)buttonAction {
if (self.callBack) {
NSLog(#"It worked on debug area %#", self.textField.text);
self.callBack(self.textField.text);
}
self.textField.text = #"";
}
VC1.m
- (void)viewDidLoad {
[super viewDidLoad];
_secondVc = [[SecondViewController alloc] init];
_secondVc.callBack = ^(NSString *str){
};
[self setupUI];
self.view.backgroundColor = [UIColor greenColor];
}
- (void)viewWillAppear:(BOOL)animated {
if (_secondVc.callBack != nil) {
NSLog(#"It wrked on debug screen");
_secondVc.callBack = ^(NSString *str){
NSLog(#"It didn't worked on debug screen");
//I want set my label.text = str;
};
};
}
The only way is that you property
#property (copy, nonatomic) void (^callBack)(NSString *text);
is empty. Try to put breakpoint in buttonAction method and look at the property.
As Sander and KrishnaCA mentioned your callBack is nil. I would suggest you create a definition of the block like this:
typedef void(^TextBlock)(NSString *text);
Then change your property to:
#property (copy, nonatomic) TextBlock callBack;
Create a copy of the block in your first view controller:
#interface FirstViewController()
#property (copy, nonatomic) TextBlock firstViewControllerCallBack;
#end
Initialize the callback copy (i.e. in viewDidLoad)
- (void)viewDidLoad {
[super viewDidLoad];
self.firstViewControllerCallBack = ^(NSString *text){
NSLog(#"Second view controller's button tapped!");
};
}
Assign the callback to the second view controller right before presenting/pushing it:
SecondViewController *secondVC = [[SecondViewController alloc] init];
secondVC.callBack = self.firstViewControllerCallBack; // Assign the callback
// ... Presenting the view controller
Clean up the completion block after you done with it (i.e. in viewWillDisappear):
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.firstViewControllerCallBack = nil;
}

UISwitch always returns "False" value even when Switch is on

Every time I switch the UISwitch to either on or off in the simulator, it still returns false even when one of the switches is on. I even tried adding
self.switch1.on = true;
inside the if statement of checkSwitch1Changed.
This is my code in .m file.
- (IBAction)checkSwitch1Changed:(id)sender {
if (self.switch1.on)
{
self.switch2.on = NO;
self.switch3.on = NO;
self.switch4.on = NO;
}
...
}
- (IBAction)checkSwitch2Changed:(id)sender {
if (self.switch2.on)
{
self.switch1.on = NO;
self.switch3.on = NO;
self.switch4.on = NO;
}
...
}
- (IBAction)checkSwitch3Changed:(id)sender {
if (self.switch3.on)
{
self.switch1.on = NO;
self.switch2.on = NO;
self.switch4.on = NO;
}
...
}
- (IBAction)checkSwitch4Changed:(id)sender {
if (self.switch4.on)
{
self.switch1.on = NO;
self.switch2.on = NO;
self.switch3.on = NO;
}
...
}
This is my code in .h
#property (weak, nonatomic) IBOutlet UISwitch *switch1;
#property (weak, nonatomic) IBOutlet UISwitch *switch2;
- (IBAction)checkSwitch1Changed:(id)sender;
- (IBAction)checkSwitch2Changed:(id)sender;
//********
#property (weak, nonatomic) IBOutlet UISwitch *switch3;
#property (weak, nonatomic) IBOutlet UISwitch *switch4;
- (IBAction)checkSwitch3Changed:(id)sender;
- (IBAction)checkSwitch4Changed:(id)sender;
This actually works and sends back true if I send the data using that view controller. But I am trying to access this data from another view controller and it sends back false. I used this code to access the data from the other view controller.
//import data from SetupController'
SetupController *setupController = [[SetupController alloc] initWithNibName:#"SetupController" bundle:nil];
...
Firebase *postRef = [savedRef childByAppendingPath: #"Switches"];
NSDictionary *post1 = #{
#"Check1": #(setupController.self.switch1.on),
Did you try checking for the isOn property, instead of on?
if (self.switch1.on)
becomes
if (self.switch1.isOn)
Also check that the IBAction associated with the switch is a
ValueChanged
event, and that the reference outlets are properly linked.
You'll need to also 'set' the switch to on, rather than listening to see if it's on (without setting first, if that makes sense).
I'm sure there's a much more elegant way of doing this (it's a but long winded here), but you should get the idea and this method should work if you hook ALL the switches up to the one IBAction and changed the sender on the method from id to UISwitch.
(of course you don't need to use just the one IBAction, though it makes more sense if you do, as opposed to 4 actions all wanting to do the same thing)
- (IBAction)switchPressed:(UISwitch *)sender {
if (sender==self.switch1) {
self.switch1.on = YES;
self.switch2.on = NO;
self.switch3.on = NO;
self.switch4.on = NO;
}
if (sender==self.switch2) {
self.switch1.on = NO;
self.switch2.on = YES;
self.switch3.on = NO;
self.switch4.on = NO;
}
if (sender==self.switch3) {
self.switch1.on = NO;
self.switch2.on = NO;
self.switch3.on = YES;
self.switch4.on = NO;
}
if (sender==self.switch4) {
self.switch1.on = NO;
self.switch2.on = NO;
self.switch3.on = NO;
self.switch4.on = YES;
}
}

Custom alert view in iOS issue

In my app I've to create a custom alert view like the following:
So I followed this tutorial to create a custom alert view. I finished it but I'm getting issue in the following method:
- (void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove {
NSMutableArray *items = [[NSMutableArray alloc]init];
[items addObject:self.buttonOk];
[items addObject:self.buttonClose];
int buttonIndex = (tag == 1);
if (shouldRemove) {
[items removeObjectAtIndex:buttonIndex];
} else {
if (tag == 1) {
[items insertObject:self.buttonOk atIndex:buttonIndex];
} else {
[items insertObject:self.buttonClose atIndex:buttonIndex];
}
}
}
I edited it than the tutorial because I don't need a UIToolBar for buttons. When I run the app it says me that I can't insert a nil object in an NSMutableArray, but I don't understand what's wrong, I hope you can help me to fix this issue.
UPDATE
Here's all the class code I developed:
#import "CustomAlertViewController.h"
#define ANIMATION_DURATION 0.25
#interface CustomAlertViewController ()
- (IBAction)buttonOk:(UIButton *)sender;
- (IBAction)buttonCancel:(UIButton *)sender;
#property (weak, nonatomic) IBOutlet UIButton *buttonClose;
#property (weak, nonatomic) IBOutlet UIButton *buttonOk;
#property (strong, nonatomic) IBOutlet UIView *viewAlert;
-(void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove;
#end
#implementation CustomAlertViewController
- (id)init
{
self = [super init];
if (self) {
[self.viewAlert setFrame:CGRectMake(self.labelAlertView.frame.origin.x,
self.labelAlertView.frame.origin.y,
self.labelAlertView.frame.size.width,
self.viewAlert.frame.size.height)];
[self.buttonOk setTag:1];
[self.buttonClose setTag:0];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)showCustomAlertInView:(UIView *)targetView withMessage:(NSString *)message {
CGFloat statusBarOffset;
if (![[UIApplication sharedApplication] isStatusBarHidden]) {
CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
if (statusBarSize.width < statusBarSize.height) {
statusBarOffset = statusBarSize.width;
} else {
statusBarOffset = statusBarSize.height;
}
} else {
statusBarOffset = 0.0;
}
CGFloat width, height, offsetX, offsetY;
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft ||
[[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) {
width = targetView.frame.size.width;
height = targetView.frame.size.height;
offsetX = 0.0;
offsetY = -statusBarOffset;
}
[self.view setFrame:CGRectMake(targetView.frame.origin.x, targetView.frame.origin.y, width, height)];
[self.view setFrame:CGRectOffset(self.view.frame, offsetX, offsetY)];
[targetView addSubview:self.view];
[self.viewAlert setFrame:CGRectMake(0.0, -self.viewAlert.frame.size.height, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.viewAlert setFrame:CGRectMake(0.0, 0.0, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView commitAnimations];
[self.labelAlertView setText:#"CIAO"];
}
- (void)removeCustomAlertFromView {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.viewAlert setFrame:CGRectMake(0.0, -self.viewAlert.frame.size.height, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView commitAnimations];
[self.view performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION];
}
- (void)removeCustomAlertFromViewInstantly {
[self.view removeFromSuperview];
}
- (BOOL)isOkayButtonRemoved {
if (self.buttonOk == nil) {
return YES;
} else {
return NO;
}
}
- (BOOL)isCancelButtonRemoved {
if (self.buttonClose == nil) {
return YES;
} else {
return NO;
}
}
- (void)removeOkayButton:(BOOL)shouldRemove {
if ([self isOkayButtonRemoved] != shouldRemove) {
[self addOrRemoveButtonWithTag:1 andActionToPerform:shouldRemove];
}
}
- (void)removeCancelButton:(BOOL)shouldRemove {
if ([self isCancelButtonRemoved] != shouldRemove) {
[self addOrRemoveButtonWithTag:0 andActionToPerform:shouldRemove];
}
}
- (void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove {
NSMutableArray *items = [[NSMutableArray alloc]init];
[items addObject:self.buttonOk];
[items addObject:self.buttonClose];
int buttonIndex = (tag == 1);
if (shouldRemove) {
[items removeObjectAtIndex:buttonIndex];
} else {
if (tag == 1) {
[items insertObject:self.buttonOk atIndex:buttonIndex];
} else {
[items insertObject:self.buttonClose atIndex:buttonIndex];
}
}
}
- (IBAction)buttonOk:(UIButton *)sender {
[self.delegate customAlertOk];
}
- (IBAction)buttonCancel:(UIButton *)sender {
[self.delegate customAlertCancel];
}
#end
UPDATE 2
Code in which I use the CustomAlertView:
#import "PromotionsViewController.h"
#import "CustomAlertViewController.h"
#interface PromotionsViewController () <CustomAlertViewControllerDelegate> {
BOOL isDeletingItem;
}
#property(nonatomic,strong) CustomAlertViewController *customAlert;
- (IBAction)buttonBack:(UIButton *)sender;
#property (weak, nonatomic) IBOutlet UIButton *buttonAlert;
- (IBAction)buttonAlert:(UIButton *)sender;
#end
#implementation PromotionsViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.buttonAlert setTitle:self.promotionSelected forState:UIControlStateNormal];
[self.customAlert setDelegate:self];
isDeletingItem = NO;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonBack:(UIButton *)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc]init];
[self.customAlert removeOkayButton:NO];
[self.customAlert removeCancelButton:NO];
NSString *message = [NSString stringWithFormat:#"La tua offerta %# del 20%% è stata convertita in punti IoSi x10", self.promotionSelected];
[self.customAlert showCustomAlertInView:self.view withMessage:message];
isDeletingItem = YES;
}
- (void)customAlertOk {
if (isDeletingItem) {
[self.customAlert removeCustomAlertFromViewInstantly];
} else {
[self.customAlert removeCustomAlertFromView];
}
}
- (void)customAlertCancel {
[self.customAlert removeCustomAlertFromView];
if (isDeletingItem) {
isDeletingItem = NO;
}
}
#end
Maybe you're calling addOrRemoveButtonWithTag:andActionToPerform: at a time where your UI is not fully created, since UI elements are created asynchronously. So if you call this method, right after custom alert view instanciation, you'll get your crash because the buttons in the view are not created.
To solve this issue, you need to call addOrRemoveButtonWithTag:andActionToPerform: only once your custom alert has been added to the view hierarchy.
EDIT :
With the example code you gave in edit 2, you call these lines :
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc]init];
[self.customAlert removeOkayButton:NO];
[self.customAlert removeCancelButton:NO];
}
but when you have just instantiated CustomAlertViewController, its 2 buttons are not yet created, so I suggest you add 2 properties hasOkButton and hasCancelButton and a new constructor to your custom class like this one :
- (instancetype) initWithOk:(BOOL)OkButton AndCancel:(BOOL) CancelButton
{
if(self = [super init])
{
hasOkButton = OkButton;
hasCancelButton = CancelButton;
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// At this time, the custom UI buttons will be created in the UI view hierarchy
[self removeOkayButton: hasOkButton];
[self removeOkayButton: hasCancelButton];
}
And in the caller you can use the following to display a custom alert View:
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc] initWithOk:NO AndCancel:NO];
// ...
}
EDIT #2
I tried your solution in a real project, I made it work by using these lines int the caller :
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [self.storyboard instantiateViewControllerWithIdentifier:#"customAlertView"];
self.customAlert.hasOK = NO;
self.customAlert.hasCancel = YES;
NSString *message = [NSString stringWithFormat:#"La tua offerta %# del 20%% è stata convertita in punti IoSi x10", self.promotionSelected];
[self.customAlert showCustomAlertInView:self.view withMessage:message];
isDeletingItem = YES;
}
In the CustomAlertViewController declare 2 visible properties hasOK and hasCancel in.h.
And modify your .m by adding method :
-(void)viewWillAppear:(BOOL)animated
{
[self removeOkayButton:self.hasOK];
[self removeCancelButton:self.hasCancel];
}
Be sure to modify your storyboard (if eligible) to have the "customAlertView" defined this way :
Don't forget also to bind your UIButton to the controller this can be a mistake too in your implementation :
Hope this will help you :)
I found on the web a tutorial to create custom alert view by using code, if you are interested you can go to this tutorial. I used it for my issue and it worked great! You have to fix a few things, because it uses deprecated command but it's easy to fix it.
If you are interested just take a look about this tutorial. I think you can integrate it in your app and after you can easily use for other stuff if it's necessary. I hope that my answer will help someone.

Switch selectedState between three UIButton on the same tab

I have 3 UIButton on the same tab.
The problem :
When I click on button1, button2 and button3 all of them got selected; however what I want is when I select (for example) button2, the other buttons be unselected (like radio buttons on html).
Any idea on how I can solve this issue ?
Here is my code :
- (IBAction)button1:(UIButton *)sender {
sender.selected = !sender.selected;
}
- (IBAction)button2:(UIButton *)sender {
sender.selected = !sender.selected;
}
- (IBAction)button3:(UIButton *)sender {
sender.selected = !sender.selected;
}
There are a couple of straightforward solutions. Maybe they are not optimal, but you can use them:
First solution:
Link your buttons with corresponding properties:
#property (weak, nonatomic) IBOutlet UIButton *button1;
#property (weak, nonatomic) IBOutlet UIButton *button2;
#property (weak, nonatomic) IBOutlet UIButton *button3;
In each action change the selected property for each button:
- (IBAction)button1Clicked:(UIButton *)sender {
_button1.selected = YES;
_button2.selected = NO;
_button3.selected = NO;
}
Second solution:
Add all your buttons in NSArray:
NSArray *buttonsArray = [[NSArray alloc] initWithObjects: button1, button2, button3, nil];
Then link all the buttons with one action:
- (IBAction)buttonClicked:(UIButton *)sender {
for (UIButton *btn in _buttonsArray) {
if (btn == sender)
btn.selected = YES;
else
btn.selected = NO;
}
}
Don't forget to make your NSArray accessible for all the methods of the class, for example by creating a corresponding property:
#property (weak, nonatomic) NSArray *buttonsArray;
Third solution:
You can change the tag property for each button (through Interface Builder or in code):
_button1.tag = 1;
_button2.tag = 2;
_button3.tag = 3;
Then link all the buttons with one action (just like in previous example):
- (IBAction)buttonClicked:(UIButton *)sender {
if (sender.tag == 1) {
_button1.selected = YES;
_button2.selected = NO;
_button3.selected = NO;
} else if (sender.tag == 2) {
_button1.selected = NO;
_button2.selected = YES;
_button3.selected = NO;
} else if (sender.tag == 3) {
_button1.selected = NO;
_button2.selected = NO;
_button3.selected = YES;
}
}
Fourth solution: (by #velmurugan-s)
Use one action for all the buttons and set their default state to selected = NO:
- (IBAction)buttonClicked:(UIButton *)sender {
_button1.selected = NO;
_button2.selected = NO;
_button3.selected = NO;
sender.selected = YES;
}
Summary:
I'd recommend you to use the second solution as the most optimal one.
What you can do is connect button1,button2,button3 to same button123 in interface section give them appropriate tags
- (IBAction)button123:(UIButton *)sender;
In its description use below code
- (IBAction)button123:(UIButton *)sender {
if (sender.tag == 111)
{
sender.selected = !sender.selected;
if (sender.selected)
{
self.button2.selected = NO;
self.button3.selected = NO;
}
}
else if (sender.tag == 222)
{
sender.selected = !sender.selected;
if (sender.selected)
{
self.button1.selected = NO;
self.button3.selected = NO;
}
}
else if (sender.tag == 333)
{
sender.selected = !sender.selected;
if (sender.selected)
{
self.button1.selected = NO;
self.button2.selected = NO;
}
}
- (IBAction)button1:(UIButton *)sender {
btn1.selected = YES;
btn2.selected = NO;
btn3.selected = NO;
}
- (IBAction)button2:(UIButton *)sender {
btn1.selected = NO;
btn2.selected = YES;
btn3.selected = NO;
}
- (IBAction)button3:(UIButton *)sender {
btn1.selected = NO;
btn2.selected = NO;
btn3.selected = YES;
}
You had change the selected sate for a button that you have selected,You need to change all other button state too.

Resources