0

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

谢谢您的帮助。

只是以下代码使应用程序崩溃:

    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();
    }
4

3 回答 3

2

我猜您的应用程序在没有可读异常的情况下崩溃,因为它用完了可用的 RAM,特别是因为您指出它正在运行大量迭代。

对于测试,我建议按照 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 上。)

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

于 2013-03-01T18:31:46.380 回答
1

你为什么要创建[array count]自动释放池?创造这么多它们有什么意义?它可能因此而崩溃。将@autoreleasepool外部放在 for 循环中。我认为您会这样做的唯一原因是,如果您在 for 循环的每次迭代中创建了如此多的瞬态对象,以至于您希望在退出迭代后立即摆脱它们。但是还有其他方法可以做到这一点,包括在每次迭代中重用这些对象。

于 2013-03-01T18:18:18.050 回答
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)]];


        }
    }
}

这还有一个额外的好处是可以帮助您放弃自动释放池

这是无效的

如果您的阵列确实有 175260 行,那可能是您的问题。您正在使用 unsigned int 作为索引变量进行循环。c 中无符号整数的最大值仅为 65535。使用无符号长整数,最大值为 4294967295。

于 2013-03-01T18:34:01.593 回答