EXC_BAD_ACCESS crash Please help!

This is driving me a bit crazy.

In the first 2-3 pages of Chapter 23, we are to modify by “adding holder relationship.” Upon making the modifications, the build succeeds but when I run the program I get the message:

thread 1:EXC_BAD_ACCESS (code=2, address=0x7fff5f3ffd98)

and one of the new lines that I have entered into BNRAsset.m is hilighted, namely

return [NSString stringWithFormat:@"<%@: $%d, assigned to %@>", self.label, self.resaleValue, self.holder];

I have checked and rechecked for typos and can’t find any. The project runs fine prior to the additions for Chap. 23 and also runs fine if I modify the above line of code and remove the “self.holder” portion, i.e. if I use

return [NSString stringWithFormat:@"<%@: $%d unassigned>", self.label, self.resaleValue];

I assume I’m overlooking something simple… can anyone review this and help me out? Following is all the code for the modified project.

Thanks!

//
//  BNRAsset.h
//  BMITime with properties

#import <Foundation/Foundation.h>
@class BNREmployee;

@interface BNRAsset : NSObject

@property (nonatomic, copy) NSString *label;
@property (nonatomic) BNREmployee *holder;
@property (nonatomic) unsigned int resaleValue;

@end
//
//  BNRAsset.m
//  BMITime with properties

#import "BNRAsset.h"
#import "BNREmployee.h"

@implementation BNRAsset

- (NSString *)description
{
//    return [NSString stringWithFormat:@"<%@: $%d>", self.label, self.resaleValue];
    // Is holder non-nil?

    if (self.holder) {
        return [NSString stringWithFormat:@"<%@: $%d, assigned to %@>", self.label, self.resaleValue, self.holder];

    } else {
        return [NSString stringWithFormat:@"<%@: $%d unassigned>", self.label, self.resaleValue];
    }

}

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}

@end
//
//  BNREmployee.h
//  BMITime with properties

// #import <Foundation/Foundation.h>
// above not needed because the #import "BNRPerson" already has imported it (?)
#import "BNRPerson.h"
@class BNRAsset;

@interface BNREmployee : BNRPerson
// Move this next declaration to BNREmployee.m as a class extension (Chap. 22)
/*
 {
    NSMutableArray *_assets;
}
 */

@property(nonatomic) unsigned int employeeID;
//@property(nonatomic) int officeAlarmCode; removed in Chap. 22
@property(nonatomic) NSDate *hireDate;
@property(nonatomic, copy) NSArray *assets;

- (double)yearsOfEmployment;
- (void)addAsset:(BNRAsset *)a;
- (void)removeAsset:(BNRAsset *)a;
- (unsigned int)valueOfAssets;

@end
//
//  BNREmployee.m
//  BMITime with properties

#import "BNREmployee.h"
#import "BNRAsset.h"

// A class extension
@interface BNREmployee ()
{
    NSMutableArray *_assets;
}

@property (nonatomic) unsigned int officeAlarmCode;

@end


@implementation BNREmployee

// Accessors for assets properties
- (void)setAssets:(NSArray *)a
{
    _assets = [a mutableCopy];
}

- (NSArray *)assets{
    return [_assets copy];
}

- (void)addAsset:(BNRAsset *)a
{
    // Is asset nil?
    if (!_assets) {
        // Create the array
        _assets = [[NSMutableArray alloc]init];
    }
    [_assets addObject:a];
    a.holder = self;
}

- (void)removeAsset:(BNRAsset *)a
{
    [_assets removeObject:a];
}

- (unsigned int)valueOfAssets
{
    // Sum up the resale value of the assets
    unsigned int sum = 0;
    for (BNRAsset *a in _assets) {
        sum += [a resaleValue];
    }
    return sum;
}

- (NSString *)description
{
//    return [NSString stringWithFormat:@"<Employee %d>", self.employeeID];
    return [NSString stringWithFormat:@"<Employee %d: $%d in assets>, %@", self.employeeID, self.valueOfAssets, self.assets];
}

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}

- (double)yearsOfEmployment
{
    // Do I have a non-nil hiredate?
    if (self.hireDate) {
        // NSTimeInterval is the same as double
        NSDate *now = [NSDate date];
        NSTimeInterval secs = [now timeIntervalSinceDate:self.hireDate];
        return secs / 31557600.0; // secs in a year
    } else {
        return 0;
    }
}

