Error on page 411


#1

In the
-(void)removeEmployeesObject(Employee *)value

the line
Employee *manager = [self manager];

Should be.

Employee *manager = (Employee *)[self manager];

Found this by comparing code of page 411 to Adam’s downloadable code.


#2

I also ran into the this problem and found the solution the same way. Perhaps my bumping this topic up, will cause Adam to add it to the errata section.


#3

Added!


#4

Fixing a compiler error is not necessarily fixing the problem.

Changing Employee *manager = [self manager]; to Employee *manager = (Employee *)[self manager]; eliminates the compiler error.
Changing Employee *manager = [self manager]; to NSMangedObject *manager = [self manager]; eliminates the compiler error.
Changing @property (nonatomic, retain) NSManagedObject *manager; to @property (nonatomic, retain) Employee *manager; also eliminates the compiler error.

In the first two cases, Department.h remains tainted because of the public declaration that a manager is typed as any NSManagedObject. We know that a manager must be of class Employee.

In all three cases, Department.h remains tainted because of the public declaration that any NSManagedObject class object can be passed to the methods:

  • (void)addEmployeesObject:(NSManagedObject *)value;
  • (void)removeEmployeesObject:(NSManagedObject *)value; We know that the objects passed to these methods must be of class Employee.

In this example, all three corrections eliminate the compiler error and correctly update the data (I tested the class of all the relevant data for each correction).
In the least case scenario Department.h is misleading and not stylish. In the worst case scenario other uses of the Department class, future custom code or even future internal changes to Core Data might allow code to be able to inject data of the wrong class into the mix. A nasty proposition, indeed.

It bothered me that Xcode would create a template with NSManagedObject instead of the proper Employee qualification, so I did some more testing.

It turns out that Xcode will create the proper template if it has enough info to do so.

This sentence on page 409 Make sure that your MyDocument.xcdatamodel file is open in the editor[color=#FF0000],[/color] and select [color=#FF0000]one[/color] of the entries.
Should be changed to: Make sure that your MyDocument.xcdatamodel file is open in the editor and select both the Department and Employee entries.

By creating the NSManagedObject Subclass for both entities at the same time, Xcode has all the necessary info to produce the proper Document.h template as shown below.

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

@class Employee;

@interface Department : NSManagedObject

@property (nonatomic, retain) NSString * deptName;
@property (nonatomic, retain) NSSet *employees;
@property (nonatomic, retain) Employee *manager;
@end

@interface Department (CoreDataGeneratedAccessors)

  • (void)addEmployeesObject:(Employee *)value;
  • (void)removeEmployeesObject:(Employee *)value;
  • (void)addEmployees:(NSSet *)values;
  • (void)removeEmployees:(NSSet *)values;

The code in Department.m is correct.