【问题标题】:NSScanner based on last occurrence of substring "@"NSScanner 基于子字符串“@”的最后一次出现
【发布时间】:2013-09-11 17:29:10
【问题描述】:

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

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

到目前为止,我已经能够检测到 @ 符号后面的文本,并在它遇到空白时停止检测。这已经用 NSScanner 完美地完成了。

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

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

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

示例 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);

    }

}

如您所见,我只是不太确定如何使这些协同工作以产生我正在寻找的结果。有任何想法吗?谢谢!

******************************更新************************ ********

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

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

文本字段文本:你好@用户名

这非常有效,正如您所看到的,我可以不断地对照一系列朋友检查此文本。

假设用户想用相同的文本向另一个用户发送消息,如下所示:

你好@username,这是我的朋友@goodfriend

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

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

这也可能与我检测空白以知道用户已完成输入用户名的方式有关,并且不需要更多建议。

希望对您有所帮助,谢谢!

【问题讨论】:

  • 您能发布一个您期望的输入/输出示例吗?
  • @Alladinian 我更新了原始帖子,详细说明了我正在尝试做的事情。简而言之,我需要能够检测用户何时开始输入 @ 符号和用户名,并根据他们输入的内容显示建议。它现在只使用一个用户名,但有两个用户名,它会忽略第二个和第三个,等等

标签: ios nsstring nsrange nsscanner


【解决方案1】:

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

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];
    ...

【讨论】:

  • 我明白你在说什么,这很有道理!在看到您的帖子之前,我只是碰巧自己弄清楚了这一点,所以我很好奇使用一种方法是否有任何优点或缺点?让我在这里发布我的方法作为答案,并告诉我您的想法?非常感谢!
  • @Kyle 这行得通。它通过扫描整个字符串而不是只扫描最后一个单词来执行许多额外的工作,但是对于 140 个字符的字符串,差异可能不会很大。
  • 哦,好吧,我明白你的意思了。性能绝对是使用您建议的方法的一个很好的理由。为此,我会将其标记为正确答案,如果他们有偏好,我会将其留给任何人,非常感谢您的帮助,我很感激!!
【解决方案2】:

所以这是我想出的解决方案。 @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。

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

【讨论】:

    猜你喜欢
    • 2015-05-11
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 2012-03-23
    • 2012-03-17
    • 2011-04-19
    • 2012-06-05
    • 2011-07-26
    相关资源
    最近更新 更多