Objective c 如何使多个单选按钮,但只有一个始终被选中,其中第一个是默认的?

Objective c 如何使多个单选按钮,但只有一个始终被选中,其中第一个是默认的?,objective-c,uibutton,Objective C,Uibutton,我从事一个Objective-C项目,试图构建一个多个单选按钮。很快,我想制作多个单选按钮,但只有一个始终处于选中状态,其中第一个是默认的 我开始尝试用两个按钮,但我不能完全达到我想要的。我希望有很好的方法做到这一点。我也可以使用扩展。您可以将UI元素放在UIView中进行分组,并使用KVO观察器来利用额外的代码 @interface ViewController () @property (nonatomic) UIView *group; @end @implementation View

我从事一个Objective-C项目,试图构建一个多个单选按钮。很快,我想制作多个单选按钮,但只有一个始终处于选中状态,其中第一个是默认的


我开始尝试用两个按钮,但我不能完全达到我想要的。我希望有很好的方法做到这一点。我也可以使用扩展。

您可以将UI元素放在UIView中进行分组,并使用KVO观察器来利用额外的代码

@interface ViewController ()
@property (nonatomic) UIView *group;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    [self createGroupWithRadios:3 andSelectIndex:0];
}

//a context to make KVO much easier to catch (and less string compare'y)
static void * kRadioGroupContext = &kRadioGroupContext;

