Cocoa Programming for Mac OS X - Aaron Hillegass [102]
The sheet will end when the user clicks the OK button. Add the following method to TutorController.m:
- (IBAction)endSpeedSheet:(id)sender
{
// Return to normal event handling
[NSApp endSheet:speedSheet];
// Hide the sheet
[speedSheet orderOut:sender];
}
Build and run your application. Bring up the sheet, adjust the speed, and dismiss the sheet.
For the More Curious: contextInfo
The contextInfo parameter is a pointer to some data. You can supply this parameter when you start the sheet, and the delegate will get the pointer when you end the sheet. For example, here the developer has started a sheet and inserted a phone number for the context info:
NSString *phoneNumber = ...;
void *voidNumber = (__bridge_retained void *)phoneNumber;
[NSApp beginSheet:aWindow
modalForWindow:someOtherWindow
modalDelegate:self
didEndSelector:@selector(didEnd:returnCode:phone:)
contextInfo:voidPhone];
Later, in the didEnd:returnCode:phone: method, the phone number will be supplied as the third argument:
- (void)didEnd:(NSWindow *)sheet
returnCode:(NSInteger)returnCode
phone:(void *)voidPhone
{
NSString *phoneNumber = (__bridge_transfer NSString *)voidPhone;
NSLog(@"sheetDidEnd: Phone number = %@", phoneNumber);
}
Note also that the context info and the NSNotification's user info dictionary serve similar purposes.
You probably noticed that we had to do some rather unsightly casting to turn the NSString * type into a void *. The reason it that ARC requires hints from the developer so that it knows how to account for the object reference. In this case, __bridge_retained instructs ARC that it should retain phoneNumber, leaving it at +1 as beginSheet:modalForWindow:modalDelegate:didEndSelector: contextInfo: is called. In didEnd:returnCode:phone:, ownership of the phoneNumber reference is being transferred to the local phoneNumber variable by using the __bridge_transfer cast. The object is then released once the local variable phoneNumber goes out of scope.
Before ARC, it was not uncommon when using manual reference counting to see an object pointer cast to void *; the developer was responsible for ensuring that the object was retained and released appropriately. Expect to see APIs like this one revised in the future.
For the More Curious: Modal Windows
When a sheet is active, the user is prevented from sending events to the window to which it is attached. When an Alert panel is run, it is a modal window—that is, the user is prevented from sending events to any other window.
To make a window modal, use the following method of NSApp:
- (NSInteger)runModalForWindow:(NSWindow *)aWindow
This method will block, and only events destined for aWindow will be processed; clicking on the menu and other windows will do nothing. When you are ready to make the aWindow nonmodal, send this message to the NSApplication object:
- (void)stopModalWithCode:(NSInteger)returnCode
At that point, runModalForWindow: will end and return returnCode.
Chapter 26. Creating NSFormatters
A formatter takes a string and makes another object, typically so that the user can type something that is more than just a string. For example, the NSDateFormatter, when passed the string August 17, 1967, converts it into an NSDate object that represents the seventeenth day of August in the year 1967 (Figure 26.1).
Figure 26.1. NSDateFormatter
Also, a formatter can take an object and create a string for the user to see. For example, imagine a text field that has an NSDateFormatter. When the text field is sent setObjectValue: with an NSDate object, the date formatter will create a string that represents that date. The user will then see that string.
All formatters are subclasses of the NSFormatter class. Two of these subclasses come with Cocoa: NSDateFormatter and NSNumberFormatter. You used NSDateFormatter in Chapter 3 to format the lottery date and NSNumberFormatter in Chapter 8 to format the expected raise as a