- (float)bodyMassIndex
{
//    return 19.0;
    float normalBMI = [super bodyMassIndex];
    return normalBMI * 0.9;
}

@end
//
//  BNRPerson.h
//  BMITime with properties

#import <Foundation/Foundation.h>

@interface BNRPerson : NSObject

// BNRPerson has two properties
@property (nonatomic) float heightInMeters;
@property (nonatomic) int weightInKilos;

// BNRPerson has a method that calculates the Body Mass Index
- (float)bodyMassIndex;

@end
//
//  BNRPerson.m
//  BMITime with properties

#import "BNRPerson.h"

@implementation BNRPerson

/*
- (float)heightInMeters
{
    return _heightInMeters ;
}

- (void)setHeightInMeters:(float)h
{
    _heightInMeters = h;
}

- (int)weightInKilos
{
    return _weightInKilos;
}

- (void)setWeightInKilos:(int)w
{
    _weightInKilos = w;
}
*/

- (float)bodyMassIndex
{
    float h = [self heightInMeters];
    return [self weightInKilos] / (h * h);
}
@end
//
//  main.m
//  BMITime with properties

#import <Foundation/Foundation.h>
// #import "BNRPerson.h"
#import "BNREmployee.h"
#import "BNRAsset.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        // Create an array of BNREmployee objects
        NSMutableArray *employees = [[NSMutableArray alloc]init];
        
        for (int i = 0; i < 10; i++) {
            // Create and instance of BNR employee
            BNREmployee *mikey = [[BNREmployee alloc] init];
            
            mikey.weightInKilos = 90 + i;
            mikey.heightInMeters = 1.8 - i/10.0;
            mikey.employeeID = i;
            
            // Put the employee in the employees array
            [employees addObject:mikey];
        }
        
        // Create 10 assets
        for (int i = 0; i < 10; i++) {
            // Create an asset
            BNRAsset *asset = [[BNRAsset alloc]init];
            
            // Give it an interesting label
            NSString *currentLabel = [NSString stringWithFormat:@"Laptop %d", i];
            asset.label = currentLabel;
//            NSLog(@"Current label %d is '%@'", i, asset.label);
            asset.resaleValue = i * 17;
            
            // Get a random number between 0 and 9 inclusive
            NSUInteger randomIndex = random() % [employees count];
            
            // Find that employee
            BNREmployee *randomEmployee = [employees objectAtIndex:randomIndex];
            
            // Assign the asset to the employee
            [randomEmployee addAsset:asset];
        }
        
        // Print employees and their assigned assets
        NSLog(@"Employees: %@", employees);
        
        // For Chap. 21 Challenge: removing assets
        // Remove an asset from a random employee if he has an asset
        
        // First, choose a random employee
        // Get a random number between 0 and 9 inclusive
        NSUInteger randomIndex = random() % [employees count];
        NSLog(@"randomIndex is %lu", (unsigned long)randomIndex);
        // Find that employee
        BNREmployee *randomEmployeeLoser = [employees objectAtIndex:randomIndex];
        // Second, check if that employee has any assets
        if (randomEmployeeLoser.assets) {
            NSLog(@"Found an employee with assets");
            // Get his asset count
            NSLog(@"Loser asset count is %lu", (unsigned long)[randomEmployeeLoser.assets count]);
            // Remove his first asset
            [randomEmployeeLoser removeAsset:[randomEmployeeLoser.assets objectAtIndex:0]];
            NSLog(@"Loser asset count after loss is %lu\n\n", (unsigned long)[randomEmployeeLoser.assets count]);
            // Use this if you want his assets to show as (null) if after loss he has 0 assets
            if ([randomEmployeeLoser.assets count] == 0) {
                randomEmployeeLoser.assets = nil;
            }
            // Print employees and their assigned assets
            NSLog(@"Employees: %@\n\n", employees);
        } else {
            NSLog(@"This employee has no assets to remove\n\n");
        }
        
        
        
//        NSLog(@"Giving up ownership of one employee");
        
//        [employees removeObjectAtIndex:5];
        
//        NSLog(@"Giving up ownership of arrays");
        
//        employees = nil;
        
        NSLog(@"\n\n*****  END OF ACTIVE CODE IN main.m  *****\n\n");
        
    }
        
    return 0;
}