将NSUInteger分配给BOOL概念理解
我正在努力寻找BOOL概念的一个很好的答案。 据我所知,零是一个错误的值,非零是一个真正的值。 想到这一点,我把string长度分配到BOOLvariables。 现在,这对iOS> 6很好。在iOS 6我看到奇怪的结果。 对于奇数长度的string,isEnabled为true,但对于长度均匀的string,isEnabled为turing False。
BOOL isEnabled = myString.length;
请帮我理解这一点。 当然,现在我已经把expression式分配给BOOLvariables,像这样:
BOOL isEnabled = myString.length > 0;
准确的代码:
- (void)textViewDidChange:(UITextView *)iTextView { self.navigationItem.rightBarButtonItem.enabled = [[self.noteTextView.text trim] length]; }
PS:如上所述,myString的长度正在改变。 从'a'到'ab'到'abc'等
但是,我不明白iOS 6的行为只启用奇数的button。 我很想知道根本原因。
为了解释观察到的行为,有两个技术细节需要解释:Objective-C的BOOL
和UIKit的实现细节。
BOOL
types
不同的行为实际上与iOS 版本无关,而与设备的架构无关。 iOS SDK如何定义32位和64位体系结构的BOOL是有区别的。 请参阅objc.h
摘录:
#if !defined(OBJC_HIDE_64) && TARGET_OS_IPHONE && __LP64__ typedef bool BOOL; #else typedef signed char BOOL; #endif
所以在32位BOOL
可以有0到255之间的任何值,而在64位它是编译器强制只有值0或1.您可以轻松地尝试通过在模拟器上运行以下行,设置为iPhone 4s( 32位)或iPhone 6(64位)。
NSLog(@"%d", (BOOL)2);
这是为什么你在不同的设备上看到不同的行为的解释。 但是奇怪的事从哪里来呢?
UIBarButtonItem的实现细节
还有一些细微的技术细节。 您实际上正在设置UIBarButtonItem
的enabled
属性。
苹果喜欢使用节省空间的scheme在UI组件中存储标志。 BOOL
(在32位和64位体系结构上)总是使用至less一个字节,但只需要一位信息。 所以他们使用位域来存储实际的值。
摘录自iOS SDK 8.4 UIBarButtonItem.h
(缩略为清晰):
@interface UIBarButtonItem : UIBarItem { struct { unsigned int enabled:1; } _barButtonItemFlags; }
魔术是:1
_barButtonItemFlags
结构中enabled
字段后面的:1
。 这定义了宽度为1的位域。 要连接enabled
属性与这个位域,他们必须实现自定义访问器。 这是一个设置器的例子:
- (void)setEnabled:(BOOL)enabled { _barButtonItemFlags.enabled = enabled; }
那么当我们这样做时会发生什么:
someBarButtonItem.enabled = 2;
编译器明白它必须使用参数2来调用setEnabled:
方法。
在64位体系结构中, 2
将被转换为_Bool
,其中标准表示这必须导致值为1
。 在32位系统上,情况并非如此,在调用方法之前,将原始值保留在原来的位置。
在setEnabled:
内部setEnabled:
该值被分配给宽度为1的无符号整数。C标准说,当分配一个宽度更大的无符号整数时,其余的位将被丢弃。 结果是setEnabled:
只在_barButtonItemFlags.enabled
存储参数的最低位。 最低位是一个奇数,偶数是零。
结论
以上所有行为均在标准提供的语义范围内。 没有涉及不确定的行为。 这只是一个不幸的事实, BOOL
的预期行为不同于你在32位体系结构上的实际行为。
在早些时候, BOOL
被实现为整数types。 因此,通过这样的实现,可以给它赋值> 1并读回。 但是从一开始这就错了(因为依赖于实现细节),因为文档总是说BOOL
types(C)对象的有效值是NO
和YES
。 期。
从2014年开始(?2013?), BOOL
types变得更像C _Bool
types。 这意味着为该types的对象赋值> 1,将1( YES
)存储到variables中。 所以,无论如何,行为改变了。 (一个未定义的行为成为一个定义的行为,行为与旧的未定义行为是不同的。)
但是你的问题看起来像只有Bit0被存储。 (偶数为0,奇数为1)这将是一个错误。 请告诉我们完整的代码。
但是,您可以使用_Bool
而不是BOOL
。
尝试使用这个,
BOOL isEnabled; if ( ( myString.length % 2 ) == 0 ) { //Is even isEnabled=FALSE; } else { //Is odd isEnabled=TRUE; }
- 在Objective-C代码中找不到windowScriptObject方法
- 正确显示和解除iOS 3.2中的全屏MPMoviePlayerController(iPad)
- 正确pipe理addObserverForName:object:queue:usingBlock:
- 未能findPDF标头:找不到“%PDF”
- 如何在Objective C中初始化一个空的可变数组
- UIActivityViewController不解散
- 为什么UIViewController touchesBegan,touchesMoved&touchesEnded只有在两个触摸的第一个开始,移动或结束时被调用?
- 当我在层次结构中添加额外的SKNode子级时,SKCropNode失败
- Xcode:构build和运行iOS模拟器和设备在一个步骤?