【问题标题】:iOS 5.1 Core Data Memory LeakiOS 5.1 核心数据内存泄漏
【发布时间】:2012-03-27 22:39:32
【问题描述】:

我正在尝试将每个 Core Data 实体的 Core Data 调用集中到一个 Helper 类中。每个 Helper 类都包含实体的 fetch、update 和 insert 方法。对于一个实体助手类,当我在这一行分析应用程序时出现内存泄漏:

NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];

ARC 已打开,并且在卸载视图后出现泄漏。

下面是相关的 ViewController 和 Helper Class 代码:

ViewController.m

@synthesize location // and other properties...;

- (void)viewDidLoad
{
    [self loadLocation];
    [super viewDidLoad];
}

- (void)viewDidUnload 
{
    // Set properties to nil here

    [super viewDidUnload];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)loadLocation
{
    if (self.locationID.intValue > 0)
    {
        LocationCoreDataHelper *helper = [[LocationCoreDataHelper alloc] init];
        self.location = [helper selectLocationWithPredicate:[NSString stringWithFormat:@"id = %d", self.locationID.intValue]];

        if(self.location)
        {
            // Create a new coordinate of the user's location
            CLLocationCoordinate2D coord;
            coord.latitude = [self.location.latitude doubleValue];
            coord.longitude =[self.location.longitude doubleValue];

            // Annotate the point with user's information
            MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
            point.coordinate = coord;
            point.title = self.location.title;
            point.subtitle = self.location.subtitle;

            // Add the annotated point
            [mkMap addAnnotation:point];  

            // Set the viewable region of the map
            MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(point.coordinate, 5000, 5000);

            [mkMap setRegion:region animated:YES]; 
        }

        helper = nil;
    }
}

location 属性定义为实体的托管对象类。

LocationCoreDataHelper.m

@implementation LocationCoreDataHelper

- (id)init
{
    if(self = [super init])
    {
        // Setup the core data manager if needed
        if(managedObjectContext == Nil)
        {
            managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
        }        
    }

    return self;
}

- (Location *)selectLocationWithPredicate:(NSString *)predicateString
{
    NSError *error = nil;

    // Build the entity and request
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Location" inManagedObjectContext:managedObjectContext];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];

    if(predicateString)
    {
        // Set the search criteria
        NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
        [request setPredicate:predicate];
    }

    // Perform the search
    // LEAK HERE
    NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];  

    if(results.count >0)
    {
        return (Location *)[results lastObject];
    }
    else
    {
        return nil;
    }
}

// Other methods here
@end

我无法弄清楚为什么那里会发生内存泄漏。有什么想法吗?

更新 #1:

如果我替换这个:

point.coordinate = coord;
point.title = self.location.title;
point.subtitle = self.location.subtitle;

用这个:

point.coordinate = coord;
point.title = @"Title";
point.subtitle = @"Subtitle";

NSLog(@"%@", self.location.title);

我没有得到内存泄漏。这是为什么呢?

【问题讨论】:

  • 听起来像是一个保留循环:制作 point.titlepoint.subtitle 弱引用?
  • 你试过开启静态分析器吗?
  • @Inafziger:如何使 MKPointAnnotation 的 Title 和 SubTitle 属性成为弱引用?
  • @LuisOscar:静态分析器没有出现任何问题。
  • 啊,没看到是MKPointAnnotation。在您的 Viewcontroller.m 中,将 mkMap = nil 添加到您的 viewDidUnload 中,它应该可以解决问题。

标签: core-data ios5 memory-leaks


【解决方案1】:

感谢 Inafziger 为我指明了正确的方向。我最终不得不像这样创建一个自定义的 MKAnnotation 类:

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MyAnnotation : NSObject <MKAnnotation>

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy, readonly) NSString *title;
@property (nonatomic, copy, readonly) NSString *subtitle;

- (id) initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates
                     title:(NSString *)paramTitle
                     subTitle:(NSString *)paramSubTitle;

@end

我像这样更新了我的视图控制器:

MyAnnotation *point = [[MyAnnotation alloc] initWithCoordinates:coord
                                                          title:self.location.title
                                                       subTitle:self.location.subtitle];

通过这种方式实现自定义注解类,解决了内存泄漏的问题。我仍然不能 100% 确定 Instruments 为什么将泄漏指向 Core Data 调用。也许是因为那是 NSManagedObject 的来源,而这不是正确发布的?

【讨论】:

    猜你喜欢
    • 2011-09-19
    • 1970-01-01
    • 2015-11-05
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    相关资源
    最近更新 更多