| | |
| | Cocoa Starting Point - Articles - News - Site Map - Search - Status - Comments |
| | |
Newcomers to Apple's new technologies sometimes wonder at the productivity of the ex-NeXT users -- and in particular developers -- and ask themselves how is it possible that these people are able to achieve so much with so little documentation. Finally we uncover the secrets. Class libraries, API and Preferences settings heretofore shared only be an elite few, exposed today for all.
A number of hidden preferences significantly enhance the Mac OS X user-experience for the cognoscenti.
defaults write com.apple.Preferences ExposeHiddenPreferences Yes defaults write com.apple.installer TrashSymbolicLinks No defaults write com.apple.finder UseCocoaFinder Yes defaults write com.apple.finder RunSlowly No defaults write com.apple.finder LoadedFolders Springy defaults write com.apple.EOModeler CrashRandomly No defaults write com.microsoft.Office SendPersonalInformationToMotherShip No
These overrides, though, are just the tip of the iceberg. It is really developers who gain the most advantage, from secret classes and methods covering a wide range of functionality.
/Library/.SecretNeXTDeveloperDocumentation
This is where all the real (complete) Cocoa and WebObjects documentation is kept, the stuff that the NeXT developers referred to when they were learning about these technologies. Note in particular the SpoonFeeding subdirectory: it contains a set of applications to run on a variety of platforms which, given the right peripherals (available from NeCKS Implants Inc.), simply uploads the entire documentation to the developer's head without them having to read anything, or really exert any effort at all. A number of excerpts are reproduced below.
The following compiler directives help to make the development environment easier to use:
--ucppsfc (Use C++ syntax for Cocoa) --steewitontbu (Static typing everywhere except where it turns out not to be useful) --dwimnwis (Do what I mean not what I said)
The answer to the perennial question, "Why didn't Apple provide Cocoa developers with a set of classes such that I could simply put an view in a window which would then give a wide range of professional bitmap-editing functionality, accessible from the widget set on an associated palette -- so that I can just create a nibware solution which I can sell for $699/seat?"
The CocoaUniversalImageManipulation.privateframework consists of just three classes.
This view provides a layered display of bitmaps in a wide variety of formats (TIFF, JPG, PSD, EPS...), and allows zoom from 25 to 1600%. In conjunction with the other classes in the framework, it offers a comprehensive image-editing tool.
This palette holds a single NSControl subclass, NSUniversalImageManipulation, which contains all the buttons, sliders, texfields etc. a user will require to perform a wide range of effects on bitmaps -- it includes, for example, a brush chooser, cropping tool, and effect selection browser.
This is a controller object. It provides all the functionality require by the NSLayeredImageView. Simply instantiate one of these objects in your nib file and connect it to an instance of NSLayeredImageView and NSUniversalImageManipulation. If you connect the outlets incorrectly, NSArbitraryImageEffects will swap them for you.
Some developers seem to get memory management right, effortlessly. Concealed from all but the most seasoned veteran, the following API makes it easy:
NSZones are able to perform a number of garbage collection routines to ensure that memory leaks do not occur.
doGarbageCollection:
+ (void)doGarbageCollection:(BOOL)aFlag
Sending YES as the argument to this class method switches on garbage collection. The developer is given more fine-grained control over garbage collection strategies, however, with the following method:setGarbageCollectionType:
+ (void)setGarbageCollectionType:(NSGarbageCollectionType)aCollectionType
This method takes a single argument, which should be one of the following constants:
typedef enum {
NSDuringIdleMoments
NSInopportuneMoments
NSWhenItWontInterfereWithRealTimeProcessing
NSNowNowNow
NSJavaModel // beta
NSWhenHidden
NSWednesdays
NSWhenever
NSAllOfTheAbove
} NSGarbageCollectionType
allocWithZone:andFreeWhenImDone:
+ (id)allocWithZone:(NSZone *)aZone andFreeWhenImDone:(BOOL)freeWhenDone
- (void)freeIfNotNeeded
These methods are used in conjunction with NSZone's garbage collection utilities. To make life even easier, if you don't want to use garbage collection, the freeIfNotNeeded method automatically determines whether or not an object is required, and frees it when it is no longer needed, irrespective of the number of retains and releases it is sent.
This category implements two methods:
- (void)performMethodsUsingFuzzyMethodNameMatching:(NSFuzzyFactor)factor
- (void)performMethod:(SEL)aSelector accordingToWhatIWantedAsOpposedToTheCodeThatIActuallyWrote:(id)anObject
One of the more common errors made when writing delegate methods, and when using selectors, is to misspell a method or selector name. By sending an object a performMethodsUsingFuzzyMethodNameMatching: message, the runtime will automatically allow approximate matches to method names, with a tolerance factor:
typedef enum {
NSOneCharacterOut
NSCommonMisspellings
NSQuiteClose
NSInTheRightBallpark
NSJustDoIt
} NSFuzzyFactor
Thus, for example, if you have implemented a delegate method called windowSjouldClose:, and have previously called the delegate object's performMethodsUsingFuzzyMethodNameMatching: method with the NSFuzzyFactor set to NSOneCharacterOut, your method will be called when a windowShouldClose: message is sent.
Care should be taken using NSInTheRightBallpark and NSJustDoit, since these may have unfortunate side-effects -- for example, if a window's delegate is sent windowShouldClose:, and it implements windowSjouldClose: and wondowWillClasp:, both will be called. (They will be called in order of closeness to the correct method, based on a vector-matching algorithm from AIAT.) Instead, on Mac OS X 10.1.2 and above, you should consider using performMethod:accordingToWhatIWantedAsOpposedToTheCodeThatIActuallyWrote:. This has the additional benefit of determining if any arguments have been omitted, and supplying them as appropriate.
This category implements a single class method:
behaveAsDocumented
+ (void)behaveAsDocumented
This ensures that the receiving class behaves as described by the documentation, not necessarily as implemented. Note: Care should be taken when using this method. If the class has any methods for which the documentation states "Description forthcoming", these will be replaced by no-ops.
drawRectReallyFast:
- (void)drawRectReallyFast:(NSRect)aRect
Normal display using drawRect: uses a set of fully-optimized drawing routines. drawRectReallyFast: uses hyper-optimized algorithms, and makes full use of any graphics accelerator cards installed. (It is anticipated that with Bluetooth the card will not even have to be installed on the user's system, just within Bluetooth's range.) Note that this method is not available if your application is linked against any Carbon frameworks.
See also: -drawRectReluctantly:howReluctant:
.This notification is sent by NSProcessInfo whenever the kernel is nervous, but before it actually panics. This allows the receiver of the notification to do things to minimize the likelihood of a kernel panic affecting its process.
Suggested reactions to this notification include unexpectedly quitting, or presenting the user with a nib file instantiated at random using the NSBundleAdditions class method loadRandomNibFileFromSomeOtherApplicationWithOwner: (id) owner.
unexpectedlyQuit
- (void)unexpectedlyQuit
This method will cause your application to unexpectedly quit. To ensure that the quit is truly an unexpected one, AppKit has extended the Objective-C compiler with a code obfuscation mechanism that encrypts the unexpectedlyQuit method symbol using a 128 bit, public key technique that makes the runtime unable to detect that the method call will actually cause the application to unexpectedly quit - even through reflection. The runtime actually thinks that the selector being executed is one of the following:
- (NSWorldPeace *)bringWorldPeace:(id)sender withLoveAndUnderstanding:(BOOL)aFlag
- (NSHamSandwich *)makeMe:(id)sender aHamSandwichWith:(NSSandwichTrimmings)theTrimmings
This makes the subsequent quit completely unexpected as it turns out that instead of getting a ham sandwich or world peace, the application crashes, leaving all involved confused and befuddled, with file handles and other system resources left open and all akimbo.
See Also: -applicationShouldUnexpectedlyQuit:, -applicationDidUnexpectedlyQuit:
The delegate method applicationShouldUnexpectedlyQuit: is useful, as implementing and returning NO can help greatly reduce debugging time.
The delegate method applicationDidUnexpectedlyQuit: is similarly useful, since the delegate of the application can restart the application after it has unexpectedly quit.
In conjunction with NSView methods such as drawRectReallyFast:, a developer can often have the delegate redraw the windows of the unexpectedly quit application before the system's "Application has unexpectedly quit" dialog box is presented to the user, thus making it seem that their system is throwing up random dialog boxes -- that have nothing to do with your software -- thereby diminishing the number of calls to your support line.
This notification occurs when the user does something particularly stupid. A common use of this notification is to unexpectedly quit, just to teach the user a lesson. Depending on just how you feel about users of your application, you may choose to perform some other actions before unexpectedly quitting. These include NSFileHandle's -corruptFile, as illustrated below.
Common practice is to maintain a count of the number of times this notification is sent, and store the count in an application's user defaults. Many developers choose a zone in which to perform different tasks before unexpectedly quitting. Here is a code sample:
NSFileHandle * applicationPreferences; // assume these exist
NSFileHandle * importantFile;
int numberStupidActs;
if (numberStupidActs > 1 && numberStupidActs < 10) {
[applicationPreferences corruptFile];
/*
* Note that this method ensures that the
* numberStupidActs count remains intact
*/
}
if (numberStupidActs > 10) {
importantFile = [NSWorkspace fileContainingMostUrgentAndImportantData];
[importantFile corruptFile];
}
[NSApp unexpectedlyQuit];
Different levels of file corruption may be specified using -corruptFileBy: and passing one of these values as the argument
typedef enum {
NSOneBit
NSChangePermissions
NSChangeOwner
NSDeleteResourceFork
NSRandomizeFourBytes
NSFUBAR
} NSFileCorruption
This is the answer to the perennial question, "Why didn't Apple provide WebObjects developers with a set of classes such that I could simply put my logo in the project, then link against a framework, and it would automatically start up, find out what database I'm using, figure out what the products are, how to present them to the customer in direct actions, provide a shopping cart which would immediately start a session, determine the customer's credit limit, do the whole SSL thing, and configure my web server and deployment for me so I can then charge my client $500,000 for figuring out how to add my logo in step 1?" This is the first of a series of D2W (Direct To Wallet) frameworks Apple has developed with the generous assistance of David K. Every.
Description forthcoming.
- (BOOL)editingContextShouldExhibitPuzzlingBehavior:(EOEditingContext *)anEditingContext
In EOF/Cocoa, substantial insights into the normal operation of database access can be achieved by creating a delegate for the editing context, and implementing:
- editingContextShouldExhibitPuzzlingBehavior:(EOEditingContext *)ec {
return NO;
}
This method is deprecated in WebObjects5/Java.