NSString的hasPrefix函数是否区分大小写?

9

这是一个简单的问题,但需要一些小技巧。我们知道,NSString 的 hasPrefix: 方法对大小写不敏感。

NSString *string = @"Xyzabcdedfghij";
    NSString *substring = @"xyz";
    if ([string hasPrefix:substring])
        NSLog(@"string has prefix "); // won't get here.

问题是:有没有内置方法解决这个问题?我的意思是,hasPrefix: 区分大小写?

我至少可以使用下面的答案。但是想知道是否有比这更好的方法..?

已知答案:(请区分大小写)

if ([[test substringWithRange:NSMakeRange(0,3)] caseInsensitiveCompare:@"xyz"] == NSOrderedSame) {
     // ....
}
8个回答

33

来自Apple官方:

NSString *searchString = @"age";

NSString *beginsTest = @"Agencies";
NSRange prefixRange = [beginsTest rangeOfString:searchString
    options:(NSAnchoredSearch | NSCaseInsensitiveSearch)];

// prefixRange = {0, 3}

NSString *endsTest = @"BRICOLAGE";
NSRange suffixRange = [endsTest rangeOfString:searchString
    options:(NSAnchoredSearch | NSCaseInsensitiveSearch | NSBackwardsSearch)];

// suffixRange = {6, 3}

这可以封装成一个易于使用的方法:
- (BOOL) string:(NSString *)string
      hasPrefix:(NSString *)prefix
caseInsensitive:(BOOL)caseInsensitive {

    if (!caseInsensitive)
        return [string hasPrefix:prefix];

    const NSStringCompareOptions options = NSAnchoredSearch|NSCaseInsensitiveSearch;
    NSRange prefixRange = [string rangeOfString:prefix
                                        options:options];
    return prefixRange.location == 0 && prefixRange.length > 0;
}

如果有其他方法可以做到这一点,我会跟随您的。但是我仍在寻找其他方法来实现这一点...任何能帮助未来访问者的方法都会得到额外的加分 :) - Mani
@iMani 除了你在问题中展示的另一种选择和Volker的答案,我怀疑还有许多其他选择。 - trojanfoe
是的,我也在等待那个。如果有其他简单易行的方法而不需要进行范围计算的痛苦就好了。 - Mani
@iMani,我已更新了我的答案,并添加了一种方法,您可以将其添加到其中,这意味着您不需要处理范围,而且可以忘记它们。 - trojanfoe
为什么这比 [[string lowercaseString] hasPrefix:[substring lowercaseString]] 更好?它至少更快吗? - Tibidabo

29

你可以在两个字符串上使用lowercaseString函数,从而强制它们拥有相同的大小写。例如:

[[string lowercaseString] hasPrefix:[substring lowercaseString]];

它会工作。但我不想修改任何字符串。谢谢Volker.. 给你一个赞 :) - Mani
谢谢。@trojanfoe的答案可能更适合,因为你可以选择不同的选项来查找子字符串。 - Volker
8
这个答案不会修改任何字符串。 - zaph

9

一个不好的做法是将两个字符串都转换成小写,然后使用hasPrefix函数进行比较,例如:

[[mainString lowercaseString] hasPrefix:[stringToFind lowercaseString]];

2
这与Volker的答案有何不同? - Amar
@Amar:这个答案是在 Volker 的答案之后仅仅 1 分 44 秒发布的。很可能他们同时打字。但这并不会使他们的答案失去有效性。 - NSGod

6

Swift 5:

extension String {
    public func hasPrefixIgnoringCase(_ prefix: String) -> Bool {
        range(of: prefix, options: [.anchored, .caseInsensitive]) != nil
    }
}

使用方法:

"Hello".hasPrefixIgnoringCase("hEl") // return true

4

您可以通过以下方法实现此目标:

if([[string lowercaseString] hasPrefix:[substring lowercaseString]])
{
NSLog(@"found");
}

1
仅在上面的例子中才能这样工作。稳定版本需要 lowercaseString 适用于两个字符串! - Volker

3

接受答案的 Swift 4.2 版本:

extension String {

    public func hasPrefix<Prefix>(_ prefix: Prefix, caseSensitive: Bool) -> Bool where Prefix : StringProtocol {

        if caseSensitive { return self.hasPrefix(prefix) }

        let prefixRange = self.range(of: prefix, options: [.anchored, .caseInsensitive])
        return prefixRange != nil
    }
}

或者,使用 .lowercased()

extension String {

    public func hasPrefix<Prefix>(_ prefix: Prefix, caseSensitive: Bool) -> Bool where Prefix : StringProtocol {

        if caseSensitive { return self.hasPrefix(prefix) }
        return self.lowercased().hasPrefix(prefix.lowercased())
    }
}

该扩展的使用方法如下:

let string = "Hello World"

let caseSensitiveSearch = string.hasPrefix("hello", caseSensitive: true) // return false
let caseNotSensitiveSearch = string.hasPrefix("hello", caseSensitive: false) // return true

0

对于那些喜欢函数式一行代码的人(就像我一样):

extension String {

    func hasPrefix<Prefix>(_ prefix: Prefix, caseSensitive: Bool) -> Bool where Prefix: StringProtocol {
        return caseSensitive ? hasPrefix(prefix) :
            self.range(of: prefix, options: [.anchored, .caseInsensitive]) != nil
    }

}

0

Swift 5

extension StringProtocol {
    public func hasPrefix<T: StringProtocol>(caseInsensitive prefix: T) -> Bool {
        lowercased().starts(with: prefix.lowercased())
    }
}

使用:

"Hello World".hasPrefix(caseInsensitive: "hello") //true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接