如何处理动态创建的UIButtons

时间:2014-07-09 13:32:49

标签: ios objective-c cocoa-touch uibutton

我有一个UIViewController作为一种菜单。菜单由多个盒子/瓦片组成,UIViews包含带描述的UILabel,UIButton链接到另一个显示更多信息的UIViewController,另一个UIButton链接到UIViewController,显示应用程序的另一个区域。

目前有3个这样的盒子,但这会增长。目前我已经像这样对每个人进行了硬编码:

- (void)drawProceduresBox
{
self.viewProceduresBox = [[UIView alloc] initWithFrame:CGRectMake((_screenWidth * 0.05), (_screenHeight * 0.35), (_screenWidth * 0.9), (_screenHeight * 0.25))];
[_viewProceduresBox setBackgroundColor:[UIColor whiteColor]];
_viewProceduresBox.layer.borderWidth = 1.0f;
_viewProceduresBox.layer.borderColor = [UIColor grayColor].CGColor;

CGFloat boxHeight = _viewProceduresBox.frame.size.height;
CGFloat boxWidth = _viewProceduresBox.frame.size.width;

self.buttonShowProcedures = [[UIButton alloc] init];
[_buttonShowProcedures setFrame:CGRectMake((boxWidth * 0.8), (boxHeight * 0.4), (boxWidth * 0.1), (boxHeight * 0.2))];
[_buttonShowProcedures setBackgroundColor:[UIColor greenColor]];
[_buttonShowProcedures addTarget:self action:@selector(showProcedures) forControlEvents:UIControlEventTouchUpInside];

_buttonshowMoreInfo = [[appButton alloc] init];
[_buttonshowMoreInfo setFrame:CGRectMake((boxWidth * 0.6), (boxHeight * 0.6), (boxWidth * 0.1), (boxHeight * 0.2))];
[_buttonshowMoreInfo setBackgroundColor:[UIColor blueColor]];
[_buttonshowMoreInfo setWhatToShow:@"vetMed"];
[_buttonshowMoreInfo addTarget:self action:@selector(showMoreInfo:) forControlEvents:UIControlEventTouchUpInside];

[_viewProceduresBox addSubview:_buttonShowProcedures];

}

可能有10多个这样的盒子,所以我想要一种动态创建它们的方法。这是我到目前为止所尝试的:

-(void)drawBox:(NSString*)moduleName boxFrame:(CGRect)boxFrame labelDesc:(NSString*)labelDesc
{

UIView *moduleInfoBox = [[UIView alloc] initWithFrame:boxFrame];
[moduleInfoBox setBackgroundColor:[UIColor purpleColor]];

CGFloat boxHeight = moduleInfoBox.frame.size.height;
CGFloat boxWidth = moduleInfoBox.frame.size.width;

UILabel *moduleLable = [[UILabel alloc] init];
[moduleLable setFrame:CGRectMake((boxWidth * 0.05), (boxHeight * 0.05), (boxWidth * 0.6), (boxHeight * 0.9))];
[moduleLable setBackgroundColor:[UIColor yellowColor]];
[moduleLable setText:labelDesc];

UIButton *showModuleButton = [[UIButton alloc] init];
[showModuleButton setFrame:CGRectMake((boxWidth * 0.8), (boxHeight * 0.15), (boxWidth * 0.1), (boxWidth * 0.2))];
[showModuleButton setBackgroundColor:[UIColor grayColor]];
[showModuleButton addTarget:self action:@selector(showModule:) forControlEvents:UIControlEventTouchUpInside];

UIButton *showMoreInfoButton = [[UIButton alloc] init];
[showMoreInfoButton setFrame:CGRectMake((boxWidth * 0.8), (boxHeight * 0.65), (boxWidth * 0.1), (boxWidth * 0.1))];
[showMoreInfoButton setBackgroundColor:[UIColor orangeColor]];
[showMoreInfoButton addTarget:self action:@selector(showMoreInfo:) forControlEvents:UIControlEventTouchUpInside];

[moduleInfoBox addSubview:moduleLable];
[moduleInfoBox addSubview:showModuleButton];
[moduleInfoBox addSubview:showMoreInfoButton];

_scrollHeight = _scrollHeight + (moduleInfoBox.frame.origin.y + moduleInfoBox.frame.size.height);

[_scrollView addSubview:moduleInfoBox];


}

我会像这样调用这个方法(在这种情况下为三个方框):