-(void)createGroupWithRadios:(int)amount andSelectIndex:(int)idx {
    CGFloat h = 30.0;
    _group = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, h*amount)];
    for (int i=0; i<amount; i++) {
        UIButton *radio = [UIButton buttonWithType:(UIButtonTypeSystem)];
        radio.tag = i;
        radio.selected = i==idx;
        { //style stuff
            radio.frame = CGRectMake(0, h*i, 100, h);
            [radio setTitle:@"off" forState:UIControlStateNormal];
            [radio setTitle:@"on" forState:UIControlStateSelected];
            [radio setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
            [radio setTitleColor:UIColor.redColor forState:UIControlStateSelected];
            //[radio setImage:[UIImage imageNamed:@"active"] forState:UIControlStateSelected];
            //[radio setImage:[UIImage imageNamed:@"inactive"] forState:UIControlStateNormal];
        }
        [radio addTarget:self action:@selector(radioButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [_group addSubview:radio];
    }
    [self.view addSubview:_group];

    //you can use _group.tag to keep which one is selected and observe it
    _group.tag = idx;
    [_group addObserver:self forKeyPath:@"tag" options:(NSKeyValueObservingOptionNew) context:kRadioGroupContext];
}

-(void)radioButtonPressed:(UIButton*)sender {
    _group.tag = sender.tag;
    for (int i=0; i<_group.subviews.count; i++) {
        UIButton *radio = _group.subviews[i];
        radio.selected = radio.tag==sender.tag;
    } 
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (context == kRadioGroupContext) {
        // do something when a new radio is selected
        NSLog(@"selected Radio %lu", _group.tag);
    }
}

您可以通过将UI元素放置在UIView中来对它们进行分组,并使用KVO观察器来利用额外的代码

@interface ViewController ()
@property (nonatomic) UIView *group;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    [self createGroupWithRadios:3 andSelectIndex:0];
}

//a context to make KVO much easier to catch (and less string compare'y)
static void * kRadioGroupContext = &kRadioGroupContext;

-(void)createGroupWithRadios:(int)amount andSelectIndex:(int)idx {
    CGFloat h = 30.0;
    _group = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, h*amount)];
    for (int i=0; i<amount; i++) {
        UIButton *radio = [UIButton buttonWithType:(UIButtonTypeSystem)];
        radio.tag = i;
        radio.selected = i==idx;
        { //style stuff
            radio.frame = CGRectMake(0, h*i, 100, h);
            [radio setTitle:@"off" forState:UIControlStateNormal];
            [radio setTitle:@"on" forState:UIControlStateSelected];
            [radio setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
            [radio setTitleColor:UIColor.redColor forState:UIControlStateSelected];
            //[radio setImage:[UIImage imageNamed:@"active"] forState:UIControlStateSelected];
            //[radio setImage:[UIImage imageNamed:@"inactive"] forState:UIControlStateNormal];
        }
        [radio addTarget:self action:@selector(radioButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [_group addSubview:radio];
    }
    [self.view addSubview:_group];

    //you can use _group.tag to keep which one is selected and observe it
    _group.tag = idx;
    [_group addObserver:self forKeyPath:@"tag" options:(NSKeyValueObservingOptionNew) context:kRadioGroupContext];
}

-(void)radioButtonPressed:(UIButton*)sender {
    _group.tag = sender.tag;
    for (int i=0; i<_group.subviews.count; i++) {
        UIButton *radio = _group.subviews[i];
        radio.selected = radio.tag==sender.tag;
    } 
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (context == kRadioGroupContext) {
        // do something when a new radio is selected
        NSLog(@"selected Radio %lu", _group.tag);
    }
}
如前所述,UIControl是UIView的一个子类,这意味着您也可以使用UIControl将UIView按钮分组在一起。其优点是,在进行新选择时,添加目标很容易捕获。缺点是您必须更多地考虑样式/布局,因为这在代码中是固定的,修改需要更多的注意。下面的示例使用NSStrings的NSArray作为标题散布在UIControl按钮内。因此,NSArray计数定义了在帧高度中生成的按钮数量。使用此选项可以轻松构建多项选择表单

//ButtonSelectGroup.h
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface ButtonSelectGroup : UIControl
-(instancetype)initWithFrame:(CGRect)frame andTitles:(NSArray<NSString*>*)titles preValue:(NSInteger)idx;
@property (nonatomic) NSInteger value;
-(void)setTitles:(NSArray<NSString *> * _Nonnull)titles;
@end

NS_ASSUME_NONNULL_END
如前所述,UIControl是UIView的一个子类,这意味着您也可以使用UIControl将UIView按钮分组在一起。其优点是,在进行新选择时,添加目标很容易捕获。缺点是您必须更多地考虑样式/布局,因为这在代码中是固定的,修改需要更多的注意。下面的示例使用NSStrings的NSArray作为标题散布在UIControl按钮内。因此,NSArray计数定义了在帧高度中生成的按钮数量。使用此选项可以轻松构建多项选择表单

//ButtonSelectGroup.h
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface ButtonSelectGroup : UIControl
-(instancetype)initWithFrame:(CGRect)frame andTitles:(NSArray<NSString*>*)titles preValue:(NSInteger)idx;
@property (nonatomic) NSInteger value;
-(void)setTitles:(NSArray<NSString *> * _Nonnull)titles;
@end

NS_ASSUME_NONNULL_END

简而言之:您需要多个单选按钮,但在第一个是默认的情况下,始终只选择一个?您可能应该创建自己的UIView子类来实现单选按钮集。无论如何,您将需要一组按钮。选择按钮时,只需在数组上迭代,如果迭代中的当前元素不是刚刚选择的按钮,则取消选择它。简言之:您需要多个单选按钮,但在第一个按钮为默认按钮的情况下,始终只选择一个单选按钮?您可能应该创建自己的UIView子类来实现单选按钮集。无论如何,您将需要一组按钮。选择按钮后,只需在数组上迭代,如果迭代中的当前元素不是刚刚选择的按钮,请取消选择。感谢您的回复,我下次将尝试此操作并保留在我的库中,但我不确定我的情况,在我看来这似乎有点复杂。我已经设置了约束并编写了选择器函数。我也不能在UIView中创建组按钮,因为它们已经有一个superview。您也可以将UIView组放置到该superview中。不要紧,您无论如何都需要它来捕获其中一个是否更改了其选择以及选择的状态。无论如何,你会在这个例子中找到一些想法来提高你的目标。不过,UIButton的扩展也不错。或者使用你的superview而不是_groups是的,非常感谢我开始考虑你的代码,我会尽快给出反馈,也不会让你对sender.superview.subviews中的RadioButton发狂Pressed:当你知道你的superview是唯一一个保管收音机按钮的人谢谢你的回复,我下次会尝试这个,并保存在我的库中,但我不是当然,我的情况有点复杂。我已经设置了约束并编写了选择器函数。我也不能在UIView中创建组按钮,因为它们已经有一个superview。您也可以将UIView组放置到该superview中。不要紧,您无论如何都需要它来捕获其中一个是否更改了其选择以及选择的状态。无论如何,你会在这个例子中找到一些想法来提高你的目标。不过,UIButton的扩展也不错。或者使用你的superview而不是_groups是的,非常感谢我开始考虑使用你的代码,我会尽快给出反馈,也不会让你对sender.superview.subviews发疯。当你知道你的superview是收音机按钮的唯一保管人时,谢谢你实际上我需要根据你的答案编辑我的问题,但我接受你的建议第一个答案。谢谢。实际上我需要根据你的答案编辑我的问题,但我接受你的第一个答案。