2014-07-09 66 views
0

我有一个UIViewController作为一种菜单。该菜单由多个盒/瓦片组成,这些盒子/瓦片是包含带有描述的UILabel的UIViews,链接到显示更多信息的另一个UIViewController的UIButton和链接到显示该应用的另一个区域的UIViewController的另一个UIButton。如何处理动态创建的UIButtons

目前有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]; 
} 

但据我所知,你可以不加参数“@选择”分配:

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

我该怎么办呢?

+0

好,动态创建。如果你想要通过一个循环。当你不知道有多少人时,把他们放在一个数组中。或者使用表格并将按钮添加到单元格。或者根本不要在任何局部变量中保留它们,而是给它们分配一个标签。您可以使用该标签,一旦按钮被点击以确定哪个按钮被点击 - 如果您需要知道。 –

+0

这就是我想要最终实现的目标。我将有一个循环遍历存储在SQLite数据库中的模块名称数组,然后使用相关链接构建每个框以动态创建UIViewControllers。我只是不知道如何将动态创建的UIButtons与加载动态创建的UIVC的方法绑定在一起。 – Ryan

+0

不知何故,你将不得不知道哪个视图控制器将被调用每个按钮。如果你可以使用一个整数作为id,让我们说一个数组的索引。然后使用for循环来创建带'i'作为循环变量的视图。将'i'分配给每个按钮的'tag'属性。当按钮被按下时,一个动作被调用,'sender'被移交给它。发送者是一个'UIView'子类,它是被按下的那个按钮。获取它的'标记'值并从那里开始... –

回答

0

如果你想创建一个按钮和一个视图控制器类显示按钮自来水之间的映射,你有2种简单的选择:

  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. 集相关联的对象(再次,一个字符串或一类)直接连接到第e钮对象:

    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"]; 
    
+0

第二个选项似乎是有道理的,可能正是我所需要的。我不喜欢使用标签,因为生成UIButtons的方法会为每个“运行”创建2个不同的按钮。还有标签我需要某种查找?标记1 = catsVC,标记2 = dogsVC ..等 – Ryan

+0

查找是通过字典在第一个选项中完成的:键是按钮的标记,值是类。 – kambala

+0

不知道为什么这个答案当时不被接受,但这实际上是为我解决了这个问题。 – Ryan

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

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

现在,每当你“摸了内部”你的按钮,showModule:将被调用,并且它可以访问sendertag属性,看看哪个按钮触发事件。

-(void)showModule:(UIButton *)sender 
{ 
    // use information about the button that sent the action 
    if(sender.tag == 1) 
    { 
     // you know which button triggered the event now! 
    } 
} 
+0

感谢你的这一点,我在最后发布的例子更像是'我喜欢这样',而不是我用过的东西。我尝试过使用标签,但我如何分配标签?正如目前使用相同的代码来创建每个UIButton。此外,创建按钮的方法创建两个按钮,而不是一个。 – Ryan

+0

@Ryan所以你说你有两个按钮是以相同的方式创建的,但你希望他们有不同的动作? – Stonz2

+0

每个添加的UIView都有1个UILabel和2个UIButton。 – Ryan