CGRect formularyFrame = CGRectMake((_screenWidth * 0.05), (_screenHeight * 0.05), (_screenWidth * 0.9), (_screenHeight * 0.25));
CGRect proceduresFrame = CGRectMake((_screenWidth * 0.05), (_screenHeight * 0.35), (_screenWidth * 0.9), (_screenHeight * 0.25));
CGRect vetMedFrame = CGRectMake((_screenWidth * 0.05), (_screenHeight * 0.65), (_screenWidth * 0.9), (_screenHeight * 0.25));
[self drawBox:@"Formulary" boxFrame:formularyFrame labelDesc:@"Desc about formulary module"];
[self drawBox:@"Procedures" boxFrame:proceduresFrame labelDesc:@"Desc about procedures module"];
[self drawBox:@"VetMed" boxFrame:vetMedFrame labelDesc:@"Desc about vetMed module"];

我遇到的问题是动态生成的UIButtons需要链接到相关的东西,在这种情况下是UIViewControllers。每个按钮都有一个选择器,用于触发方法'showModule'和'showModuleInfo'。

在这些方法中,我如何告诉UIButton被按下了什么,因此,知道哪个UIViewController将navigationController推送到?基本上我想要的是:

-(void)showModule:(NSString*)moduleToShow
{
    [self.navigationController pushViewController:moduleToShow animated:NO];
}

但据我了解,你不能在“@selector”赋值中添加参数:

[_buttonshowMoreInfo addTarget:self action:@selector(showMoreInfo:) forControlEvents:UIControlEventTouchUpInside];

我该怎么办?

2 个答案:

答案 0 :(得分:0)

点击UIButton时调用的方法有点偏差。例如,现在你有:

// if a button action triggers this as your code is written, it won't have a valid string.
-(void)showModule:(NSString*)moduleToShow
{
    [self.navigationController pushViewController:moduleToShow animated:NO];
}

这意味着当您点击按钮时showModule:方法将收到NSString对象,但实际上它会收到触发该事件的UIButton对象。像这样:

-(void)showModule:(UIButton *)sender
{
    // use information about the button that sent the action
}

了解点击哪个按钮的常用方法是在创建按钮时在按钮上设置唯一标记。如果您只有几个,那么将int编码到它们上面会很好 - 如果您有很多并需要将它们全部区分开来,您可能需要设置宏以便命名int s

UIButton *showModuleButton = [[UIButton alloc] init];
...
showModuleButton.tag = 1;
[showModuleButton addTarget:self action:@selector(showModule:) forControlEvents:UIControlEventTouchUpInside];

现在,只要您在按钮内“触摸”,就会调用showModule:,然后在其中您可以访问tag的{​​{1}}属性以查看触发的按钮事件。

sender

答案 1 :(得分:0)

如果要在按钮和视图控制器类之间创建一个映射,以便在按钮上显示,您有两个简单的选项:

  1. 为每个按钮分配一个标签,并创建一个将标签映射到类(到NSStringClass)的字典:

    @property(nonatomic, strong) NSMutableDictionary *tagClassDic;
    
    -(void)drawBox:(NSString*)moduleName boxFrame:(CGRect)boxFrame labelDesc:(NSString*)labelDesc buttonTag:(NSInteger)tag {
        ...
        showModuleButton.tag = tag;
    }
    
    -(void)showModule:(UIButton *)sender {
        NSString *classStr = self.tagClassDic[@(sender.tag)];
        [self.navigationController pushViewController:[NSClassFromString(classStr) new] animated:NO];
        // or, if you decide to store classes in the dictionary:
        [self.navigationController pushViewController:[self.tagClassDic[@(sender.tag)] new] animated:NO];
    }
    
    ...
    
    self.tagClassDic = [NSMutableDictionary dictionary];
    
    NSInteger firstTag = 1;
    [self drawBox:@"Formulary" boxFrame:formularyFrame labelDesc:@"Desc about formulary module" buttonTag:firstTag];
    self.tagClassDic[@(firstTag)] = @"ViewController"; // or [ViewController class]
    
  2. 将关联对象(再次,字符串或类)直接设置为按钮对象:

    static const char *kViewControllerClassKey = "viewControllerClassKey";
    
    -(void)drawBox:(NSString*)moduleName boxFrame:(CGRect)boxFrame labelDesc:(NSString*)labelDesc viewControllerClassStr:(NSString*)classStr {
        ...
        objc_setAssociatedObject(showModuleButton, kViewControllerClassKey, classStr, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    -(void)showModule:(UIButton *)sender {
        NSString *classStr = objc_getAssociatedObject(sender, kViewControllerClassKey);
        [self.navigationController pushViewController:[NSClassFromString(classStr) new] animated:NO];
    }
    
    ...
    
    [self drawBox:@"Formulary" boxFrame:formularyFrame labelDesc:@"Desc about formulary module" viewControllerClassStr:@"ViewController"];