以编程方式创建的 UIButton 为目标
Posted
技术标签:
【中文标题】以编程方式创建的 UIButton 为目标【英文标题】:Targeting programmatically created UIButton 【发布时间】:2014-02-13 09:56:01 【问题描述】:问题:如何定位众多动态创建的 UIButton 之一,以便更改其属性?
背景:我有一个带有 UIViewConroller 的故事板。当这个 UIVC 加载一个 UIScrollView 时,会添加一个 UIImageView ,该 UIImageView 有一个展览平面图。每个参展商在包含其在平面图上的位置的数据库中都有一个条目。加载 UIVC 时,将为所有参展商运行一个循环,并且每个参展商都有一个 UIButton 绘制在 UIIV 上。单击 UIB 时,按钮背景颜色会更改(以确认已选择哪个参展商),并显示 UIAlertView 以及有关该参展商的信息。当按下 UIAV 的“取消”(确定)按钮时,UIAV 会关闭,并且应该删除之前应用的背景突出显示颜色,但这是我遇到问题的地方。我无法定位 UIButton,因此我可以更改其背景颜色。
到目前为止我所做的尝试: 创建每个按钮时,我都会给它一个标签和一个标题,并将它们记录在一个数组中。当在 UIAlertView 上按下“取消”按钮时,我尝试检查数组中的标记,但我仍然无法真正定位 UIButton。
我在想这样的事情:
// obviously not correct syntax but the kind of thing I want
[exhibitorBtn(tag) setBackgroundColor:[UIColor greenColor]];
所以,假设我有 12 个 UIButton,全都称为 existorBtn,但标题和标签不同:
对象 ----- 名称 ---------- 标题 -------- 标签
UIButton --existorBtn -- Glaxo ------ 1
UIButton --existorBtn -- Porsche --- 2
UIButton --existorBtn --Rolex ------- 3
编辑 - 添加创建按钮的代码只是为了澄清:
for (NSDictionary *dict in exhibitorStandArray)
NSInteger currentPosition = [exhibitorStandArray indexOfObject:dict];
NSLog(@"Position in array = %li", (long)currentPosition);
if (![dict[@"locCoords"] isEqual: @""])
NSInteger buttonTag = [exhibitorStandArray indexOfObject:dict];
NSString *standNo = dict[@"locStandNo"];
NSMutableDictionary *buttonDictionary = [[NSMutableDictionary alloc] init];
[buttonDictionary setObject:[NSNumber numberWithInteger:buttonTag] forKey:@"buttonTag"];
[buttonDictionary setObject:standNo forKey:@"buttonStandNo"];
[_masterButtonList addObject:buttonDictionary];
NSString *locCoords = dict[@"locCoords"];
NSArray *tempArray =[locCoords componentsSeparatedByString:@","];
tlcTop = [[tempArray objectAtIndex:0] integerValue];
tlcLeft = [[tempArray objectAtIndex:1] integerValue];
brcTop = [[tempArray objectAtIndex:2] integerValue];
brcRight = [[tempArray objectAtIndex:3] integerValue];
buttonWidth = brcRight - tlcLeft;
buttonHeight = brcTop - tlcTop;
testBtn = [UIButton buttonWithType:UIButtonTypeCustom];
testBtn.frame = CGRectMake(tlcTop, tlcLeft, buttonHeight, buttonWidth);
testBtn.titleLabel.text = standNo;
testBtn.tag = buttonTag;
NSLog(@"UIButton Title = %@", testBtn.titleLabel.text);
NSLog(@"UIButton Tag = %li", (long)testBtn.tag);
testBtn.titleLabel.hidden = YES;
[testBtn addTarget:self action:@selector(displayInfo:) forControlEvents:UIControlEventTouchUpInside];
[_buttonArray addObject:testBtn];
[_imageView addSubview:testBtn];
【问题讨论】:
在nsmutableArray中添加所有按钮,可以通过数组获取任意按钮:) 更改 UIButton 属性的语法是什么? UIButton *btn = (UIButton *) [myArray objectAtIndex: 0]; [btn setBackgroundColor:[UIColor greenColor]]; 好的,让我试试,我会回来的。 如何找出标签是什么?我们需要更多代码来澄清这一点。 【参考方案1】:你为什么不能直接使用viewWithTag:
UIButton * button = (UIButton *)[self.scrollView viewWithTag:tag];
【讨论】:
嗯,这很尴尬。现在你已经写了,这是显而易见的答案。这非常适合我的需要,非常感谢。 @Ryan - 不用担心我们都有这样的日子【参考方案2】:您的代码可能如下所示:
for (int i = 0; i < 5; i++)
UIButton *exhibitorBtn = [[UIButton alloc] initWithFrame:etc..];
exhibitorButton.tag = i;
[scrollView addSubview:exhibitorBtn];
只需更改循环,以便将每个按钮也添加到数组中。将NSMutableArray
声明为属性:@property (strong, nonatomic) NSMutableArray *buttonsArray;
@synthesize
并在您的 init 方法中对其进行初始化。 buttonsArray = [[NSMutableArray alloc] init]
然后,像我上面说的那样改变循环:
for (int i = 0; i < 5; i++)
UIButton *exhibitorBtn = [[UIButton alloc] initWithFrame:etc..];
exhibitorButton.tag = i;
[buttonsArray addObject:exhibitorBtn];
[scrollView addSubview:exhibitorBtn];
最后,当你想访问按钮时:
for (int i = 0; i < [buttonsArray count]; i++)
UIButton *button = [buttonsArray objectAtIndex:i];
if (button.tag == 3) // This is the button you wanted to target!
[button setHidden:YES];
【讨论】:
如果按钮已经在数组序列中,为什么要使用增加tag
?
我只是给出了他的代码示例。我假设所有者无论如何都在 Interface Builder 中设置了标签。 :]
当我遍历数据库中的参展商并创建按钮并在那里分配他们的标签时,没有设置标签。标签本身不只是 1、2、3,因为它们与参展商的展位编号相匹配,因此所示的阵列不会完美运行。另一方面,字典可能会很好用。【参考方案3】:
让我们说清楚:您确实将 UIButton 的 target
和 action
设置为控制器的 IBAction 方法,并将按钮作为 sender
参数。现在您显示 UIAlertView 和 它被关闭后,您想向 那个 按钮发送一些消息,对吧?
另一种方法是为 UIAlertView 设置delegate
属性并响应– alertView:clickedButtonAtIndex:
委托方法。麻烦的是sender
在那个时候丢失了。您可以使用objc_setAssociatedObject
将 UIButton 与 UIAlertView 相关联,并在委托方法触发时将其取回:
#import <objc/runtime.h>
static char myButtonKey = 0; // to use address as a key (value is irrelevant)
- (IBAction)buttonDidClick:(id)button
UIAlertView *alertView = <setup alert>;
[alertView setDelegate:self];
objc_setAssociatedObject(alertView, &myButtonKey, button, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
<show alert>;
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
UIButton *thatButton = objc_getAssociatedObject(alertView, &myButtonKey);
<use thatButton>;
【讨论】:
我已将其视为解决此类问题的潜在方法。我会先尝试数组方法,然后再this。 @Ryan 只是好奇,UIAlertView 关闭后你怎么知道tag
?如果您在按下按钮时在临时控制器字段中记住它,那么您可以记住按钮数组中的实际索引,而根本不处理标签搜索。
我通过创建一个属性来保存“currentTag”有点作弊。按下按钮时,此属性会更新为当前按钮的标签。
@Ryan :) 那为什么不拿着currentButton
作弊呢?
我没想到,好像是我想多了:S【参考方案4】:
尝试以这种方式创建按钮并向它们添加选择器:
for (int i = 0; i < 5; i++)
UIButton *button = [[UIButton alloc] initWithFrame:CGRectZero];
button.tag = i;
[button addTarget:self
action:@selector(buttonPressedMethod:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:@"Show View" forState:UIControlStateNormal];
// add button to subview here
在方法中,随心所欲:
- (void) buttonPressedMethod : (id) sender
UIButton *selectedButton = (UIButton *)sender;
if (selectedButton.tag == 0)
else if (selectedButton.tag == 1)
else
【讨论】:
这个答案可能会奏效,但我选择了 Flexicoder 的,因为它更简单,需要对我的修改更少。此外,标签是根据它们在数据库中的位置设置的(稍后使事情变得更简单),因此数组索引不会匹配,因此我可能需要一个字典。以上是关于以编程方式创建的 UIButton 为目标的主要内容,如果未能解决你的问题,请参考以下文章
如何导航 UIViewController 作为以编程方式创建的 UIButton 操作的目标