Cocoa Design pattern
@interface PayCalculator : NSObject { IBOutlet NSTextField *employeeNameField; IBOutlet NSFormCell *hourlyRateField; IBOutlet NSFormCell *hoursWorkedField; IBOutlet NSFormCell *standardHoursInPeriodField; IBOutlet NSTextField *payAmountField; IBOutlet NSButton *employeeIsExemptButton; } - (IBAction)calculatePayAmount:(id)sender; @end
Outlets are merely pointers to other objects, and Actions are messages that are sent from object to object.
The Outlets are connected to other objects such as text input fields in Interface Builder. Similarly, a connection is made from the Calculate button to the -calculatePayAmount: action to specify that the calculatePayAmount: message should be sent whenever the button is pressed.
The MYEmployee design identifies all of the attributes needed for the Pay Calculator example: hourlyRate,hoursWorked... It doesn't really matter how the attributes are stored for each instance of the MYEmployee class. NSManagedObject makes the underlying storage irrelevant. All that's needed is to implement the application-specific logic in the MYEmployee class and the Model is complete:
#import "MYEmployee.h" @implementation MYEmployee + (NSSet *)keyPathsForValuesAffectingPayAmount { // return names of attributes that affect payAmount return [NSSet setWithObjects:@"isExempt", @"hourlyRate", @"hoursWorked", @"standardHours", nil]; } - (NSNumber *)payAmount { // return a calculated pay amount based on other attributes float calculatedPayAmount; float hourlyRate = [[self valueForKey:@"hourlyRate"] floatValue]; float standardNumberOfHours = [[self valueForKey:@"standardHours"] floatValue]; if([[self valueForKey:@"isExempt"] boolValue]) { // Pay the hourly rate times the standard number of hours // regardless of the actual number of hours worked calculatedPayAmount = hourlyRate * standardNumberOfHours; } else { // Pay the hourly rate times the actual number of hours worked float numberOfHoursWorked = [[self valueForKey:@"hoursWorked"] floatValue]; calculatedPayAmount = hourlyRate * numberOfHoursWorked; if(numberOfHoursWorked > standardNumberOfHours) { // pay 50% extra for overtime float overtimePayAmount = 0.5f * hourlyRate * (numberOfHoursWorked - standardNumberOfHours); calculatedPayAmount = calculatedPayAmount + overtimePayAmount; } } return [NSNumber numberWithFloat:calculatedPayAmount]; } @end
The ability to access attributes and relationships by name is inherited from the NSManagedObject class.
and the attributes that are available are specified in XCode. The ability to make some attributes depend on others is part of Cocoa’s
Key Value Observing technology. The+(NSSet *)keyPathsForValuesAffectingPayAmountmethod of the MYEmployeeclass tells Cocoa that the payAmountattribute depends on the other MYEmployeeattributes, so any time any of the other attributes changes, the payAmountat-tribute needs to be recalculated.