编辑:我在项目中使用ARC

我从plist加载注释,如下所示:

[NSThread detachNewThreadSelector:@selector(loadPList) toTarget:self withObject:nil];


...

- (void) loadPList
{

    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *path = [[documentPaths lastObject] stringByAppendingPathComponent:@"test.plist"];

    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; // memory leak here

    NSMutableArray *annotations = [[NSMutableArray alloc]init];


    dispatch_async(dispatch_get_main_queue(), ^{


        NSMutableArray * annotationsToRemove = [ mapView.annotations mutableCopy ] ;
        [ annotationsToRemove removeObject:mapView.userLocation ] ;
        [ mapView removeAnnotations:annotationsToRemove ] ;



        if ([[NSUserDefaults standardUserDefaults] boolForKey:@"blackKey"])
        {

            NSArray *ann = [dict objectForKey:@"Black"];

            for(int i = 0; i < [ann count]; i++) {

                NSString *coordinates = [[ann objectAtIndex:i] objectForKey:@"Coordinates"];

                double realLatitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:1] doubleValue];
                double realLongitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:0] doubleValue];

                MyAnnotation *myAnnotation = [[MyAnnotation alloc] init];
                CLLocationCoordinate2D theCoordinate;
                theCoordinate.latitude = realLatitude;
                theCoordinate.longitude = realLongitude;

                myAnnotation.coordinate=CLLocationCoordinate2DMake(realLatitude,realLongitude);
                myAnnotation.title = [[ann objectAtIndex:i] objectForKey:@"Name"];
                myAnnotation.subtitle = [[ann objectAtIndex:i] objectForKey:@"Address"];
                myAnnotation.icon = [[ann objectAtIndex:0] objectForKey:@"Icon"];

                [mapView addAnnotation:myAnnotation];
                [annotations addObject:myAnnotation];

            }

        }


    });


}


所有加载都正常,但是内存泄漏工具显示了泄漏。

最佳答案

您需要将@autoreleasepool放在方法的开头-在其外部进行dictionaryWithContentsOfFile:调用,这是在创建没有池的自动释放对象,因此它会泄漏。 Per the threading programming guide


  如果您的应用程序使用托管内存模型,则创建一个
  自动释放池应该是您在线程条目中要做的第一件事
  常规。同样,销毁此自动释放池应该是
  您在线程中所做的最后一件事。


另外,请问为什么您使用NSThread而不是使用全局队列的dispatch_async()来加载plist?我很少看到dispatch_async()嵌套在线程分离中,所以很好奇。

编辑:

要修复内存泄漏,而又不打扰线程/ GCD混合,请按以下方式调用您的方法:

[NSThread detachNewThreadSelector:@selector(loadPList) toTarget:self withObject:nil];


并像这样实现它:

- (void) loadPList
{
    @autoreleasepool {
        NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString *path = [[documentPaths lastObject] stringByAppendingPathComponent:@"test.plist"];

        NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; // memory leak here

        NSMutableArray *annotations = [[NSMutableArray alloc]init];


        dispatch_async(dispatch_get_main_queue(), ^{

            NSMutableArray * annotationsToRemove = [ mapView.annotations mutableCopy ] ;
            [ annotationsToRemove removeObject:mapView.userLocation ] ;
            [ mapView removeAnnotations:annotationsToRemove ] ;

            if ([[NSUserDefaults standardUserDefaults] boolForKey:@"blackKey"])
            {
                NSArray *ann = [dict objectForKey:@"Black"];

                for(int i = 0; i < [ann count]; i++)
                {
                    NSString *coordinates = [[ann objectAtIndex:i] objectForKey:@"Coordinates"];

                    double realLatitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:1] doubleValue];
                    double realLongitude = [[[coordinates componentsSeparatedByString:@","] objectAtIndex:0] doubleValue];

                    MyAnnotation *myAnnotation = [[MyAnnotation alloc] init];
                    CLLocationCoordinate2D theCoordinate;
                    theCoordinate.latitude = realLatitude;
                    theCoordinate.longitude = realLongitude;

                    myAnnotation.coordinate=CLLocationCoordinate2DMake(realLatitude,realLongitude);
                    myAnnotation.title = [[ann objectAtIndex:i] objectForKey:@"Name"];
                    myAnnotation.subtitle = [[ann objectAtIndex:i] objectForKey:@"Address"];
                    myAnnotation.icon = [[ann objectAtIndex:0] objectForKey:@"Icon"];

                    [mapView addAnnotation:myAnnotation];
                    [annotations addObject:myAnnotation];
                }
            }
        }
        );
    }
}

08-25 23:02
查看更多