NSMakeRange导致应用程序锁定;性能缓慢

时间:2014-06-01 01:27:12

标签: ios objective-c uitableview nsstring nsrange

我有一个困境,我认为到目前为止我解决得很好。但是,当我使用UITableView测试时,我会收到各种警告,例如:

[__NSCFString substringWithRange:]: Range {2147483647, 2147483701} out of bounds; string length 56. This will become an exception for apps linked after 10.9. Warning shown once per app execution.

我将在下面发布我的方法之前描述我想要做的事情。基本上,当用户上传个人资料照片时,我在其用户名之后设置了一个唯一的子字符串,但在文件扩展名(.png)之前示例:JohnDoe的用户名采用新的个人资料照片,我将文件名设置为:

NSString *file = [NSString stringWithFormat:@"JohnDoe%@.png",[[NSProcessInfo processInfo] globallyUniqueString]];

我这样做,以便应用程序稍后可以告诉它是否需要下载用户的朋友的新个人资料图片,基于查看这个完整的NSString是否在本地保存到磁盘,如果我找不到它保存在本地,我只需下载它来自网络。问题很可能来自UITableView连续调用该方法。

此外,这需要在客户端进行,因此请不要讨论后端相关的解决方案。

这是我想出的用于获取用户的配置文件图像文件名的实际唯一NSString的方法。我的这种方法在:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法

中调用
- (NSString *)actualPhotoPath:(NSDictionary *)input
{
    // This code needs work, ridiculous bottle neck!
    NSRange r1 = [[input objectForKey:@"pic"] rangeOfString:[input objectForKey:@"username"]];
    NSRange r2 = [[input objectForKey:@"pic"] rangeOfString:@".png"];
    NSRange rSub = NSMakeRange(r1.location + r1.length, r2.location - r1.location - r1.length);
    // Hangs up on the below line of code eventually
    NSString *sub = [[input objectForKey:@"pic"] substringWithRange:rSub];
    NSString *actual = [NSString stringWithFormat:@"%@%@.png",[input objectForKey:@"username"],sub];
    NSLog(@"%@",actual);
    return actual;
}

感谢您提供的任何帮助!谢谢

2 个答案:

答案 0 :(得分:4)

您应该检查if(r1.location != NSNotFound)if(r2.location != NSNotFound)

2147483647 10 == 0x7FFFFFFF 16 等于2 31 -1,它是32位系统上最高的NSInteger值,也是名为NSIntegerMax

查看docs

enum {
   NSNotFound = NSIntegerMax
};

- (NSString *)actualPhotoPath:(NSDictionary *)input
{
    NSRange r1 = [[input objectForKey:@"pic"] rangeOfString:[input objectForKey:@"username"]];
    NSRange r2 = [[input objectForKey:@"pic"] rangeOfString:@".png"];

    if(r1.location != NSNotFound && r2.location != NSNotFound){
        NSRange rSub = NSMakeRange(r1.location + r1.length, r2.location - r1.location - r1.length);

        NSString *sub = [[input objectForKey:@"pic"] substringWithRange:rSub];
        NSString *actual = [NSString stringWithFormat:@"%@%@.png",[input objectForKey:@"username"],sub];
        NSLog(@"%@",actual);
        return actual;
    }

    // if the code reaches this block, one of the ranges didn't work.
    // do what ever must be done in that case here
    return nil;
}

实际上你应该首先创建r1,如果location!= NSFound,你应该使用r2的位置来确保在它之后找到一个字符串png。

- (NSString *)actualPhotoPath:(NSDictionary *)input
{
    NSRange r1 = [[input objectForKey:@"pic"] rangeOfString:[input objectForKey:@"username"]];
    if (r1.location != NSNotFound ) {
        NSRange r2 = [[[input objectForKey:@"pic"] substringFromIndex:r1.location] rangeOfString:@".png"];

        if(r2.location != NSNotFound){
            NSRange rSub = NSMakeRange(r1.location + r1.length, r2.location - r1.location - r1.length);

            NSString *sub = [[input objectForKey:@"pic"] substringWithRange:rSub];
            NSString *actual = [NSString stringWithFormat:@"%@%@.png",[input objectForKey:@"username"],sub];
            NSLog(@"%@",actual);
            return actual;
        }
    }
    return nil;
}

或者您可以使用NSRegularExpressions或NSScanner。

答案 1 :(得分:0)

您应该检查您的范围在未签名的区域内是否有效。例如,如果你这样做:

NSString* s = [@"foo" substringWithRange: {NSNotFound, 0}];

你会得到同样的例外。

此外,如果您还没有,则在Xcode中为所有例外添加断点,您可以检查代码中的这种情况。