逻辑与 NSUInteger 和字符串类型?

Logically ANDing NSUInteger and String Type?

我搜索过 Whosebug 和其他网站,但我似乎找不到这个答案。

在 Apple Text Editor 源代码中,他们至少有一个例程在两个非布尔变量之间执行一些明显奇怪的逻辑与操作。将它们转换为 Bools 可以完成,但没有多大意义。我正在学习 Swift 并且对 Objective-C 不太熟悉,但对于我来说,我无法弄清楚他们是如何努力实现 "Build list of encodings, sorted, and including only those with human readable names."[= 中规定的目标的11=]

代码如下:

/* Return a sorted list of all available string encodings.
*/
+ (NSArray *)allAvailableStringEncodings {
    static NSMutableArray *allEncodings = nil;
    if (!allEncodings) {    // Build list of encodings, sorted, and including only those with human readable names
        const CFStringEncoding *cfEncodings = CFStringGetListOfAvailableEncodings();
        CFStringEncoding *tmp;
        NSInteger cnt, num = 0;
        while (cfEncodings[num] != kCFStringEncodingInvalidId) num++;   // Count
        tmp = malloc(sizeof(CFStringEncoding) * num);
        memcpy(tmp, cfEncodings, sizeof(CFStringEncoding) * num);   // Copy the list
        qsort(tmp, num, sizeof(CFStringEncoding), encodingCompare); // Sort it
        allEncodings = [[NSMutableArray alloc] init];           // Now put it in an NSArray
        for (cnt = 0; cnt < num; cnt++) {
            NSStringEncoding nsEncoding = CFStringConvertEncodingToNSStringEncoding(tmp[cnt]);
            if (nsEncoding && [NSString localizedNameOfStringEncoding:nsEncoding]) [allEncodings addObject:[NSNumber numberWithUnsignedInteger:nsEncoding]];
        }
        free(tmp);
    }
    return allEncodings;
}

相关行包含“&&”。任何指导将不胜感激。

Objective-C 是 C 的严格超集,因此逻辑规则相同 运营商申请。与 Swift 相比,后者更加严格 类型,C 中的逻辑运算符采用任意 标量 操作数。 (boolean 类型 bool 在 C 的早期版本中甚至不存在, 它是随 C99 标准添加的。)

C 标准规定(参见 http://port70.net/~nsz/c/c11/n1570.pdf,这是 C11 标准的草案):

6.5.13 Logical AND operator

Constraints

2 Each of the operands shall have scalar type.

Semantics

3 The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.

在你的情况下,在

if (nsEncoding && [NSString localizedNameOfStringEncoding:nsEncoding])

左操作数的类型为 NSUInteger(可以是 unsigned longunsigned int,取决于平台),以及右 操作数的类型为 NSString *,这是一个 指针类型 。所以 上面的表达式等同于

if (nsEncoding != 0 && [NSString localizedNameOfStringEncoding:nsEncoding] != 0)

右操作数中的零是空指针常量 对于 Objective-C 指针,通常写为 NULLnil

if (nsEncoding != 0 && [NSString localizedNameOfStringEncoding:nsEncoding] != nil)

关于这与 Swift

的更多信息

Cocoa/Cocoa触摸Objective-C方法,其中return一个对象指针 通常 return nil 表示错误 (比较 Handling Error Objects Returned From Methods 在 "Error Handling Programming Guide") 中。所以

[NSString localizedNameOfStringEncoding:nsEncoding] != nil

表示 "no localized name for the encoding could be determined"。 Swift 等价物是 returning 一个 可选 字符串的方法, 你可以用

检查是否成功
NSString.localizedNameOfStringEncoding(nsEncoding) != nil

但是,这不会编译,原因如下:如果您选择单击 Objective-C localizedNameOfStringEncoding 方法 在 Xcode 中显示它的声明然后你会看到

+ (NSString * _Nonnull)localizedNameOfStringEncoding:(NSStringEncoding)encoding

这里_Nonnull表示该方法不是预期return nil。这种可空性注释被引入到 改进 Objective-C 方法到 Swift 的映射,参见示例 "Nullability and Objective-C" 在 Swift 博客中。

由于这个 _Nonnull 注释,该方法被导入到 Swift 作为

public class func localizedNameOfStringEncoding(encoding: UInt) -> String

所以可以测试 return 中 Objective-C 的值,但不会 有意义,因为该方法总是 return 是一个非 nil 值。 在 Swift 中,编译器 假定 return 值永远不会 nil returns 是一个非可选的 String.

因此,将 if 语句翻译成 Swift 就是

if nsEncoding != 0 {
    // ...
}