NSScanner基于最后一次出现的子串" @"

时间:2013-09-07 20:34:52

标签: ios nsstring nsrange nsscanner

我有一个类似于使用@符号的twitters的用户名系统。

我已将其设置为通过键入@username来向用户发送消息。这与推特中的提及基本相同。

到目前为止,我已经能够检测@符号后面的文本并停止检测它何时到达空白区域。这与NSScanner完美结合。

我的问题是如果我想要发送多个@usernames,NSScanner将只检测第一次出现。我需要它来检测最新的事件。我发现这是一个有用的工具:

NSRange lastSymbol = [text rangeOfString:@"@" options:NSBackwardsSearch];

我似乎无法弄清楚如何与NSScanner一起正确使用它。以下是我的代码尝试的两个示例。

示例1:

NSString *user = nil;
NSString *text = textView.text;

NSRange lastSymbol = [text rangeOfString:@"@" options:NSBackwardsSearch];

if (lastSymbol.location != NSNotFound) {

    NSScanner *userScanner = [NSScanner scannerWithString:text];
    [userScanner scanUpToString:@"@" intoString:nil];

    NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:@"@"];

    if (![userScanner isAtEnd]) {

        [userScanner scanUpToCharactersFromSet:charset intoString:nil];
        [userScanner scanCharactersFromSet:charset intoString:nil]
        [userScanner scanUpToCharactersFromSet:charset intoString:&user];


    }
}


if (user.length > 0) {

    NSRange whiteSpaceRange = [user rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]];
    if (whiteSpaceRange.location != NSNotFound) {

        // White space, username has ended

    } else {

        // Still getting username
        NSLog(@"%@", user);

    }

}

正如您所看到的,我不太确定如何将这些工作结合起来以产生我正在寻找的结果。有任何想法吗?谢谢!

************************** UPDATE ******************** ********

更具体地说,当用户键入@符号并开始输入用户名时,我想根据他们键入的内容显示他们的朋友列表。很自然地,我想在@符号后面拉出字符串,并且当用户继续输入时,不断更新他们的朋友列表。一旦用户键入一个空格,我们就会假设他们输入了用户名(用户名不能包含空格),所以我就停止显示表视图。

到目前为止,上面的代码只是检测并拉出@符号后面的字符串。这是现在的输出:

文本字段文本:Hello @username

enter image description here

这非常有效,因为你可以看到我可以继续对一群朋友检查这个文本。

假设用户希望在同一文本中向其他用户发送消息,如下所示:

Hello @username,这是我的朋友@goodfriend

这次它仍会显示第一个@username,但忽略第二个@goodfriend。

我认为最好的方法是以某种方式告诉NSScanner引用@符号的最后一次出现,因为我现在所拥有的只是引用第一个@符号。

这可能还与我检测空白区域的方式有关,以便知道用户输入了用户名,并且不再需要任何建议。

希望这有帮助,谢谢!

2 个答案:

答案 0 :(得分:2)

对于使用这样的实时输入,我建议使用完全不同的方法。不要寻找最后一个“@”,而是查看最后一个单词,看看它是否以“@”开头。

NSString *user = nil;
NSString *text = textView.text;
// Find the last whitespace character
NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
NSRange lastWordRange = [text rangeOfCharacterFromSet:whitespace options:NSBackwardsSearch];
// If found, get the index after it. Otherwise, the entire string is one word.
if(lastWordRange.location != NSNotFound)
    lastWordRange.location += lastWordRange.length;
else lastWordRange.location = 0;
// If the index is not at the end, look for a '@' right after it
if(lastWordRange.location < [text length] &&
   [text characterAtIndex:lastWordRange.location] == '@') {
    // Found a '@', use the rest of the string as the username
    user = [text substringFromIndex:lastWordRange.location+1];
}
if(user) NSLog(@"%@", user); // The user is still typing a name

如果您真的想使用扫描仪,可以使用相同的substringFromIndex:方法来获取要扫描的子字符串。

NSRange lastSymbol = [text rangeOfString:@"@" options:NSBackwardsSearch];
if (lastSymbol.location != NSNotFound) {
    NSString *substring = [text substringFromIndex:lastSymbol.location];
    NSScanner *userScanner = [NSScanner scannerWithString:substring];
    ...

答案 1 :(得分:0)

所以这是我提出的解决方案。 @ugjoavgfhw有一个方法也适用于我所做的有限测试。

这是我的解决方案:

NSString *user = nil;
NSString *text = textView.text;

NSRange lastSymbol = [text rangeOfString:@"@" options:NSBackwardsSearch];
NSScanner *userScanner = [NSScanner scannerWithString:text];
if (lastSymbol.location < 140) {
    [userScanner setScanLocation:lastSymbol.location];
}

[userScanner scanUpToString:@"@" intoString:nil];
NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:@"@"];

if (![userScanner isAtEnd]) {        

    if (lastSymbol.location != NSNotFound) {

        [userScanner scanUpToCharactersFromSet:charset intoString:nil];
        [userScanner scanCharactersFromSet:charset intoString:nil];
        [userScanner scanUpToCharactersFromSet:charset intoString:&user];

    }

}


if (user.length > 0) {

    NSRange whiteSpaceRange = [user rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]];
    if (whiteSpaceRange.location != NSNotFound) {

        // White space, username has ended

    } else {

        // Still getting username
        NSLog(@"%@", user);

    }


}

为了清楚起见,这个代码在委托方法中调用:

- (void)textViewDidChange:(UITextView *)textView

每次文本更新时,我们都会执行向后搜索以查找@符号。这被分配给NSRange。

然后创建NSScanner。之后我们检查lastSymbol.location以确保它低于140个字符(格式与具有有限字符的twitter相同)。

如果是,则我们将扫描位置分配给NSScanner。

其余的按预期工作。希望这有助于其他人!