按钮设置通过BOOL选择

Den*_*Vog 1 boolean uibutton ios

有人可以教育我为什么以下不起作用?该按钮永远不会设置为选中状态.

[self.boldButton setSelected:isBold];
Run Code Online (Sandbox Code Playgroud)

如果我用if else语句替换上面的代码就行了.我也可以将setSelected值更改为1或0,而不是YES或NO,它仍然可以正常工作.

if (isBold)
{
    [self.boldButton setSelected:YES];
}
else
{
    [self.boldButton setSelected:NO];
}
Run Code Online (Sandbox Code Playgroud)

所以我有一个工作项目,但我不明白为什么这两个实现不能提供相同的结果.谢谢.

FWIW - 我用另一种方法测试粗体.虽然如果测试有缺陷,我看不出第二种方法如何工作,而第一种方法仍然没有.

- (BOOL)isBold
{
    CTFontRef fontRef = (CTFontRef)CFBridgingRetain(self);
    CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(fontRef);
    return (symbolicTraits & kCTFontTraitBold);
}
Run Code Online (Sandbox Code Playgroud)

rob*_*off 15

BOOL定义如下<objc/objc.h>:

typedef signed char     BOOL;
Run Code Online (Sandbox Code Playgroud)

这意味着一个BOOL实际上可以保持-128到127(含)范围内的任何值.

-[UIControl setSelected:] 工作大致如下:

#define kSelectedBitPosition 10
#define kSelectedBit (1 << kSelectedBitPosition)

- (void)setSelected:(BOOL)selected {
    if (((self->_controlFlags >> kSelectedBitPosition) & 1) == selected) {
        return;
    } else {
        self->_controlFlags = (self->_controlFlags & ~kSelectedBit)
            | ((selected & 1) << kSelectedBitPosition);
        [self setNeedsDisplay];
    }
}
Run Code Online (Sandbox Code Playgroud)

(我UIKitHopper拆解了模拟器版本来解决这个问题.)

所以,请注意两件事:

  • if语句条件只能是如果为true selected == 0selected == 1.如果selected有任何其他价值,它永远不会是真的.

  • 赋值语句(更新_controlFlags)仅使用位0(1位)selected.因此,例如,如果selected == -2,在C中逻辑上为真并且除了位0 之外的每个位都设置,则赋值语句仍然不会打开该位_controlFlags.

这意味着您必须将0或1传递-[UIControl setSelected:].没有其他价值可靠地运作.

在C中将所有非零值转换为1的最短方法是将!运算符应用两次:

[self.boldButton setSelected:!!isBold];
Run Code Online (Sandbox Code Playgroud)

但是,修复您的-isBold方法以返回"安全" 可能更好BOOL:

- (BOOL)isBold {
    CTFontRef fontRef = (CTFontRef)CFBridgingRetain(self);
    CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(fontRef);
    return !!(symbolicTraits & kCTFontTraitBold);
}
Run Code Online (Sandbox Code Playgroud)