Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object property with strong reference becomes null

A key of an array that's set on a property on another object (dataController in BWMasterViewController) with a strong reference becomes null. I don't understand why.

BWMasterViewController

header:

#import <UIKit/UIKit.h>

@class BWBirdSightingDataController;

@interface BWMasterViewController : UITableViewController
@end

implementation:

#import "BWMasterViewController.h"
#import "BWBirdSightingDataController.h"
#import "Bird.h"
#import "BWWebviewController.h"

@interface BWMasterViewController()
@property (strong, nonatomic) BWBirdSightingDataController *dataController;
@property (copy, nonatomic) NSString *test;
@end

@implementation BWMasterViewController

- (void)awakeFromNib
{

    [super awakeFromNib];

    NSLog(@"awake from nib");
    self.dataController = [[BWBirdSightingDataController alloc] init];
    self.test = @"Test var";

    NSLog(@"test: %@", self.test);
    Bird *bird = [self.dataController objectInListAtIndex:0];
    NSLog(@"bird object: %@", bird);
    NSLog(@"bird name: %@", bird.name)

}

- (void)viewDidLoad
{

    [super viewDidLoad];

    NSLog(@"view did load");

    NSLog(@"test: %@", self.test);
    Bird *bird = [self.dataController objectInListAtIndex:0];
    NSLog(@"bird object: %@", bird);
    NSLog(@"bird name: %@", bird.name)

}

// ....

BWBirdSightingDataController

header:

#import <Foundation/Foundation.h>

@class Bird;

@interface BWBirdSightingDataController : NSObject
- (NSUInteger)countOfList;
- (Bird *)objectInListAtIndex:(NSUInteger)theIndex;
@end

implementation:

#import "BWBirdSightingDataController.h"
#import "BWDataController.h"
#import "Bird.h"

@interface BWBirdSightingDataController ()
-(void)initializeDefaultDataList;
@property (nonatomic, copy) NSMutableArray *birds;
@end

@implementation BWBirdSightingDataController

- (id)init
{

    if (self = [super init]) {
        [self initializeDefaultDataList];
        return self;
    }

    return nil;

}

- (void)initializeDefaultDataList
{

    BWDataController *dataController = [[BWDataController alloc] init];

    NSEntityDescription *birdsEntity = [NSEntityDescription
                                        entityForName:@"Bird"
                                        inManagedObjectContext:dataController.managedObjectContext];
    NSFetchRequest *fetchBirds = [[NSFetchRequest alloc] init];
    [fetchBirds setEntity:birdsEntity];

    NSError *fetchError = nil;
    NSArray *birdsObjects = [dataController.managedObjectContext
                             executeFetchRequest:fetchBirds
                             error:&fetchError];
    self.birds = [birdsObjects mutableCopy];

}

- (NSUInteger)countOfList
{
    return [self.birds count];
}

- (Bird *)objectInListAtIndex:(NSUInteger)theIndex
{
    return self.birds[theIndex];
}

@end

Bird

Bird is a NSManagedObject based on a CoreData Entity.

header:

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


@interface Bird : NSManagedObject

@property (nonatomic, retain) NSDate * date;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * location;
@property (nonatomic, retain) NSString * image;
@property (nonatomic, retain) NSString * url;

@end

implementation:

#import "Bird.h"


@implementation Bird

@dynamic date;
@dynamic name;
@dynamic location;
@dynamic image;
@dynamic url;

@end

Output

When I run it, this outputs:

2013-05-31 11:36:47.824 BirdWatching[69565:c07] awake from nib
2013-05-31 11:36:47.834 BirdWatching[69565:c07] test: Test var
2013-05-31 11:36:47.834 BirdWatching[69565:c07] bird object: <Bird: 0x8545ec0> (entity: Bird; id: 0x8545040 <x-coredata://D24A664F-8E8F-4AF0-891C-098C8A7DD860/Bird/p1> ; data: <fault>)
2013-05-31 11:36:47.835 BirdWatching[69565:c07] bird name: Pigeon
2013-05-31 11:36:47.839 BirdWatching[69565:c07] view did load
2013-05-31 11:36:47.840 BirdWatching[69565:c07] test: Test var
2013-05-31 11:36:47.840 BirdWatching[69565:c07] bird object: <Bird: 0x8545ec0> (entity: Bird; id: 0x8545040 <x-coredata://D24A664F-8E8F-4AF0-891C-098C8A7DD860/Bird/p1> ; data: <fault>)
2013-05-31 11:36:47.840 BirdWatching[69565:c07] bird name: (null)

So as you can see, in the viewDidLoad function the bird.name has become null. How come? I declared the property as a strong reference.

I have the same problem when I would define self.dataController in viewDidLoad, then it would be null in prepareForSegue, where I also need it.

like image 334
gitaarik Avatar asked May 31 '13 08:05

gitaarik


1 Answers

You create the Bird objects in initializeDefaultDataList using the local BWDataController *dataController. dataController is automatically deallocated at the end of this method, which probably means that the managed object context dataController.managedObjectContext also no longer exist.

However, a managed object can only live in the context that it was created in. If the context is destroyed then exactly that happens: Accessing all properties returns nil.

Possible solutions:

  • Make dataController a strong property of BWBirdSightingDataController instead of a local variable.
  • Use a shared managed object context across the application.
like image 74
Martin R Avatar answered Nov 15 '22 19:11

Martin R