2016-06-22 77 views
2

这里是我的代码。UIButton performSelector:withObject:withObject:not making call

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 
    button.frame = CGRectMake(110, 270, 100, 40); 
    button.backgroundColor = [UIColor grayColor]; 
    [button setTitle:@"next" forState:UIControlStateNormal]; 
    [self.view addSubview:button]; 

我想通过这种方法 设置按钮标题的颜色,但它不工作!

[button performSelector:@selector(setTitleColor:forState:) 
       withObject:[UIColor blackColor] 
       withObject:@(UIControlStateNormal)]; 

有人知道为什么它不起作用?


谢谢大家的帮助。 昨天晚上,我找到了一种方法使它工作。无论参数是UIControlStateNormal(特殊情况)还是其他类似UIControlStateHighlighted。 这里是代码:

 [button performSelector:@selector(setTitleColor:forState:) 
        withObject:[UIColor blueColor] 
        withObject:(__bridge id)((void *)UIControlStateNormal)]; 
    [button performSelector:@selector(setTitleColor:forState:) 
        withObject:[UIColor blackColor] 
        withObject:(__bridge id)((void *)UIControlStateHighlighted)]; 
    [button performSelector:@selector(setTitleColor:forState:) 
        withObject:[UIColor redColor] 
        withObject:(__bridge id)((void *)UIControlStateSelected)]; 

所以问题就解决了。


我发现它很有用!所以,我想用它做更多的事情, 下面是代码:

[button.layer performSelector:@selector(setMasksToBounds:) withObject:(__bridge id)((void *)YES)]; 
    [button.layer performSelector:@selector(setCornerRadius:) withObject:(__bridge id)((void *)5)]; 
    [button.layer performSelector:@selector(setBorderWidth:) withObject:(__bridge id)((void *)5)]; 
    [button.layer performSelector:@selector(setBorderColor:) withObject:(__bridge id)(__bridge CGColorRef)[UIColor greenColor]]; 

当我测试,我发现它不会再工作!太失望了:(。如果有人有兴趣在这个问题上,你可以测试它。

+1

你确定从主线程调用了performSelector吗? –

+0

为什么要在主线程中调用? –

+0

是否调用setTitleColor:forState:如果直接调用工作? – Eiko

回答

1

如果我正确理解你的意图,你要求让框架进行相应的调用,所以你期望

[button performSelector:@selector(setTitleColor:forState:) 
       withObject:[UIColor blackColor] 
       withObject:@(UIControlStateNormal)]; 

调用

[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 

您在这里漏掉了一个重要的事情:performSelector:withObject:withObject:需要两个对象。您在NSNumber中包装普通整数值(因为UIControlStateNormal是某个int /枚举值)。现在,该对象(或指针,地址或任何你称之为)被作为第二个参数传递给setTitleColor:forState:,这显然不是该值本身,但由于该方法不知道这一点,它将该值解释为某种整数值。

因此,像这样将在后面叫:

NSNumber *number = ...; // your number object 
[button setTitleColor:[UIColor blackColor] forState:number]; 

正如另一种答案是说,这可能是由这里省略@(...)操作符,使值不裹在一个NSNumber。这将发生什么:NSControlStateNormal定义为0。所以编译器会将其解释为nil,这是一个有效的对象,或者缺少一个对象。 nil稍后将被重新解释为一个整数值UIControlState,因此您的0(== UIControlStateNormal)再次被解析。

这是一个特殊情况,因为0可能会被视为nil。它不起作用(通常甚至不编译)与任何其他值,即UIControlStateFocused。您将得到一个 “不能初始化类型为'(匿名枚举...)''的错误的'id'类型的参数。

如果你坚持要去的performSelector:路线,你可以添加一个方法是这样的:

-(void)setProperties:(NSDictionary *)props onButton:(UIButton *)button { 
    UIColor *color = props[@"color"]; 
    NSNumber *stateWrapper = props[@"state"]; 
    UIControlState state = (UIControlState)stateWrapper.unsignedIntegerValue; 
    [button setTitleColor:color forState:state]; 
} 

,并使用它像这样:

[self performSelector:@selector(setProperties:onButton:) 
      withObject:@{@"color" : [UIColor blackColor], 
         @"state" : [NSNumber numberWithUnsignedInteger:UIControlStateNormal]} 
      withObject:button]; 

它甚至可能是更清洁包住值转换为NSValue,或者使用专门的类来获取参数等。

但是,我更喜欢dispatch_*方法,即

dispatch_sync(dispatch_get_main_queue(), ^{ 
    [button setTitleColor:[UIColor blackColor] forState:number]; 
}) 

或使用dispatch_async或任何你当时的意图。

+0

我给它一个错误的类型值,所以它不会调用[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];删除@(),只是UIControlStateNormal,它的工作原理! –

+0

请看我编辑的答案。删除@()只是非常错误。 – Eiko

+0

正如你所说,这是一个特例。当我使用像UIControlStateHighlighted,UIControlStateSelected等值时,我应该如何使它工作。 –

1

你为什么不干脆用[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

对你来说

[button performSelector:@selector(setTitleColor:forState:) 
      withObject:[UIColor redColor] 
      withObject:UIControlStateNormal]; 

UIControlStateNormal删除@()

+1

这是显而易见的。问题是为什么不起作用 –

+0

当然我知道。我只是想知道为什么这种方法不起作用! –

+0

编辑了答案。 – Saad