iOS - 在循环过程中应用程序崩溃而没有错误

时间:2013-03-01 18:08:53

标签: ios objective-c arrays loops crash

在循环过程中,我的应用程序崩溃而没有错误。数组计数等于175260.使用分析器我没有泄漏,所以我不知道为什么App退出,可能在很长一段时间内CPU使用率为100%?

感谢您的帮助。

以下代码崩溃App:

    for(unsigned int i = 0; i <14;i++)
    {
        if(findSensor[i]==YES)
        {
            for(unsigned int j = 1; j <[array count];j++)
            {
                @autoreleasepool {

                    if([[[[array objectAtIndex:j] componentsSeparatedByString:@";"] objectAtIndex:0] isEqualToString:[NSString stringWithFormat:@"%d",10*(i+1)]])
                    {
                        //Code here 
                    }
                }
            }
        }
    }

完整的代码是:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [NSString stringWithFormat:@"%@/%@",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase];

NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:fileName];

NSFileHandle *output = [NSFileHandle fileHandleForReadingAtPath:[NSString stringWithFormat:@"%@/%@10",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase]];

if(output == nil)
{

    NSManagedObjectContext *context = [self managedObjectContext];
    _recordlocal = [NSEntityDescription insertNewObjectForEntityForName:@"RECORD" inManagedObjectContext:context];
    _recordlocal.date = [ibNavSettings interfaceSettings].selectedFileToDataBase;

    NSData *inputData = [NSData dataWithData:[fh readDataToEndOfFile]];

    NSString *inputString = [[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding];

    NSArray *array = [[NSArray alloc] initWithArray:[inputString componentsSeparatedByString:@"\n"]];


    for(unsigned int i = 0; i <14;i++)
    {
        if(findSensor[i]==YES)
        {
            [[NSFileManager defaultManager] createFileAtPath:[NSString stringWithFormat:@"%@/%@%d",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase,10*(i+1)] contents:nil attributes:nil];

            NSMutableString *saveString = [[NSMutableString alloc] init];

            int count = 0;

            for(unsigned int j = 1; j <[array count];j++)
            {
                @autoreleasepool {

                    if([[[[array objectAtIndex:j] componentsSeparatedByString:@";"] objectAtIndex:0] isEqualToString:[NSString stringWithFormat:@"%d",10*(i+1)]])
                    {
                        [saveString appendString:[array objectAtIndex:j]];
                        [saveString appendString:@"\n"];
                        if(i == 0)
                            count++;
                        progress++;
                        pourcent = progress/total;
                        load = pourcent*100;
                        if(load%5==0)
                            [self performSelectorInBackground:@selector(changeUI:)withObject:[NSNumber numberWithFloat:(pourcent)]];


                    }
                }
            }

            [saveString writeToFile:[NSString stringWithFormat:@"%@/%@%d",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase,10*(i+1)] atomically:YES encoding:NSUTF8StringEncoding error:nil];
            if(i == 0)
                _recordlocal.count = [[NSNumber alloc] initWithInt:(count/50)];
        }

    }

    _recordlocal.load = [[NSNumber alloc] initWithBool:YES];

    NSError *error = nil;
    if (![context save:&error]) {
        NSLog(@"Core data error %@, %@", error, [error userInfo]);
        abort();
    }

3 个答案:

答案 0 :(得分:2)

我猜你的应用程序崩溃没有可读的异常,因为它的可用内存不足,特别是因为你指出它正在运行大量的迭代。

对于测试,我建议做Rikkles建议的自动释放池。另外,由于i的值(以及比较字符串的结果)很少改变,我也会在j循环之外创建该字符串。这样可以避免产生大量额外的字符串。

除此之外,因为看起来你正在寻找一个由分号分隔的字符串开头的字符串,我建议不要使用componentsSeparatedByString而是检查元素零,你使用NSString方法hasPrefix来检查对于你正在寻找的条件。

以下是一个例子:

for(unsigned int i = 0; i <14;i++)
{
    NSString *searchString = [NSString stringWithFormat:@"%d;", 10*(i+1)];
    if(findSensor[i]==YES)
    {
        for(unsigned int j = 1; j <[array count];j++)
        {
            if([[array objectAtIndex:j] hasPrefix:searchString])
            {
                //Code here 
            }
        }
    }
}

(我希望这可以编译并运行,如果没有,它应该需要的不仅仅是微调。我现在远离我的Mac。)

如果这没有帮助,那么//代码里面发生的事情必定是罪魁祸首。

答案 1 :(得分:1)

为什么要创建[array count] autoreleasepool?创造这么多人的意义何在?因此可能会崩溃。将@autoreleasepool置于for循环之外。 我认为你会这样做的唯一原因是,如果你在for循环的每次迭代中创建了这么多瞬态对象,那么一旦你离开迭代,你就想要摆脱它们。但还有其他方法可以做到这一点,包括在每次迭代中重用这些对象。

答案 2 :(得分:0)

第一个建议

对内循环使用快速枚举,实际上并没有使用索引'j'来代替

https://developer.apple.com/library/mac/documentation/General/Conceptual/DevPedia-CocoaCore/Enumeration.html

第二个建议

放置一些NSLog,它会减慢一切,但你需要弄清楚你失败的地方。这将有助于指出每个人都朝着正确的方向前进。

第三个建议

实际使用NSError对象并在抛出错误时输出它们的值:

NSError *writeError = nil;
[saveString writeToFile:[NSString stringWithFormat:@"%@/%@%d",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase,10*(i+1)] 
             atomically:YES 
               encoding:NSUTF8StringEncoding 
                  error:&writeError];
if(error != nil) NSLog(@"error writing file: %@", [[writeError userInfo]description]);

第四个建议

您似乎尝试从后台线程更新UI。这将无法工作或将导致崩溃。 UI代码只能从主线程调用。所以不要这样做:

[self performSelectorInBackground:@selector(changeUI:)withObject:[NSNumber numberWithFloat:(pourcent)]];

如果您已经在后台线程上,这可能会崩溃,因为您在线程上的线程上创建线程。你想要打电话:

[self performSelectorOnMainThread:@selector(changeUI:)withObject:[NSNumber numberWithFloat:(pourcent)]];

第五个建议

你可能会超过NSString的最大长度(它很大但我之前做过一次)。您应该只是在循环的每次迭代中附加文件,因此您没有不断增长的NSMutableString:

NSString *path = [NSString stringWithFormat:@"%@/%@%d",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase,10*(i+1)]
NSFileHandle *fh  = [NSFileHandle fileHandleForWritingAtPath:filePath];

NSData *newLine = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
for(NSString *rowString in array)
{
    if([[[rowString componentsSeparatedByString:@";"] objectAtIndex:0] isEqualToString:[NSString stringWithFormat:@"%d",10*(i+1)]])
    {
        NSData *stringData = [rowString dataUsingEncoding:NSUTF8StringEncoding];
        [fh truncateFileAtOffset:[fh seekToEndOfFile]];
        [fh writeData:stringData];
        [fh truncateFileAtOffset:[fh seekToEndOfFile]];
        [fh writeData:newLine];
        if(i == 0)
            count++;
        progress++;
        pourcent = progress/total;
        load = pourcent*100;
        if(load%5==0)
            [self performSelectorOnMainThread:@selector(changeUI:)withObject:[NSNumber numberWithFloat:(pourcent)]];


        }
    }
}

这有助于你放弃autoreleasepools

这是无效的

如果您的阵列实际上有175260行,那可能就是您的问题。您使用unsigned int作为索引var进行循环。 c中的无符号整数的最大值为65535.使用unsigned long int,最大值为4294967295。