【问题标题】:NSMakeRange causes app to lock up; slow performanceNSMakeRange 导致应用程序锁定;性能缓慢
【发布时间】:2014-06-01 01:27:11
【问题描述】:

我有一个困境,我认为到目前为止我已经很好地解决了。但是,当我使用 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;
}

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

【问题讨论】:

    标签: ios objective-c uitableview nsstring nsrange


    【解决方案1】:

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

    214748364710 == 0x7FFFFFFF16 等于 231-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。

    【讨论】:

    • 2147483647 是 0x7FFFFFFF,在 32 位系统上是 NSNotFound。经常检查错误!当然,“幸福之路”更有趣,但该死的,错误可以杀死!也必须处理“不愉快的道路”。
    • ~ 22 亿个字母对于大多数文本来说应该足够了。
    • 如果您需要超过 22 亿个字符,则必须使用 64 位处理器的 iPhone 5 或 iPad Air,其中 NSIntegerMax 更大。 ;)
    • 不,这是正确的:您的字符串不存在,或者您正在搜索的对象为 nil。
    • 嗯,没有。那是不可能的。您应该使用创建字典的代码提出一个新问题。
    【解决方案2】:

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

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

    你会得到同样的异常。

    此外,如果您还没有为 Xcode 中的所有异常添加断点,您可以检查代码中发生这种情况的位置。

    【讨论】:

    • 是的,总是添加一个异常断点——除非你使用的是 Core Data,否则它会在“快乐路径”中使用异常——呃!
    猜你喜欢
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多