Cocoa Programming for Mac OS X, 3rd Edition

If you are developing applications for the Mac, or are hoping to do so, this book is just the resource you need. This book is written for programmers who already know some C programming and something about objects.


Aaron Hillegass


655 Pages

56961 Reads

91 Downloads

English

PDF Format

4.65 MB

iOS App Development

Download PDF format


  • Aaron Hillegass   
  • 655 Pages   
  • 20 Feb 2015
  • Page - 1

    Cocoa® Programming for Mac® OS X, Third Edition by Aaron Hillegass Publisher: Addison Wesley Professional Pub Date: May 05, 2008 Print ISBN-10: 0-321-50361-9 Print ISBN-13: 978-0-321-50361-9 eText ISBN-10: 0-321-56273-9 eText ISBN-13: 978-0-321-56273-9 Pages: 464 Table of Contents | Index Overview The best-selling introduction to Cocoa, once again read more..

  • Page - 2

    Cocoa® Programming for Mac® OS X, Third Edition by Aaron Hillegass Publisher: Addison Wesley Professional Pub Date: May 05, 2008 Print ISBN-10: 0-321-50361-9 Print ISBN-13: 978-0-321-50361-9 eText ISBN-10: 0-321-56273-9 eText ISBN-13: 978-0-321-56273-9 Pages: 464 Table of Contents | Index Copyright Preface Acknowledgments Chapter 1. Cocoa: What Is It? A read more..

  • Page - 3

    Chapter 7. Key-Value Coding; Key-Value Observing Key-Value Coding Bindings Key-Value Observing Making Keys Observable Properties and Their Attributes For the More Curious: Key Paths For the More Curious: Key-Value Observing Chapter 8. NSArrayController Starting the RaiseMan Application Key-Value Coding and nil Add Sorting For the More Curious: read more..

  • Page - 4

    Chapter 15. Using Alert Panels Make the User Confirm the Deletion Challenge Chapter 16. Localization Localizing a Nib File String Tables For the More Curious: ibtool For the More Curious: Explicit Ordering of Tokens in Format Strings Chapter 17. Custom Views The View Hierarchy Getting a View to Draw Itself Drawing with NSBezierPath read more..

  • Page - 5

    Challenge Chapter 25. Sheets Adding a Sheet For the More Curious: contextInfo For the More Curious: Modal Windows Chapter 26. Creating NSFormatters A Basic Formatter The delegate of the NSControl Checking Partial Strings Formatters That Return Attributed Strings Chapter 27. Printing Dealing with Pagination For the More Curious: Am I read more..

  • Page - 6

    Copyright Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the publisher was aware of a trademark claim, the designations have been printed with initial capital letters or in all capitals. The author read more..

  • Page - 7

    Boston, MA 02116 Fax: (617) 671-3447 ISBN-13: 978-0321-50361-9 Text printed in the United States on recycled paper at Courier in Stoughton, Massachusetts. First printing, May 2008 Dedication For my sons, Walden and Otto read more..

  • Page - 8

    Preface If you are developing applications for the Mac, or are hoping to do so, this book is just the resource you need. Does it cover everything you will ever want to know about programming for the Mac? Of course it doesn't. But it does cover probably 80% of what you need to know. You can read more..

  • Page - 9

    Acknowledgments Creating this book required the efforts of many people. I want to thank them for their help. Their contributions have made this a better book than I could have ever written alone. First, I want to thank the students who took the Cocoa programming course at the Big Nerd Ranch. They helped read more..

  • Page - 10

    Chapter 1. Cocoa: What Is It? A Little History Tools Language Objects, Classes, Methods, and Messages Frameworks How to Read This Book Typographical Conventions Common Mistakes How to Learn A Little History The story of Cocoa starts with a delightful bit of history. Once upon a time, two guys named Steve started a company read more..

  • Page - 11

    events from the user and forwards them to the applications. The application then sends drawing commands back to the window server to update what the user sees. One of the nifty things about the NeXT window server is that the drawing code that goes to the window server is the same drawing code that read more..

  • Page - 12

    don't know what the intelligence community was using it for, but intelligence agencies bought thousands of copies of OpenStep. Because they were so useful, the OpenStep development tools were ported to Solaris and Windows NT, and the NeXTSTEP operating system was ported to most of the popular CPUs of the day: read more..

  • Page - 13

    Chapter 1. Cocoa: What Is It? A Little History Tools Language Objects, Classes, Methods, and Messages Frameworks How to Read This Book Typographical Conventions Common Mistakes How to Learn A Little History The story of Cocoa starts with a delightful bit of history. Once upon a time, two guys named Steve started a company read more..

  • Page - 14

    events from the user and forwards them to the applications. The application then sends drawing commands back to the window server to update what the user sees. One of the nifty things about the NeXT window server is that the drawing code that goes to the window server is the same drawing code that read more..

  • Page - 15

    don't know what the intelligence community was using it for, but intelligence agencies bought thousands of copies of OpenStep. Because they were so useful, the OpenStep development tools were ported to Solaris and Windows NT, and the NeXTSTEP operating system was ported to most of the popular CPUs of the day: read more..

  • Page - 16

    Tools You will love Cocoa but perhaps not immediately. First, you will learn the basics. Let's start with the tools that you will use. All the tools for Cocoa development come as part of the Mac OS X Developer Tools, and you get them for free with Mac OS X. Although the developer tools will add read more..

  • Page - 17

    Language This book uses Objective-C for all the examples. Objective-C is a simple and elegant extension to C, and mastering it will take about two hours if you already know C and an object-oriented language, such as Java or C++. It is possible to develop Cocoa applications in Ruby or Python. This book read more..

  • Page - 18

    Objects, Classes, Methods, and Messages All Cocoa programming is done using object-oriented techniques. This section very briefly reviews terms used in object-oriented programming. If you have not done any object-oriented programming before, I recommend that you read The Objective-C Language. The PDF file for the book is on read more..

  • Page - 19

    read more..

  • Page - 20

    Frameworks A framework is a collection of classes that are intended to be used together. In other words, the classes are compiled together into a reusable library of code. Any related resources are put into a directory with the library. The directory is renamed with the extension .framework . You can find read more..

  • Page - 21

    How to Read This Book When I sat down to write this book, I imagined that I was guiding a friend through activities that would help him understand Cocoa programming. This book acts as the guide through these activities. Often, I will ask you to do something and will explain the details or theory read more..

  • Page - 22

    Typographical Conventions To make the book easier to comprehend, I've used several typographical conventions. In Objective-C, class names are always capitalized. In this book, I've also made them appear in a monospaced boldface font. In Objective-C, method names start with a lowercase letter. Method names also will read more..

  • Page - 23

    Common Mistakes Having watched many, many people work through this material, I've seen the same mistakes made hundreds of times. I see two mistakes particularly often: capitalization mistakes and forgotten connections. Capitalization mistakes happen because C and Objective-C are case-sensitive languages —the compiler does not read more..

  • Page - 24

    How to Learn All sorts of people come to my class: the bright and the not so bright, the motivated and the lazy, the experienced and the novice. Inevitably, the people who get the most from the class share one characteristic: They remain focused on the topic at hand. The first trick to maintaining read more..

  • Page - 25

    Chapter 2. Let's Get Started Many books start by giving you a lot of philosophy. But doing so would be a waste of precious paper at this point. Instead, I am going to guide you through writing your first Cocoa application. Upon finishing, you will be excited and confused—and ready for the philosophy. Our read more..

  • Page - 26

    [View full size image] In this book, we discuss the following major types of projects: Application: A program that creates windows. Tool: A program that does not have a graphical user interface. Typically, a tool is a command line utility or a daemon that runs in the background. Bundle or framework: A read more..

  • Page - 27

    A project directory, with the skeleton of an application inside it, will be created for you. You will extend this skeleton into the source for a complete application and then compile the source into a working application. Looking at the new project in Xcode, you will see an outline view on the left read more..

  • Page - 28

    While the application is launching, you will see a bouncing icon in the dock. The name of your application will then appear in the menu. This means that your application is now active. The window for your application may be hidden by another window. If you do not see your window, choose Hide Others read more..

  • Page - 29

    It doesn't do much, but note that it is already a fully functional application. Printing even works. There is exactly one line of code in the application. Let's look at it now; quit RandomApp and return to Xcode. The main Function Select main.m by single-clicking on it. If you double-click on the filename, read more..

  • Page - 30

    You will almost never modify main.m in an application project. The default main() simply calls NSApplicationMain() , which in turn loads the user interface objects from a nib file. Nib files are created with Interface Builder. (Trivia: NIB stands for NeXT Interface Builder; NS stands for NeXTSTEP.) Once it has read more..

  • Page - 31

    Chapter 2. Let's Get Started Many books start by giving you a lot of philosophy. But doing so would be a waste of precious paper at this point. Instead, I am going to guide you through writing your first Cocoa application. Upon finishing, you will be excited and confused—and ready for the philosophy. Our read more..

  • Page - 32

    [View full size image] In this book, we discuss the following major types of projects: Application: A program that creates windows. Tool: A program that does not have a graphical user interface. Typically, a tool is a command line utility or a daemon that runs in the background. Bundle or framework: A read more..

  • Page - 33

    A project directory, with the skeleton of an application inside it, will be created for you. You will extend this skeleton into the source for a complete application and then compile the source into a working application. Looking at the new project in Xcode, you will see an outline view on the left read more..

  • Page - 34

    While the application is launching, you will see a bouncing icon in the dock. The name of your application will then appear in the menu. This means that your application is now active. The window for your application may be hidden by another window. If you do not see your window, choose Hide Others read more..

  • Page - 35

    It doesn't do much, but note that it is already a fully functional application. Printing even works. There is exactly one line of code in the application. Let's look at it now; quit RandomApp and return to Xcode. The main Function Select main.m by single-clicking on it. If you double-click on the filename, read more..

  • Page - 36

    You will almost never modify main.m in an application project. The default main() simply calls NSApplicationMain() , which in turn loads the user interface objects from a nib file. Nib files are created with Interface Builder. (Trivia: NIB stands for NeXT Interface Builder; NS stands for NeXTSTEP.) Once it has read more..

  • Page - 37

    In Interface Builder In the outline view under Resources is a nib file called MainMenu.nib . Double-click on it to open the nib in Interface Builder (Figure 2.7). Lots of windows will appear, so this is a good time to hide your other applications. In the Interface Builder menu, you will find Hide Others. read more..

  • Page - 38

    The Blank Window The blank window represents an NSWindow class instance that is inside your nib file. As you drop objects from the library onto the window, they will be added to the nib file. After you have created instances of these objects and edited their attributes, saving the nib file is like read more..

  • Page - 39

    Double-click the button to change its title to Seed random number generator using time. Copy and paste the button. Relabel the new button Generate random number. Drag out the Label text field (as shown in Figure 2.10) and drop it on the window. Figure 2.10. Dragging a Text Field [View full size image] read more..

  • Page - 40

    To make the text field as wide as the buttons, drag the left and right sides of the text field toward the sides of the window. (You may notice that blue lines appear when you are close to the edge of the window. These guides are intended to help you conform to Apple's GUI guidelines.) Make read more..

  • Page - 41

    Work-flow tip: In the morning, I open up the Inspector window and never close it again. The Doc Window In your nib file, some objects (e.g., buttons) are visible, and others (e.g., your custom controller objects) are invisible. The icons that represent the invisible objects appear in the doc window. In the read more..

  • Page - 42

    The files Foo.h and Foo.m will appear in your project. If they don't appear in the Classes group, drag them there (Figure 2.13). Figure 2.13. Put Foo.h and Foo.m in the Classes Group [View full size image] read more..

  • Page - 43

    In Foo.h , you will add instance variables and methods to your class. Instance variables that are pointers to other objects are called outlets. Methods that can be triggered by user interface objects are called actions. Edit Foo.h to look like this: #import <Cocoa/Cocoa.h> @interface Foo : NSObject { IBOutlet read more..

  • Page - 44

    In the Identity Inspector, set its class to Foo (Figure 2.15). (Your actions and outlets should appear in the Inspector. If they do not, check Foo.h . You have a mistake in it, or it hasn't been saved.) Figure 2.15. Setting the Class [View full size image] read more..

  • Page - 45

    Make Connections A lot of object-oriented programming has to do with which objects need to know about which other objects. Now you are going to introduce some objects to each other. Cocoa programmers would say, "We are now going to set the outlets of our objects." To introduce one object to another, read more..

  • Page - 46

    This step is all about pointers: You have just set the pointer textField in your Foo object to point to the text field. Now you will set the Seed button's target outlet to point to your instance of Foo . Furthermore, you want the button to trigger Foo 's seed: method. Control-drag from the button to read more..

  • Page - 47

    Similarly, you will set the Generate button's target instance variable to point to your instance of Foo and set its action to the generate: method. Control-drag from the button to Foo . Choose generate: in the Received Actions panel (Figure 2.19). Figure 2.19. Set the Target and Action of the Generate Button [View read more..

  • Page - 48

    Back in Xcode If this is the first time that you are seeing Objective-C code, you may be alarmed to discover that it looks quite different from C++ or Java code. The syntax may be different, but the underlying concepts are the same. In Java, for example, a class would be declared like this: import read more..

  • Page - 49

    Look at the Header File Click on Foo.h . Study it for a moment. It declares Foo to be a subclass of NSObject . Instance variables are declared inside braces. #import <Cocoa/Cocoa.h> @interface Foo : NSObject { IBOutlet NSTextField *textField; } - (IBAction)generate:(id)sender; - (IBAction)seed:(id)sender; @end #import is similar to the read more..

  • Page - 50

    Edit the Implementation File Now look at Foo.m . It contains the implementations of the methods. In C++ or Java, you might implement a method something like this: public void increment(Object sender) { count++; textField.setIntValue(count); } In English, you would say, "increment is a public instance method that takes read more..

  • Page - 51

    public, and all instance variables are protected. (In fact, there are visibility specifiers for instance variables, but they are rarely used. The default is protected, and that works nicely.) In Chapter 3, we will explore Objective-C in all its beauty. For now, simply copy the methods: #import "Foo.h" @implementation read more..

  • Page - 52

    Build and Run Your application is now finished. Click Build and Go. (If your app is already running, the toolbar item will be disabled; quit your app before trying to run it again.) If your code has an error, the compiler's message indicating a problem will appear at the view in the upper-right read more..

  • Page - 53

    Launch your application. Click the buttons and see the generated random numbers. Congratulations—you have a working Cocoa application. Did you see the log statement on the console? When things go badly, the Cocoa classes will log to the console, so you will want to keep an eye on the console while testing read more..

  • Page - 54

    awakeFromNib Note that your application is flawed: When the application starts, the word Label appears in the text field instead of anything interesting. Let's fix that problem. You will make the text field display the time and date that the application started. The nib file is a collection of objects that read more..

  • Page - 55

    runs (Figure 2.24). Figure 2.24. Completed Application In Cocoa, a lot of things (e.g., awakeFromNib ) get called automatically. Some of the confusion that you may experience as you read this book will come from trying to figure out which methods you have to call and which ones will get called for you read more..

  • Page - 56

    Documentation Before this chapter wraps up, you should know where to find the documentation, as it may prove handy if you get stuck while doing an exercise later in the book. The easiest way to get to the documentation is by choosing Documentation from Xcode's Help menu (Figure 2.25). Figure 2.25. The read more..

  • Page - 57

    What Have You Done? You have now gone through the steps involved in creating a simple Cocoa application. Create a new project. Lay out an interface. Create custom classes. Connect the interface to your custom class or classes. Add code to the custom classes. Compile. Test. Let's briefly discuss the chronology of an read more..

  • Page - 58

    When it receives an event from the keyboard and mouse, the window server puts the event data into the event queue for the appropriate application, as shown in Figure 2.27. The application object reads the event data from its queue and forwards it to a user interface object (like a button), and your read more..

  • Page - 59

    When the user chooses Quit from the menu, NSApp is sent the terminate: message. This ends the process, and all your objects are destroyed. Puzzled? Excited? Move on to the next chapter so we can fill in some blanks. read more..

  • Page - 60

    Chapter 3. Objective-C Once upon a time, a man named Brad Cox decided that it was time for the world to move toward a more modular programming style. C was a popular and powerful language. Smalltalk was an elegant untyped object-oriented language. Starting with C, Brad Cox added Smalltalk-like classes and read more..

  • Page - 61

    by sending the message alloc to the class NSMutableArray . The method init returns the newly initialized object. As a consequence, you will always nest the message sends like this: NSMutableArray *foo; foo = [[NSMutableArray alloc] init]; What about destroying the object when you no longer need it? Chapter 4 talks about this read more..

  • Page - 62

    Chapter 3. Objective-C Once upon a time, a man named Brad Cox decided that it was time for the world to move toward a more modular programming style. C was a popular and powerful language. Smalltalk was an elegant untyped object-oriented language. Starting with C, Brad Cox added Smalltalk-like classes and read more..

  • Page - 63

    by sending the message alloc to the class NSMutableArray . The method init returns the newly initialized object. As a consequence, you will always nest the message sends like this: NSMutableArray *foo; foo = [[NSMutableArray alloc] init]; What about destroying the object when you no longer need it? Chapter 4 talks about this read more..

  • Page - 64

    Using Existing Classes If it isn't running, start Xcode. Close any projects that you were working on. Under the File menu, choose New Project.... When the panel pops up, choose to create a Foundation Tool (Figure 3.1). Figure 3.1. Choose Project Type [View full size image] A Foundation Tool has no graphical read more..

  • Page - 65

    When the new project appears, select lottery.m under Source. Edit lottery.m to look like this: #import <Foundation/Foundation.h> int main (int argc, const char * argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSMutableArray *array; array = [[NSMutableArray alloc] init]; int i; for (i = 0; i < 10; i++) read more..

  • Page - 66

    #import <Foundation/Foundation.h> You are including the headers for all the classes in the Foundation framework. The headers are precompiled, so this approach is not as computationally intensive as it sounds. int main (int argc, const char *argv[]) The main function is declared just as it would be in any Unix C program. read more..

  • Page - 67

    Here you are printing the contents of the array to the console. NSLog is a function much like the C function printf() ; it takes a format string and a comma-separated list of variables to be substituted into the format string. When displaying the string, NSLog prefixes the generated string with the name read more..

  • Page - 68

    strings and constant NSString s, you must put @ before the opening quote of a constant NSString : // C string char *foo; // NSString NSString *bar; foo = "this is a C string"; bar = @"this is an NSString"; You will use mostly NSString in Cocoa programming. Wherever a string is needed, the classes in the frameworks expect read more..

  • Page - 69

    Figure 3.3. Completed Execution [View full size image] (If your console doesn't appear, use the Run -> Console menu item.) Sending Messages to nil In most object-oriented languages, your program will crash if you send a message to nil . In applications written in those languages, you will see many checks for read more..

  • Page - 70

    In the preceding example, what is bar set to? Zero. If bar were a pointer, it would be set to nil (zero for pointers). For other types, the value is less predictable. NSObject, NSArray, NSMutableArray, and NSString You have now used these standard Cocoa objects: NSObject , NSMutableArray , and NSString . (All read more..

  • Page - 71

    message is generally coupled with an alloc message in the same line of code: TheClass *newObject = [[TheClass alloc] init]; - (NSString *)description Returns an NSString that describes the receiver. The debugger's print object command ("po") invokes this method. A good description method will often make debugging easier. Also, read more..

  • Page - 72

    and [x isEqual:y] The first expression compares the two pointers. The second expression compares the characters in the strings. Note, however, that if x and y are instances of a class that has not overridden NSObject 's isEqual: method, the two expressions are equivalent. NSArray An NSArray is a list of pointers to read more..

  • Page - 73

    whether an object is present in the array by sending an isEqual: message to each of the array's objects and passing anObject as the parameter. -(unsigned)indexOfObject:(id)anObject Searches the receiver for anObject and returns the lowest index whose corresponding array value is equal to anObject . Objects are considered equal read more..

  • Page - 74

    determined on the basis of anObject 's response to the isEqual: message. - (void)removeObjectAtIndex:(unsigned)index Removes the object at index and moves all elements beyond index down one slot to fill the gap. You will get an error if index is beyond the end of the array. As mentioned earlier, you cannot add nil to read more..

  • Page - 75

    Returns a string object made by appending aString to the receiver. The following code snippet, for example, would produce the string "Error: unable to read file." NSString *errorTag = @"Error: "; NSString *errorString = @"unable to read file."; NSString *errorMessage; errorMessage = [errorTag stringByAppendingString:errorString]; "Inherits read more..

  • Page - 76

    Creating Your Own Classes Where I live, the state government has decided that the uneducated have entirely too much money: You can play the lottery every week here. Let's imagine that a lottery entry has two numbers between 1 and 100, inclusive. You will write a program that will make up lottery read more..

  • Page - 77

    Note that you are also causing LotteryEntry.h to be created. LotteryEntry.h Edit the LotteryEntry.h file to look like this: #import <Foundation/Foundation.h> @interface LotteryEntry : NSObject { NSCalendarDate *entryDate; int firstNumber; int secondNumber; } - (void)prepareRandomNumbers; - (void)setEntryDate:(NSCalendarDate *)date; - (NSCalendarDate read more..

  • Page - 78

    firstNumber and secondNumber are both int s. You have declared five methods in the new class: prepareRandomNumbers will set firstNumber and secondNumber to random values between 1 and 100. This method takes no arguments and returns nothing. entryDate and setEntryDate: will allow other objects to read and set the variable read more..

  • Page - 79

    Here is the play-by-play for each method: prepareRandomNumbers uses the standard random function to generate a pseudorandom number. You use the mod operator (%) and add 1 to get the number in the range 1–100. setEntryDate: sets the pointer entryDate to a new value. entryDate , firstNumber , and secondNumber return the read more..

  • Page - 80

    for (LotteryEntry *entryToPrint in array) { // Display its contents NSLog(@"%@", entryToPrint); } [pool drain]; return 0; } Note the second for loop. Here you are using Objective-C's mechanism for enumerating over the members of a collection. This program will read more..

  • Page - 81

    Hmm. Not quite what we hoped for. After all, the program is supposed to reveal the dates and the numbers you should play on those dates, and you can't see either. (You are seeing the default description method as defined in NSObject .) Next, you will make the LotteryEntry objects display themselves in a more read more..

  • Page - 82

    NSCalendarDate Before moving on to any new ideas, let's examine NSCalendarDate in some depth. Instances of NSCalendarDate have a date and time, a time zone, and a format string. NSCalendarDate inherits from NSDate . Instances of NSCalendarDate are basically immutable: You can't change the day or time of a calendar read more..

  • Page - 83

    now = [NSCalendarDate calendarDate]; + (id)dateWithYear:(int)year month:(unsigned)month day:(unsigned)day hour:(unsigned)hour minute:(unsigned)minute second:(unsigned)second timeZone:(NSTimeZone *)aTimeZone This class method read more..

  • Page - 84

    This method returns a number that indicates the day of the month (1 through 31) of the receiver. - (int)dayOfWeek This method returns a number that indicates the day of the week (0 through 6) of the receiver, where 0 indicates Sunday. - (int)dayOfYear This method returns a number that indicates the day of read more..

  • Page - 85

    %a Abbreviated weekday name ("Fri") %A Full weekday name ("Friday") %w Weekday as a decimal number (0–6), where Sunday is 0 %d Day of the month as a decimal number (01–31) %e Same as %d but does not print the leading 0 %j Day of the year as a decimal number (001–366) %H Hour based on a read more..

  • Page - 86

    newEntry = [[LotteryEntry alloc] init]; [newEntry prepareRandomNumbers]; You are creating a new instance and then immediately calling prepareRandomNumbers to initialize firstNumber and secondNumber . This is something that should be handled by the initializer, so you are going to override the init method in your LotteryEntry class. In the read more..

  • Page - 87

    This version will always work and is considered the most correct form; however, none of the classes that you will subclass in this book require these checks. For simplicity, this book will sometimes leave out the check. Initializers with Arguments Look at the same place in lottery.m . It should now look like read more..

  • Page - 88

    To protect Rex from his own ignorance, you will override init to call your initializer with a default date: - (id)init { return [self initWithEntryDate:[NSCalendarDate calendarDate]]; } Add this method to your LotteryEntry.m file. Note that initWithEntryDate: still does all the work. Because a class can have multiple read more..

  • Page - 89

    The Debugger The Free Software Foundation developed the compiler (gcc) and the debugger (gdb) that come with Apple's developer tools. Apple has made significant improvements to both over the years. This section discusses the processes of setting breakpoints, invoking the debugger, and browsing the values of variables. While read more..

  • Page - 90

    In the list on the left, you can see the frames on the stack. Because our breakpoint is in main() , the stack is not very deep. In the outline view on the right, you can see the variables and their values. Note that the variable i is currently 0. The buttons above the stack information are read more..

  • Page - 91

    Exceptions are raised when something goes very wrong. To make the debugger stop whenever an exception is thrown, you will want to add a symbolic breakpoint. Any breakpoint for which you don't have a line number is a symbolic breakpoint. In this case, you want a breakpoint on the function objc_exception_throw . read more..

  • Page - 92

    You can test this automatic breakpoint by asking for an index that is not in an array. Immediately after the array is created, ask it what its first object is: array = [[NSMutableArray alloc] init]; NSLog(@"first item = %@", [array objectAtIndex:0]); Rebuild and restart the program. It should stop when the exception read more..

  • Page - 93

    Now, if you build and run the Release configuration, you'll see that your assertion is not getting checked. (Before going on, fix your assertion: It should ensure that dates are not nil .) NSAssert() works only inside Objective-C methods. If you need to check an assertion in a C function, use NSCAssert() . That's read more..

  • Page - 94

    What Have You Done? You have written a simple program in Objective-C, including a main() function that created several objects. Some of these objects were instances of LotteryEntry , a class that you created. The program logged some information to the console. At this point, you have a fairly complete understanding read more..

  • Page - 95

    For the More Curious: How Does Messaging Work? As mentioned earlier, an object is like a C struct. NSObject declares an instance variable called isa . Because NSObject is the root of the entire class-inheritance tree, every object has an isa pointer to the class structure that created the object (Figure 3.15). read more..

  • Page - 96

    At compile time, the compiler looks up the selectors wherever it sees a message send. Thus, [myObject addObject:yourObject]; becomes (assuming that the selector for addObject: is 12) objc_msgSend(myObject, 12, yourObject); Here, objc_msgSend() looks at myObject 's isa pointer to get to its class structure and looks for the method read more..

  • Page - 97

    Challenge Change the format string on the calendar date objects in your LotteryEntry class. read more..

  • Page - 98

    Chapter 4. Memory Management Let's say that there are two instances of Person and that each has a favoriteColor , a pointer to a color object. If two people have the same favoriteColor , the objects will have pointers to the same color object. As the people age, their favorite color might change. read more..

  • Page - 99

    Why not always use the garbage collector? If you use the garbage collector, your application will not run on any version of Mac OS before 10.5. Also, the garbage collector requires some CPU time to scan through the objects, looking for garbage. This can sometimes result in poorer performance. In an read more..

  • Page - 100

    The other two choices will enable the garbage collector. You must recompile before the change takes effect. (The difference between Supported and Required is interesting only if you are creating a framework or plug-in that will be used in another application.) The code in this book is dual-mode code. Dual-mode read more..

  • Page - 101

    In the future, you may decide, "This retain-count stuff is for the birds. I'm going to use the garbage collector for everything." I wouldn't blame you. For now, however, learn about the retain-count mechanism. When you study old code or anything that uses lower-level frameworks (such as CoreFoundation), you will read more..

  • Page - 102

    Chapter 4. Memory Management Let's say that there are two instances of Person and that each has a favoriteColor , a pointer to a color object. If two people have the same favoriteColor , the objects will have pointers to the same color object. As the people age, their favorite color might change. read more..

  • Page - 103

    Why not always use the garbage collector? If you use the garbage collector, your application will not run on any version of Mac OS before 10.5. Also, the garbage collector requires some CPU time to scan through the objects, looking for garbage. This can sometimes result in poorer performance. In an read more..

  • Page - 104

    The other two choices will enable the garbage collector. You must recompile before the change takes effect. (The difference between Supported and Required is interesting only if you are creating a framework or plug-in that will be used in another application.) The code in this book is dual-mode code. Dual-mode read more..

  • Page - 105

    In the future, you may decide, "This retain-count stuff is for the birds. I'm going to use the garbage collector for everything." I wouldn't blame you. For now, however, learn about the retain-count mechanism. When you study old code or anything that uses lower-level frameworks (such as CoreFoundation), you will read more..

  • Page - 106

    Living with the Garbage Collector Your application will have an instance of NSGarbageCollector if and only if it is using the garbage collector. Add a line near the end of lottery.m : [pool drain]; NSLog(@"GC = %@", [NSGarbageCollector defaultCollector]); return 0; Build and run the tool. Are you using the garbage read more..

  • Page - 107

    Living with Retain Counts Let's assume for the rest of this chapter that you need to support users of 10.4. Thus, you are going to forego the convenience of the garbage collector and use the retain- count mechanism. Every object has a retain count. The retain count is an integer. When an object is read more..

  • Page - 108

    // Done with 'now' [now release]; now = nil; for (LotteryEntry *entryToPrint in array) { NSLog(@"%@", entryToPrint); } // Done with 'array' [array release]; array = nil; [pool drain]; NSLog(@"GC = %@", [NSGarbageCollector defaultCollector]); return 0; } Now the read more..

  • Page - 109

    - (void)dealloc { NSLog(@"deallocing %@", self); [entryDate release]; [super dealloc]; } In the initWithEntryDate: method, we did not retain the entryDate . Add the necessary retain: - (id)initWithEntryDate:(NSCalendarDate *)theDate { if (![super init]) return nil; entryDate = [theDate retain]; read more..

  • Page - 110

    There is, however, still a memory leak. Creating Autoreleased Objects You created a description method that looks like this: - (NSString *)description { NSString *result; result = [[NSString alloc] initWithFormat:@"%@ = %d and %d", [entryDate descriptionWithCalendarFormat:@"%b %d %Y"], read more..

  • Page - 111

    - (NSString *)description { NSString *result; result = [[NSString alloc] initWithFormat:@"%@ = %d and %d", [entryDate descriptionWithCalendarFormat:@"%b %d %Y"], firstNumber, secondNumber]; [result autorelease]; return result; } Rules Concerning Release Objects created by alloc , new read more..

  • Page - 112

    created: 13 by uppercaseString and 13 by stringWithFormat: ; the initial constant string is a special case and doesn't count. One of the resulting strings is returned and may be retained by the object that asked for it. The other 25 strings are deallocated automatically at the end of the event loop. (Note read more..

  • Page - 113

    The first idiom is: Retain, then Release: - (void)setFoo:(NSCalendarDate *)x { [x retain]; [foo release]; foo = x; } Here, it is important to retain before releasing. Suppose that you reverse the order. If x and foo are both pointers to the same object that happens to have a retain count of 1, read more..

  • Page - 114

    foo = [x retain]; } } Here, you are not setting the variable unless a different value is passed in. Trade-off: An extra if statement is necessary. The final idiom is: Autorelease Old Value: - (void)setFoo:(NSCalendarDate *)x { [foo autorelease]; foo = [x retain]; } Here, you autorelease the old value. read more..

  • Page - 115

    } OO purists would argue that this is the most-correct implementation of the description method. Change setEntryDate: in LotteryEntry.m to correctly retain the new value and release the old: - (void)setEntryDate:(NSCalendarDate *)date { [date retain]; [entryDate release]; entryDate = date; } read more..

  • Page - 116

    What Have You Done? You have now written a simple program in Objective-C, including a main() function that created several objects. Some of these objects were instances of LotteryEntry , a class that you created. The program logged some information to the console. At this point, you have a fairly complete read more..

  • Page - 117

    Chapter 5. Target/Action Once upon a time, there was a company called Taligent, which was created by IBM and Apple to develop a set of tools and libraries like Cocoa. About the time Taligent reached the peak of its mindshare, I met one of its engineers at a trade show. I asked him to create a read more..

  • Page - 118

    The action methods take one argument: the sender. This enables the receiver to know which control sent the message. Often, you will call back to the sender to get more information. For example, a check box will send its action message when it is turned on and when it is turned off. After getting read more..

  • Page - 119

    At the top of the class hierachy is NSObject . All the classes inherit from NSObject , and this is where they get the basic methods: retain , release , dealloc , and init . NSResponder is a subclass of NSObject . Responders have the ability to handle events with such methods as mouseDown: and keyDown: . NSView read more..

  • Page - 120

    NSButton Instances of NSButton can have several different appearances: oval, square, check box. They can also have different behavior when clicked: toggle (like a check box) or momentarily on (like most other buttons). Buttons can have icons and sounds associated with them. Figure 5.4 shows the Attributes Inspector for an read more..

  • Page - 121

    a check box programmatically. Set the state to NSOnState to check the check box and to NSOffState to uncheck it. NSSlider Instances of NSSlider can be vertical or horizontal. They can send the action to the target continuously while being changed, or they can wait to send the action until the user releases read more..

  • Page - 122

    shows the Attributes Inspector panel for an NSTextField in Interface Builder. Figure 5.6. Text Field Inspector [View full size image] Text fields have a placeholder string. When the text field is empty, the placeholder string is displayed in gray. NSSecureTextField is a subclass of NSTextField and is used for such read more..

  • Page - 123

    methods use the description method. For example, you might use a text field to allow the user to type in a date. As the programmer, you don't want the string that the user typed in; you want an instance of NSCalendarDate . By attaching an NSDateFormatter , you ensure that the text field's objectValue method read more..

  • Page - 124

    Chapter 5. Target/Action Once upon a time, there was a company called Taligent, which was created by IBM and Apple to develop a set of tools and libraries like Cocoa. About the time Taligent reached the peak of its mindshare, I met one of its engineers at a trade show. I asked him to create a read more..

  • Page - 125

    The action methods take one argument: the sender. This enables the receiver to know which control sent the message. Often, you will call back to the sender to get more information. For example, a check box will send its action message when it is turned on and when it is turned off. After getting read more..

  • Page - 126

    At the top of the class hierachy is NSObject . All the classes inherit from NSObject , and this is where they get the basic methods: retain , release , dealloc , and init . NSResponder is a subclass of NSObject . Responders have the ability to handle events with such methods as mouseDown: and keyDown: . NSView read more..

  • Page - 127

    NSButton Instances of NSButton can have several different appearances: oval, square, check box. They can also have different behavior when clicked: toggle (like a check box) or momentarily on (like most other buttons). Buttons can have icons and sounds associated with them. Figure 5.4 shows the Attributes Inspector for an read more..

  • Page - 128

    a check box programmatically. Set the state to NSOnState to check the check box and to NSOffState to uncheck it. NSSlider Instances of NSSlider can be vertical or horizontal. They can send the action to the target continuously while being changed, or they can wait to send the action until the user releases read more..

  • Page - 129

    shows the Attributes Inspector panel for an NSTextField in Interface Builder. Figure 5.6. Text Field Inspector [View full size image] Text fields have a placeholder string. When the text field is empty, the placeholder string is displayed in gray. NSSecureTextField is a subclass of NSTextField and is used for such read more..

  • Page - 130

    methods use the description method. For example, you might use a text field to allow the user to type in a date. As the programmer, you don't want the string that the user typed in; you want an instance of NSCalendarDate . By attaching an NSDateFormatter , you ensure that the text field's objectValue method read more..

  • Page - 131

    Start the SpeakLine Example As a simple example of using controls, you will build an application that enables users to type in a line of text and hear it spoken by the Mac OS X speech synthesizer. The app will look like Figure 5.8 when you are done with this chapter. Figure 5.8. Completed read more..

  • Page - 132

    Lay Out the Nib File Double-click on MainMenu.nib to open it in Interface Builder. From the Library window, drag out a text field and two buttons. Double-click on the text field to change the text to read "Peter Piper picked a peck of pickled peppers" (or some other text that will amuse you when read more..

  • Page - 133

    Making Connections in Interface Builder Making a connection is analogous to introducing people. You say, "Mrs. Robinson, this is Dr. Pepper." If it is important that Dr. Pepper also know Mrs. Robinson, you would continue, "Dr. Pepper, this is Mrs. Robinson." With objects in Interface Builder, you will drag read more..

  • Page - 134

    At this point, you have set all but one of the connections shown in the object diagram in Figure 5.9. The missing connection, speechSynth , will be done programmatically—not in Interface Builder. NSWindow's initialFirstResponder Outlet When your application runs and the new window appears, users should not have to read more..

  • Page - 135

    Implementing the AppController Class Now you need to write some code, so return to Xcode and select the AppController.h file. Add an instance variable named speechSynth of type NSSpeechSynthesizer : #import <Cocoa/Cocoa.h> @interface AppController : NSObject { IBOutlet NSTextField *textField; NSSpeechSynthesizer *speechSynth; } - read more..

  • Page - 136

    - (IBAction)stopIt:(id)sender { NSLog(@"stopping"); [speechSynth stopSpeaking]; } @end Your application is done. Build it and run it. You should be able to start the recitation of the text in the text field and stop it in midsentence. Final note: A menu item (an instance of NSMenuItem ) read more..

  • Page - 137

    For the More Curious: Setting the Target Programmatically Note that the action of a control is a selector. NSControl includes the following method: - (void)setAction:(SEL)aSelector But how would you get a selector? The Objective-C compiler directive @selector will tell the compiler to look up the selector for you. For read more..

  • Page - 138

    Challenge This exercise is an important challenge that you should do before moving on. Although it is easy to follow my instructions, you will eventually want to create your own applications. Here is where you can start to develop some independence. Feel free to refer back to the earlier examples for read more..

  • Page - 139

    When the user types in a string and clicks the button, the message text will display the input string and the number of characters it has (Figure 5.14). It is important to know how to use the Cocoa classes in your application. For this exercise, you should recognize that the NSTextField class has read more..

  • Page - 140

    Debugging Hints Now that you are writing code, not simply copying it from the book, you are ready for some debugging hints. Always watch the console. If a Cocoa object throws an exception, it will be logged to the console, and the event loop will be restarted. If you aren't watching the console, you read more..

  • Page - 141

    No objects are being freed, it still crashes. Check the type of your arguments. For example, this is a great way to crash your app: int x = 5; NSLog(@"x is %@", x); Interface Builder won't let me make a connection. A .h file is messed up. A missing semicolon? A variable declared to be NSTabView instead read more..

  • Page - 142

    Chapter 6. Helper Objects Once upon a time (before Baywatch), there was a man with no name. Knight Industries decided that if this man were given guns and wheels and booster rockets, he would be the perfect crime-fighting tool. First, they thought, "Let's subclass him and override everything we need to add read more..

  • Page - 143

    - (void )speechSynthesizer:(NSSpeechSynthesizer *)sender willSpeakPhoneme:(short)phonemeOpcode; The Apple programmer who wrote NSSpeechSynthesizer put these hooks in. He is Michael Knight. You are KITT. Of the three messages that the speech synthesizer sends to its delegate, you care about only the first one: read more..

  • Page - 144

    In AppController.m , set the delegate outlet of the speech synthesizer: - (id)init { [super init]; NSLog(@"init"); speechSynth = [[NSSpeechSynthesizer alloc] initWithVoice:nil]; [speechSynth setDelegate:self]; return self; } Next, add the delegate method. For now, simply log a message: - read more..

  • Page - 145

    The Stop button should be disabled when it first appears on screen, so select the button and disable it in the Attributes Inspector, as shown in Figure 6.3. Save the nib file. Figure 6.3. Disable Stop Button [View full size image] In Xcode, edit the AppController.m file to properly enable and disable the read more..

  • Page - 146

    [speechSynth startSpeakingString:string]; NSLog(@"Have started to say: %@", string); [stopButton setEnabled:YES]; [startButton setEnabled:NO]; } In speechSynthesizer:didFinishSpeaking: , reset the buttons to their initial states: - (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)complete { NSLog(@"complete = read more..

  • Page - 147

    Chapter 6. Helper Objects Once upon a time (before Baywatch), there was a man with no name. Knight Industries decided that if this man were given guns and wheels and booster rockets, he would be the perfect crime-fighting tool. First, they thought, "Let's subclass him and override everything we need to add read more..

  • Page - 148

    - (void )speechSynthesizer:(NSSpeechSynthesizer *)sender willSpeakPhoneme:(short)phonemeOpcode; The Apple programmer who wrote NSSpeechSynthesizer put these hooks in. He is Michael Knight. You are KITT. Of the three messages that the speech synthesizer sends to its delegate, you care about only the first one: read more..

  • Page - 149

    In AppController.m , set the delegate outlet of the speech synthesizer: - (id)init { [super init]; NSLog(@"init"); speechSynth = [[NSSpeechSynthesizer alloc] initWithVoice:nil]; [speechSynth setDelegate:self]; return self; } Next, add the delegate method. For now, simply log a message: - read more..

  • Page - 150

    The Stop button should be disabled when it first appears on screen, so select the button and disable it in the Attributes Inspector, as shown in Figure 6.3. Save the nib file. Figure 6.3. Disable Stop Button [View full size image] In Xcode, edit the AppController.m file to properly enable and disable the read more..

  • Page - 151

    [speechSynth startSpeakingString:string]; NSLog(@"Have started to say: %@", string); [stopButton setEnabled:YES]; [startButton setEnabled:NO]; } In speechSynthesizer:didFinishSpeaking: , reset the buttons to their initial states: - (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)complete { NSLog(@"complete = read more..

  • Page - 152

    The NSTableView and Its dataSource Next, you will add a table view that will enable the user to change the voice, as shown in Figure 6.4. Figure 6.4. Completed Application [View full size image] A table view is used for displaying columns of data. An NSTableView has a helper object called a dataSource , as read more..

  • Page - 153

    If you have editable cells in your table view, you will need to implement one more method: - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex; The dataSource takes the input that the user put into row rowIndex of aTableColumn . You read more..

  • Page - 154

    First, add the declaration of two instance variables to AppController.h : #import <Cocoa/Cocoa.h> @interface AppController : NSObject { IBOutlet NSTextField *textField; IBOutlet NSButton *startButton; IBOutlet NSButton *stopButton; IBOutlet NSTableView *tableView; NSArray *voiceList; NSSpeechSynthesizer *speechSynth; } Save the file. read more..

  • Page - 155

    Lay Out the User Interface Open MainMenu.nib . You will edit the window to look like Figure 6.7. Figure 6.7. Completed Interface [View full size image] Drag an NSTableView onto the window (Figure 6.8). Figure 6.8. Drop a Table View on the Window [View full size image] Select the table view so that you can read more..

  • Page - 156

    column is inside the table view. Experiment. You will know that you have selected the table view when the title of the Inspector window is Table View Attributes. In the Inspector, make the table view have only one column. Also, disable column selection. Figure 6.9. Inspect the Table View [View full size read more..

  • Page - 157

    Make Connections First, you will set the dataSource outlet of the NSTableView to be your instance of AppController . Select the NSTableView . Control-click in the table view to bring up the connections panel. Drag from the dataSource outlet to the AppController . If you do not see dataSource in the Inspector, you read more..

  • Page - 158

    Save the nib file and close it. read more..

  • Page - 159

    Edit AppController.m Implement the data source methods in AppController.m : - (int)numberOfRowsInTableView:(NSTableView *)tv { return [voiceList count]; } - (id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row { NSString *v = [voiceList read more..

  • Page - 160

    } The speech synthesizer will not allow you to change the voice while it is speaking, so you should prevent the user from changing the selected row. The table view should be enabled and disabled with startButton : - (IBAction)sayIt:(id)sender { NSString *string = [textField stringValue]; if ([string length] == 0) { read more..

  • Page - 161

    problem is to copy and paste the declaration of the method from the documentation or the header file. Forgetting to set the delegate outlet. You will not get any error or warning from the compiler if you make this error. Object Delegates Delegation is a design pattern that you will see used many places read more..

  • Page - 162

    For the More Curious: How Delegates Work The delegate doesn't have to implement all the methods, but if the object does implement a delegate method, it will get called. In many languages, this sort of thing would be impossible. How is it achieved in Objective-C? NSObject has the the following method: - read more..

  • Page - 163

    - (BOOL)respondsToSelector:(SEL)aSelector { NSString *methodName = NSStringFromSelector(aSelector); NSLog(@"respondsToSelector:%@", methodName); return [super respondsToSelector:aSelector]; } You might want to try adding this method to AppController.m now. read more..

  • Page - 164

    Challenge: Make a Delegate Create a new application with one window. Make an object that is a Delegate of the window. As the user resizes the window, make sure that it always remains twice as tall as it is wide. Here is the signature of the Delegate method you will implement: - read more..

  • Page - 165

    Challenge: Make a Data Source Make a to-do list application. The user will type tasks into the text field. When the user clicks the Add button, you will add the string to a mutable array, and the new task will appear at the end of the list (Figure 6.12). Figure 6.12. Diagram of Challenge [View read more..

  • Page - 166

    Chapter 7. Key-Value Coding; Key-Value Observing Key-value coding (KVC) is a mechanism that allows you to set and get the value of a variable by its name. The name is simply a string, but we refer to that name as a key. So, for example, imagine that you have a class called Student that has an read more..

  • Page - 167

    Save the nib file. Back in Xcode, open AppController.h , and add an instance variable called fido of type int : @interface AppController : NSObject { int fido; } @end In AppController.m , you are going to create an init method that sets and reads fido by using key-value coding. This is a bit silly because it read more..

  • Page - 168

    return self; } The key-value coding mechanism will automatically convert the NSNumber to an int before using it to set the value of fido . Build and run the application, but don't expect much. When the blank window appears, "fido = 5" will be logged to the console. If you have accessor methods read more..

  • Page - 169

    Chapter 7. Key-Value Coding; Key-Value Observing Key-value coding (KVC) is a mechanism that allows you to set and get the value of a variable by its name. The name is simply a string, but we refer to that name as a key. So, for example, imagine that you have a class called Student that has an read more..

  • Page - 170

    Save the nib file. Back in Xcode, open AppController.h , and add an instance variable called fido of type int : @interface AppController : NSObject { int fido; } @end In AppController.m , you are going to create an init method that sets and reads fido by using key-value coding. This is a bit silly because it read more..

  • Page - 171

    return self; } The key-value coding mechanism will automatically convert the NSNumber to an int before using it to set the value of fido . Build and run the application, but don't expect much. When the blank window appears, "fido = 5" will be logged to the console. If you have accessor methods read more..

  • Page - 172

    Bindings Many graphical objects in Cocoa have bindings. When you bind a key, such as fido , to an attribute of the graphical object (like its value or its font color), the view will automatically keep those in sync. You are going to add a slider, bind its value to fido , and see how it uses read more..

  • Page - 173

    Build and run the application. Note that the slider uses valueForKey: to get its initial value, which triggers your fido method. As you move the slider, it calls setValue:forKey: to update the fido variable, which triggers your setFido: method. read more..

  • Page - 174

    Key-Value Observing What happens if fido is changed by something other than the slider? How would the slider know that it has a new value? When the slider is created, it tells the AppController that it is observing its fido key. Whenever the value of fido is changed by the accessor methods or by read more..

  • Page - 175

    Making Keys Observable In the previous section, I mentioned that when you use accessors or key-value coding to change the value for a key, the observers are automatically notified of the change. What happens if you change the variable directly? Open AppController.h and declare a new action method: - read more..

  • Page - 176

    You would hope that when the button is clicked, the slider would move and the text field would update itself. Sadly, neither happens. Try building and running the application. If you are going to change the variable directly, you will need to explicitly trigger the notification of the observers. Change the read more..

  • Page - 177

    Or, you could use the accessor method to change fido : - (IBAction)incrementFido:(id)sender { [self setFido:[self fido] + 1]; } Type this version in. Then build and run it. Figure 7.6 is an object diagram of what you have done. Note the use of half-arrows to represent bindings. Figure 7.6. Object Diagram read more..

  • Page - 178

    Properties and Their Attributes As you can guess, we spend a lot of time calling accessor methods. In Objective-C 2.0, Apple gives programmers the option of calling accessors by using dot notation. If you have a pointer rover to an object with a getter method rex , you can call it like this: read more..

  • Page - 179

    The attributes can include readwrite (the default) or readonly . A property marked readonly gets no setter method. To describe how the setter method should work, the attributes can also include one of the following: assign , retain , copy . Let's look at each in turn: assign (the default) makes a simple assignment read more..

  • Page - 180

    For the More Curious: Key Paths Objects are often arranged in a network. For example, a person might have a spouse who has a scooter that has a model name (Figure 7.7). Figure 7.7. Objects Are a Directed Graph To get the model name of the selected person's spouse's scooter, you can use a key read more..

  • Page - 181

    toObject:employeeController withKeyPath:@"arrangedObjects.@avg.expectedRaise" options:nil]; Of course, it is usually easier to create a binding in Interface Builder. Use the unbind: method to remove the binding: [textField unbind:@"value"]; read more..

  • Page - 182

    For the More Curious: Key-Value Observing How did the text field become an observer of the fido key in the AppController object? When it wakes up from being in the nib, the text field adds itself as an observer. If you wanted to become an observer of this key, your line of code might look read more..

  • Page - 183

    Chapter 8. NSArrayController In the object-oriented programming community, a very common design pattern is Model-View-Controller. In this design pattern, each class you write should fall into exactly one of the following groups: Model: Model classes describe your data. For example, if you write banking systems, you would probably read more..

  • Page - 184

    Starting the RaiseMan Application Over the next few chapters, you will create a full-featured application for keeping track of employees and the raise that each person will receive this year. As this book progresses, you will add file saving, undo, user preferences, and printing capabilities. After this chapter, the read more..

  • Page - 185

    Note that the class MyDocument has already been created for you. MyDocument is a subclass of NSDocument . The document object is responsible for reading and writing files. In this exercise, we will use an NSArrayController and bindings to construct our simple interface, so we won't be adding any code to read more..

  • Page - 186

    Edit the Person.h file to declare two properties: #import <Foundation/Foundation.h> @interface Person : NSObject { NSString *personName; float expectedRaise; } @property (readwrite, copy) NSString *personName; @property (readwrite) float expectedRaise; @end Now edit Person.m to implement these methods and to override init and dealloc : #import read more..

  • Page - 187

    } - (void)dealloc { [personName release]; [super dealloc]; } @synthesize personName; @synthesize expectedRaise; @end Note that Person is a model class—it has no information about the user interface. As such, the class doesn't need to know about all the Cocoa frameworks. Thus, instead of importing Cocoa/Cocoa.h , we are read more..

  • Page - 188

    In Interface Builder In Xcode, double-click MyDocument.nib to open it in Interface Builder. Delete the text field Your document contents here. Drop a table view and two buttons on the window. Relabel and arrange them as shown in Figure 8.5. Figure 8.5. Document Window [View full size image] From Cocoa->Objects & read more..

  • Page - 189

    Bind the Content Array of the array controller to the employees array of File's Owner, which is the instance of MyDocument (Figure 8.7). Figure 8.7. Bind Content Array [View full size image] read more..

  • Page - 190

    The first column of the table view will display each employee's name. Click and double- click the column to select it. (At no time in this book will you ever bind to the scroll view, table view, or the cell; doing so is a common mistake, so keep an eye on the title of the Inspector read more..

  • Page - 191

    Figure 8.9 (page 130). Figure 8.9. Adding a Number Formatter [View full size image] Reselect the second column. In the Bindings Inspector, set value to display the expectedRaise of the arrangedObjects of the NSArrayController , as shown in Figure 8.10. Figure 8.10. Bind Second Column to expectedRaise of arrangedObjects [View read more..

  • Page - 192

    [View full size image] The user will also want to delete the selected employees by pressing the Delete key on his or her keyboard. Select the button; in the Attributes Inspector, set the keyboard equivalent to the Delete key (Figure 8.12). Figure 8.12. Make Delete Key Trigger Delete Button [View full size read more..

  • Page - 193

    Chapter 8. NSArrayController In the object-oriented programming community, a very common design pattern is Model-View-Controller. In this design pattern, each class you write should fall into exactly one of the following groups: Model: Model classes describe your data. For example, if you write banking systems, you would probably read more..

  • Page - 194

    Starting the RaiseMan Application Over the next few chapters, you will create a full-featured application for keeping track of employees and the raise that each person will receive this year. As this book progresses, you will add file saving, undo, user preferences, and printing capabilities. After this chapter, the read more..

  • Page - 195

    Note that the class MyDocument has already been created for you. MyDocument is a subclass of NSDocument . The document object is responsible for reading and writing files. In this exercise, we will use an NSArrayController and bindings to construct our simple interface, so we won't be adding any code to read more..

  • Page - 196

    Edit the Person.h file to declare two properties: #import <Foundation/Foundation.h> @interface Person : NSObject { NSString *personName; float expectedRaise; } @property (readwrite, copy) NSString *personName; @property (readwrite) float expectedRaise; @end Now edit Person.m to implement these methods and to override init and dealloc : #import read more..

  • Page - 197

    } - (void)dealloc { [personName release]; [super dealloc]; } @synthesize personName; @synthesize expectedRaise; @end Note that Person is a model class—it has no information about the user interface. As such, the class doesn't need to know about all the Cocoa frameworks. Thus, instead of importing Cocoa/Cocoa.h , we are read more..

  • Page - 198

    In Interface Builder In Xcode, double-click MyDocument.nib to open it in Interface Builder. Delete the text field Your document contents here. Drop a table view and two buttons on the window. Relabel and arrange them as shown in Figure 8.5. Figure 8.5. Document Window [View full size image] From Cocoa->Objects & read more..

  • Page - 199

    Bind the Content Array of the array controller to the employees array of File's Owner, which is the instance of MyDocument (Figure 8.7). Figure 8.7. Bind Content Array [View full size image] read more..

  • Page - 200

    The first column of the table view will display each employee's name. Click and double- click the column to select it. (At no time in this book will you ever bind to the scroll view, table view, or the cell; doing so is a common mistake, so keep an eye on the title of the Inspector read more..

  • Page - 201

    Figure 8.9 (page 130). Figure 8.9. Adding a Number Formatter [View full size image] Reselect the second column. In the Bindings Inspector, set value to display the expectedRaise of the arrangedObjects of the NSArrayController , as shown in Figure 8.10. Figure 8.10. Bind Second Column to expectedRaise of arrangedObjects [View read more..

  • Page - 202

    [View full size image] The user will also want to delete the selected employees by pressing the Delete key on his or her keyboard. Select the button; in the Attributes Inspector, set the keyboard equivalent to the Delete key (Figure 8.12). Figure 8.12. Make Delete Key Trigger Delete Button [View full size read more..

  • Page - 203

    Key-Value Coding and nil Note that our example contains very little code. You described what should be displayed in each of the columns in Interface Builder, but there is no code that calls the accessor methods of your Person class. How does this work? Key-value coding. Key-value coding makes generic, reusable read more..

  • Page - 204

    Add Sorting While the application is running, click the column headers and note that sorting works but does so badly. In particular, it is using the strongly case-sensitive compare: method to order the names. For example, "Z" will come before "a". Let's change the method used for sorting. Open read more..

  • Page - 205

    For the More Curious: Sorting without NSArrayController In Chapter 6, you created a table view by implementing the dataSource methods explicitly. You might have wondered then how you could implement this sorting behavior in your own application. The information that you added to the columns of the table is packed into read more..

  • Page - 206

    Challenge 1 Make the application sort people based on the number of characters in their names. You can complete this challenge using only Interface Builder; the trick is to use a key path. (Hint: Strings have a length method.) read more..

  • Page - 207

    Challenge 2 In the first edition of this book, readers created the RaiseMan application without using NSArrayController or the bindings mechanism. (These features were added in Mac OS X 10.3.) To do so, readers used the ideas from previous chapters. The challenge, then, is to rewrite the RaiseMan application read more..

  • Page - 208

    // Is the selection empty? if ([rows count] == 0) { NSBeep(); return; } [employees removeObjectsAtIndexes:rows]; [tableView reloadData]; } - (IBAction)createEmployee:(id)sender { Person *newEmployee = [[Person alloc] init]; [employees addObject:newEmployee]; [newEmployee release]; [tableView read more..

  • Page - 209

    Chapter 9. NSUndoManager Using NSUndoManager , you can add undo capabilities to your applications in a very elegant manner. As objects are added, edited, and deleted, the undo manager keeps track of all messages that must be sent to undo these changes. As you invoke the undo mechanism, the undo manager keeps track read more..

  • Page - 210

    Chapter 9. NSUndoManager Using NSUndoManager , you can add undo capabilities to your applications in a very elegant manner. As objects are added, edited, and deleted, the undo manager keeps track of all messages that must be sent to undo these changes. As you invoke the undo mechanism, the undo manager keeps track read more..

  • Page - 211

    How the NSUndoManager Works Suppose that the user opens a new RaiseMan document and makes three edits: Inserts a new record Changes the name from "New Employee" to "Rex Fido" Changes the raise from 0 to 20 As each edit is performed, your controller will add an invocation that would undo read more..

  • Page - 212

    The undo manager is actually quite clever: When the user is doing edits, the undo invocations go onto the undo stack. When the user is undoing edits, the undo invocations go onto the redo stack. When the user is redoing edits, the undo invocations go onto the undo stack. These tasks are handled read more..

  • Page - 213

    makeItColder is invoked as a result of an undo, this inverse will go onto the redo stack. The invocations on either stack are grouped. By default, all invocations added to a stack during a single event are grouped together. Thus, if one user action causes changes in several objects, all the changes are read more..

  • Page - 214

    Adding Undo to RaiseMan Let's give the user the ability to undo the effects of clicking the Add New Employee and Delete buttons, as well as the ability to undo the changes made to Person objects in the table. The necessary code will go into your MyDocument class. When designing a class, I tend to read more..

  • Page - 215

    There are several cases, so here is a list: id arrayProxy = [playlist mutableArrayValueForKey:@"songs"]; int x = [arrayProxy count]; // is the same as int x = [playlist countOfSongs]; // if countOfSongs exists id y = [arrayProxy objectAtIndex:5] // is the same as id y = [playlist objectInSongsAtIndex:5]; // if the method exists [arrayProxy insertObject:p atIndex:4] read more..

  • Page - 216

    id setProxy = [teacher mutableSetValueForKey:@"students"]; int x = [setProxy count]; // is the same as int x = [teacher countOfStudents]; // if countOfStudents exists [setProxy addObject:newStudent]; // is the same as [teacher addStudentsObject:newStudent]; // if the method exists [setProxy removeObject:expelledStudent]; // is the same as [teacher removeStudentsObject:expelledStudent]; // if read more..

  • Page - 217

    // Add the inverse of this operation to the undo stack NSUndoManager *undo = [self undoManager]; [[undo prepareWithInvocationTarget:self] insertObject:p inEmployeesAtIndex:index]; if (![undo isUndoing]) { [undo setActionName:@"Delete Person"]; read more..

  • Page - 218

    Key-Value Observing In Chapter 7, we discussed key-value coding. To review: Key-value coding is a way to read and change a variable's value by using its name. Key-value observing allows you to be informed when these sorts of changes occur. To enable undo capabilities for edits, you will want your document object read more..

  • Page - 219

    Undo for Edits The first step is to register your document object to observe changes to its Person objects. Add the following methods to MyDocument.m : - (void)startObservingPerson:(Person *)person { [person addObserver:self forKeyPath:@"personName" read more..

  • Page - 220

    [self stopObservingPerson:p]; [employees removeObjectAtIndex:index]; } - (void)setEmployees:(NSMutableArray *)a { if (a == employees) return; for (Person *person in employees) { [self stopObservingPerson:person]; } [a retain]; [employees release]; employees = a; for (Person *person in read more..

  • Page - 221

    toValue:oldValue]; [undo setActionName:@"Edit"]; } That should do it. Once you build and run your application, undo and redo should work flawlessly. Note that as you make changes to the document, a dot appears in read more..

  • Page - 222

    Begin Editing on Insert Your app is coming along nicely, but your users will complain, "Why do I have to double-click to start editing after an insert? It is obvious that I am going to immediately change the name of the new person. Can't you start the editing as part of the insert?" read more..

  • Page - 223

    In MyDocument.m , add the createEmployee: method: Code View: - (IBAction)createEmployee:(id)sender { NSWindow *w = [tableView window]; // Try to end any editing that is taking place BOOL editingEnded = [w makeFirstResponder:w]; if (!editingEnded) { NSLog(@"Unable to end editing"); return; } read more..

  • Page - 224

    // Begin the edit in the first column [tableView editColumn:0 row:row withEvent:nil select:YES]; } I don't really expect you to understand every line of that code now, but browse through the method read more..

  • Page - 225

    For the More Curious: Windows and the Undo Manager A view can add edits to the undo manager. NSTextView , for example, can put onto the undo manager each edit that a person makes to the text. This can be enabled in Interface Builder (Figure 9.7). Figure 9.7. NSTextView Inspector [View full size image] read more..

  • Page - 226

    Chapter 10. Archiving While an object-oriented program is running, a complex graph of objects is being created. It is often necessary to represent this graph of objects as a stream of bytes, a process called archiving (Figure 10.1). This stream of bytes can then be sent across a network connection or read more..

  • Page - 227

    Java construct called an interface. That is, a protocol is a list of method declarations. When you create a class that implements a protocol, it promises to implement all the methods declared in the protocol. NSCoder and NSCoding One protocol is NSCoding . If your class implements NSCoding , it promises to read more..

  • Page - 228

    [coder encodeObject:personName forKey:@"personName"]; [coder encodeFloat:expectedRaise forKey:@"expectedRaise"]; } If you looked at the documentation for NSString , you would see that it implements the NSCoding protocol. Thus, the personName knows how to encode itself. All the commonly used AppKit and Foundation classes read more..

  • Page - 229

    because NSObject doesn't have one. If Person 's superclass had implemented the NSCoding protocol, the method would have looked like this: - (id)initWithCoder:(NSCoder *)coder { [super initWithCoder:coder]; personName = [[coder decodeObjectForKey:@"personName"] retain]; expectedRaise = [coder decodeFloatForKey:@"expectedRaise"]; return self; } You read more..

  • Page - 230

    Chapter 10. Archiving While an object-oriented program is running, a complex graph of objects is being created. It is often necessary to represent this graph of objects as a stream of bytes, a process called archiving (Figure 10.1). This stream of bytes can then be sent across a network connection or read more..

  • Page - 231

    Java construct called an interface. That is, a protocol is a list of method declarations. When you create a class that implements a protocol, it promises to implement all the methods declared in the protocol. NSCoder and NSCoding One protocol is NSCoding . If your class implements NSCoding , it promises to read more..

  • Page - 232

    [coder encodeObject:personName forKey:@"personName"]; [coder encodeFloat:expectedRaise forKey:@"expectedRaise"]; } If you looked at the documentation for NSString , you would see that it implements the NSCoding protocol. Thus, the personName knows how to encode itself. All the commonly used AppKit and Foundation classes read more..

  • Page - 233

    because NSObject doesn't have one. If Person 's superclass had implemented the NSCoding protocol, the method would have looked like this: - (id)initWithCoder:(NSCoder *)coder { [super initWithCoder:coder]; personName = [[coder decodeObjectForKey:@"personName"] retain]; expectedRaise = [coder decodeFloatForKey:@"expectedRaise"]; return self; } You read more..

  • Page - 234

    The Document Architecture Applications that deal with multiple documents have a lot in common. All can create new documents, open existing documents, save or print open documents, and remind the user to save edited documents when he or she tries to close a window or quit the application. Apple supplies three read more..

  • Page - 235

    The document controller has an array of document objects—one for each open document. NSDocument The document objects are instances of a subclass of NSDocument . In your RaiseMan application, for example, the document objects are instances of MyDocument . For many applications, you can simply extend NSDocument to do what read more..

  • Page - 236

    went wrong. - (NSFileWrapper *)fileWrapperOfType:(NSString *)aType error:(NSError *)e Your document object returns the model as an NSFileWrapper object. It will be written to the filesystem in the location chosen by the user. - (BOOL)writeToURL:(NSURL *)absoluteURL read more..

  • Page - 237

    file that the user is trying to open. Return YES if you successfully create a model from the data. If you return NO , the user will get an Alert panel that should explain why it was unable to parse the file. The contents of the Alert panel will be determined by the NSError object you give it. read more..

  • Page - 238

    You want to put the user interface controller logic and model controller logic into separate classes. You want to create a window without a corresponding NSDocument object. You will do this in Chapter 12. read more..

  • Page - 239

    Saving and NSKeyedArchiver Now that you have taught your object to encode and decode itself, you will use it to add saving and loading to your application. When it is time to save your people to a file, your MyDocument class will be asked to create an instance of NSData . Once your object has read more..

  • Page - 240

    Loading and NSKeyedUnarchiver Now you will add the ability to load files to your application. Once again, NSDocument has taken care of most of the details for you. To do the unarchiving, you will use NSKeyedUnarchiver , which has the following handy method: + (id)unarchiveObjectWithData:(NSData *)data In your MyDocument class, read more..

  • Page - 241

    Note that your document is asked which nib file to load when a document is opened or created. This method also needs no changing: - (NSString *)windowNibName { return @"MyDocument"; } The window is automatically marked as edited when you make an edit, because you have properly enabled the undo mechanism. read more..

  • Page - 242

    Setting the Extension and Icon for the File Type RaiseMan files will have the extension .rsmn , and .rsmn files will have an icon. First, find an .icns file and copy it into your project. A fine icon is found at /Developer/Examples/AppKit/CompositeLab/BBall.icns . Drag it from the Finder into the Groups and read more..

  • Page - 243

    To set the document-type information, select the RaiseMan target in Xcode, and choose Get Info from the File menu. Under the Properties tab, set the identifier for your application to be com.bignerdranch.RaiseMan. Set the Icon File to be BBall. In the document-types table view, set the name to be RaiseMan read more..

  • Page - 244

    Build and run your application. You should be able to save data to a file and read it in again. In Finder, the BBall.icns icon will be used as the icon for your .rsmn files. An application is a directory containing the nib files, images, sounds, and executable code for the application. In Terminal, read more..

  • Page - 245

    For the More Curious: Preventing Infinite Loops The astute reader may be wondering: "If object A causes object B to be encoded, and object B causes object C to be encoded, and then object C causes object A to be encoded again, couldn't it just go around and around in an infinite loop?" read more..

  • Page - 246

    read more..

  • Page - 247

    For the More Curious: Creating a Protocol Creating your own protocol is very simple. Here is a protocol with two methods. It would typically be in a file called Foo.h . @protocol Foo - (void)fido:(int)x; - (float)rex; @end With Objective-C 2.0, @optional was added to the protocol grammar. Now you can indicate which methods read more..

  • Page - 248

    For the More Curious: Document-Based Applications without Undo The NSUndoManager for your application knows when unsaved edits have occurred. Also, the window is automatically marked as edited. But what if you've written an application and you are not registering your changes with the undo manager? NSDocument keeps track read more..

  • Page - 249

    Universal Type Identifiers One of the enduring problems in working with computers is embodied in the question: "What does this data represent?" On the Mac, this question gets asked in several places: when a file is opened from the Finder, when data is copied off the pasteboard, and when a file is read more..

  • Page - 250

    You can find the entire list of system-defined UTIs in Apple's documentation. read more..

  • Page - 251

    Chapter 11. Basic Core Data At this point, you've implemented an application that keeps track of an array of objects, takes care of undo, and handles saving and loading from a file. As you can imagine, there are an awful lot of applications like the one you just wrote. Apple decided to make this read more..

  • Page - 252

    In the new project, under Models, open MyDocument.xcdatamodel . At the bottom of the Entity table view, click the + button to create a new entity. Name the entity Car. With the Car entity selected, choose Add Attribute in the pop-up at the bottom of the Properties table view. Add six attributes and give read more..

  • Page - 253

    Figure 11.2 shows what it looks like in the modeler. Figure 11.2. Completed Model [View full size image] Although we could put lots of other things in the model, that is enough for this exercise. read more..

  • Page - 254

    Chapter 11. Basic Core Data At this point, you've implemented an application that keeps track of an array of objects, takes care of undo, and handles saving and loading from a file. As you can imagine, there are an awful lot of applications like the one you just wrote. Apple decided to make this read more..

  • Page - 255

    In the new project, under Models, open MyDocument.xcdatamodel . At the bottom of the Entity table view, click the + button to create a new entity. Name the entity Car. With the Car entity selected, choose Add Attribute in the pop-up at the bottom of the Properties table view. Add six attributes and give read more..

  • Page - 256

    Figure 11.2 shows what it looks like in the modeler. Figure 11.2. Completed Model [View full size image] Although we could put lots of other things in the model, that is enough for this exercise. read more..

  • Page - 257

    Interface Open MyDocument.nib . In the window, delete the text field Your document contents here. Drag an array controller into the doc window. The array controller will be using the document object's NSManagedObjectContext to fetch and store data. Use the Bindings Inspector to bind the array controller's managedObjectContext read more..

  • Page - 258

    Create and Configure Views Drag out a table view (from Cocoa->Views & Cells->Data Views). In the Attributes Inspector, give it three columns. Name the columns Make/Model, Price, and Special. Drop a number formatter (from Cocoa->Views & Cells -> Formatters) on the Price column. Select the formatter (represented by read more..

  • Page - 259

    The third column will be populated by check boxes, so drop a check box cell (from Cocoa- >Views & Cells->Cells) on the third column. Select the cell, and clear its title (Figure 11.6). Figure 11.6. Drop Check Box Cell [View full size image] Below the table view, drop on the window an read more..

  • Page - 260

    Make the NSImageView editable by using the Attributes Inspector. Select the date picker, the image view, the two labels, and the level indicator. Using the Layout -> Embed Objects In -> Box menu item, wrap them in a box (Figure 11.8). Figure 11.8. Embed in a Box [View full size image] read more..

  • Page - 261

    Connections and Bindings Now, you are going to do a bunch of bindings. I will walk you through it step by step; Figure 11.9 is a diagram of the bindings that you are going to create between your views and the array controller. Figure 11.9. Summary of Bindings [View full size image] read more..

  • Page - 262

    A reminder: You will never bind to a scroll view, a table view, or a cell in this book. You will, however, bind to table view columns, which have cells and are inside table views, which are, in turn, inside scroll views. Bind the value of each column (Cars is the NSArrayController ): Binding Bind read more..

  • Page - 263

    Make the Delete button trigger the remove: method of the array controller. Bind the value of the controls to the selection of the array controller: Binding Bind to Controller Key Key Path value of date picker Cars selection datePurchased enabled of Delete button Cars canRemove value of level indicator Cars selection condition Bind the read more..

  • Page - 264

    Bind the Title With Pattern of the box to Cars . Set the Controller Key to selection . Set the Model Key Path to makeModel . Set the Display Pattern to Details for %{title1}@ . Set the No Selection Placeholder to <No selection>. S et the Null Placeholder <no Make/Model>. S ee Figure 11.12. Figure 11.12. Box read more..

  • Page - 265

    Let's also make the text of the first two columns appear in boldface if the car is on special. Bind the Font Bold binding to Cars 's arrangedObjects onSpecial (Figure 11.13). Figure 11.13. Specials Appear in Boldface [View full size image] You are done. Build and run the application. Saving and loading should read more..

  • Page - 266

    How Core Data Works Although you have written no code, many objects will be created to make this work. Figure 11.14 is a diagram of some of them. Figure 11.14. Overview of Core Data [View full size image] So, the NSPersistentDocument reads in the model you created and uses it to create an instance of read more..

  • Page - 267

    would be nice if the datePurchased attribute were set to the current date. One good way to do this is to subclass NSArrayController and override its newObject method. In Xcode, create a new file of type Objective-C Class. Name the class CarArrayController . In CarArrayController.h , make it a subclass of read more..

  • Page - 268

    Build and run your application. When new cars are added, their datePurchased attribute should be initialized to the current date. read more..

  • Page - 269

    Chapter 12. Nib Files and NSWindowController In RaiseMan, you are already using two nib files: MainMenu.nib and MyDocument.nib . MainMenu.nib is automatically loaded by NSApplication when the application first launches. MyDocument.nib is automatically loaded each time an instance of MyDocument is created. In this section, you will read more..

  • Page - 270

    Chapter 12. Nib Files and NSWindowController In RaiseMan, you are already using two nib files: MainMenu.nib and MyDocument.nib . MainMenu.nib is automatically loaded by NSApplication when the application first launches. MyDocument.nib is automatically loaded each time an instance of MyDocument is created. In this section, you will read more..

  • Page - 271

    Adding a Panel to the Application The Preferences panel that you are going to add will not do anything except appear for now. In the next chapter, however, you will learn about user defaults and will make the Preferences panel do something. The Preferences panel will be in its own nib file. You will read more..

  • Page - 272

    [View full size image] Open the RaiseMan project and create a new Objective-C class named AppController . Edit AppController.h to look like this: #import <Cocoa/Cocoa.h> @class PreferenceController; @interface AppController : NSObject { PreferenceController *preferenceController; } - (IBAction)showPreferencePanel:(id)sender; @end Note the Objective-C syntax: @class read more..

  • Page - 273

    #import "PreferenceController.h" This statement would import the header, and the compiler would learn that PreferenceController was a class. Because the import command requires the compiler to parse more files, @class will often result in faster builds. Note that you must always import the superclass's header file, read more..

  • Page - 274

    Close the nib file. AppController.m Now you need to write the code for AppController . Make the contents of AppController.m look like this: #import "AppController.h" #import "PreferenceController.h" @implementation AppController - (IBAction)showPreferencePanel:(id)sender { // Is preferenceController nil? if (!preferenceController) { read more..

  • Page - 275

    [View full size image] Edit PreferenceController.h to look like this: #import <Cocoa/Cocoa.h> @interface PreferenceController : NSWindowController { IBOutlet NSColorWell *colorWell; IBOutlet NSButton *checkbox; } - (IBAction)changeBackgroundColor:(id)sender; - (IBAction)changeNewEmptyDoc:(id)sender; @end Preferences.nib In Xcode, create a new, empty nib file named read more..

  • Page - 276

    You will see that there are XIB and NIB files. They serve the same function, but NIB files are a binary format and XIB files are XML. XIB files are compiled into NIB files when you build your app. Why would anyone use XIB files? They work nicely with version-control systems, such as Subversion. read more..

  • Page - 277

    objects that already exist need to establish some connection to the objects read from the nib file. File's Owner provides this connection. File's Owner is a placeholder in a nib file for an object that will already exist when the nib file is loaded. An object loading a nib file will provide the owner read more..

  • Page - 278

    Set the target of the color well to be File's Owner (your PreferenceController ), and set the action to be changeBackgroundColor: (Figure 12.10). Figure 12.10. Set the target of the Color Well [View full size image] Also, make your PreferenceController be the target of the check box, and set the action to be read more..

  • Page - 279

    Control-click File's Owner to get the connection window. Connect the window outlet to the panel (Figure 12.12). Figure 12.12. Set the window Outlet of File's Owner Open the Attributes Inspector for the panel. Disable resizing. Change the title on the window to Preferences. Save the nib file. See Figure 12.13. Figure read more..

  • Page - 280

    [View full size image] PreferenceController.m In Xcode, edit the PreferenceController.m to look like this: Code View: #import "PreferenceController.h" @implementation PreferenceController - (id)init { if (![super initWithWindowNibName:@"Preferences"]) return nil; return self; } - (void)windowDidLoad { NSLog(@"Nib file is read more..

  • Page - 281

    Note that you set the name of the nib file to be loaded in the init method. This nib file will be loaded automatically when it is needed. The instance of PreferenceController will be substituted for File's Owner in the nib file. After the nib file is loaded, the PreferenceController will read more..

  • Page - 282

    For the More Curious: NSBundle A bundle is a directory of resources that may be used by an application. Resources include such things as images, sounds, compiled code, and nib files. (Users often use the word plug-in instead of bundle.) The class NSBundle is a very elegant way of dealing with bundles. Your read more..

  • Page - 283

    As you see, NSBundle is handy in many ways. In this section, the NSBundle was responsible (behind the scenes) for loading the nib file. If you wanted to load a nib file without an NSWindowController , you could do it like this: BOOL successful = [NSBundle loadNibNamed:@"About" owner:someObject]; Note that you would read more..

  • Page - 284

    Challenge Create a nib file with a custom About panel. Add an outlet to AppController to point to the new window. Also add a showAboutPanel: method. Load the nib by using NSBundle , and make AppController File's Owner. read more..

  • Page - 285

    Chapter 13. User Defaults Many applications have Preferences panels that allow the user to choose a preferred appearance or behavior. The user's choices go into the user defaults database in the user's home directory. Note that only the choices that vary from the factory defaults are saved in the user defaults read more..

  • Page - 286

    A string can be a key only once in a dictionary. When you want to know the value to which a key is bound, you will use the objectForKey: method: anObject = [myDictionary objectForKey:@"foo"]; If the key is not in the dictionary, this method will return nil . NSMutableDictionary is a subclass of read more..

  • Page - 287

    Enumerators are also known as iterators, or enumerations. You can use them to step through all the members of a collection. The preceding method returns an enumerator that steps through all the keys in the dictionary. Here is how you would use one to list all the key-value pairs in a dictionary: NSEnumerator read more..

  • Page - 288

    Chapter 13. User Defaults Many applications have Preferences panels that allow the user to choose a preferred appearance or behavior. The user's choices go into the user defaults database in the user's home directory. Note that only the choices that vary from the factory defaults are saved in the user defaults read more..

  • Page - 289

    A string can be a key only once in a dictionary. When you want to know the value to which a key is bound, you will use the objectForKey: method: anObject = [myDictionary objectForKey:@"foo"]; If the key is not in the dictionary, this method will return nil . NSMutableDictionary is a subclass of read more..

  • Page - 290

    Enumerators are also known as iterators, or enumerations. You can use them to step through all the members of a collection. The preceding method returns an enumerator that steps through all the keys in the dictionary. Here is how you would use one to list all the key-value pairs in a dictionary: NSEnumerator read more..

  • Page - 291

    NSUserDefaults Every application comes with a set of defaults from the factory. When a user edits his or her defaults, only the differences between the user's wishes and the factory defaults are stored in the user's defaults database. Thus, every time the application starts up, you need to remind it of read more..

  • Page - 292

    - (void)registerDefaults:(NSDictionary *)dictionary Registers the factory defaults for the application. - (void)setBool:(BOOL)value forKey:(NSString *)defaultName - (void)setFloat:(float)value forKey:(NSString *)defaultName - (void)setInteger:(int)value forKey:(NSString *)defaultName - (void)setObject:(id)value forKey:(NSString *)defaultName Methods for changing and saving a user's wishes. - read more..

  • Page - 293

    Setting the Identifier for the Application What is the property list file in ~/Library/Preferences created for this application called? By default, it uses the identifier of the application that created it. You set this identifier in Chapter 10 to be com.bignerdranch.RaiseMan , so the filename will be read more..

  • Page - 294

    Creating Keys for the Names of the Defaults You will be registering, reading, and setting defaults in several classes in your application. To make sure that you always use the same name, you should declare those strings in a single file and then simply #import that file into any file in which you use the read more..

  • Page - 295

    Registering Defaults Each class is sent the message initialize before any other message. To ensure that your defaults are registered early, you will override initialize in AppController.m : + (void)initialize { // Create a dictionary NSMutableDictionary *defaultValues = [NSMutableDictionary dictionary]; // Archive the color object read more..

  • Page - 296

    Letting the User Edit the Defaults Next, you will alter the PreferenceController class so that the Preferences panel will cause the defaults database to get updated. Declare the following methods in PreferenceController.h : - (NSColor *)tableBgColor; - (BOOL)emptyDoc; Make your PreferenceController.m file look like this: Code View: #import read more..

  • Page - 297

    - (IBAction)changeNewEmptyDoc:(id)sender { int state = [checkbox state]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setBool:state forKey:BNREmptyDocKey]; } @end In the windowDidLoad method, you are reading the defaults and making the color well and check box reflect the current settings. In read more..

  • Page - 298

    Using the Defaults Now you are going to use the defaults. First, you will make your AppController become a delegate of the NSApplication object and suppress the creation of an untitled document, depending on the user defaults. Then, in MyDocument , you will set the background color of the table view from the read more..

  • Page - 299

    Figure 13.5. Select the delegate Outlet Setting the Background Color on the Table View After the nib file for a new document window has been successfully unarchived, your MyDocument object is sent the message windowControllerDidLoadNib: . At that moment, you can update the background color of the table view. You should read more..

  • Page - 300

    For the More Curious: NSUserDefaultsController Sometimes, you will want to bind to a value from the NSUserDefaults object. An NSUserDefaultsController class makes this possible. All the nibs in your application will use a single shared instance of NSUserDefaultsController . For example, if you wanted to use bindings, instead of read more..

  • Page - 301

    For the More Curious: Reading and Writing Defaults from the Command Line The user defaults database is found in ~/Library/Preferences/ . To edit it from the command line, you use a tool called defaults. For example, to see your defaults for Xcode, you can bring up the Terminal and enter the following command: read more..

  • Page - 302

    Challenge Add to the Preferences panel a button that will remove all the user's defaults. Label the button Reset Preferences. Don't forget to update the Preferences window to reflect the new defaults. read more..

  • Page - 303

    Chapter 14. Using Notifications A user may have several RaiseMan documents open when he or she decides that it is too hard to read them with a purple background. The user opens the Preferences panel, changes the background color, but then is disappointed to find that the color of the existing windows doesn't read more..

  • Page - 304

    Chapter 14. Using Notifications A user may have several RaiseMan documents open when he or she decides that it is too hard to read them with a purple background. The user opens the Preferences panel, changes the background color, but then is disappointed to find that the color of the existing windows doesn't read more..

  • Page - 305

    What Notifications Are Not When programmers first hear about the notification center, they sometimes think that it is a form of interprocess communications. They think, "I will create an observer in one application and post notifications from an object in another." This scheme doesn't work, however: A read more..

  • Page - 306

    NSNotification and NSNotificationCenter Notification objects are very simple. A notification is like an envelope into which the poster will place information for the observers. A notification has two important instance variables: name and object . Nearly always, object is a pointer to the object that posted the read more..

  • Page - 307

    If notificationName is nil , the notification center sends the observer all notifications with an object matching anObject . If anObject is nil , the notification center sends the observer all notifications with the name notificationName . The observer is not retained by the notification center. Note that the method takes read more..

  • Page - 308

    - (void)postNotificationName:(NSString *)aName object:(id)anObject Creates and posts a notification. - (void)removeObserver:(id)observer Removes observer from the list of observers. read more..

  • Page - 309

    Posting a Notification Posting a notification is the easiest step, so you will start there. When it receives a changeBackgroundColor: message, your PreferenceController object will post a notification with the new color. You are going to name the notification @"BNRColorChanged" , but you are going to create a global read more..

  • Page - 310

    Registering as an Observer To register as an observer, you must supply several things: the object that is the observer, the names of the notifications in which it is interested, and the message that you want sent when an interesting notification arrives. You can also specify that you are interested only in read more..

  • Page - 311

    Handling the Notification When It Arrives When the notification arrives, the method handleColorChange: is called. For now, simply log its arrival. Add this method to your MyDocument.m file: - (void)handleColorChange:(NSNotification *)note { NSLog(@"Received notification: %@", note); } Build and run the application. Note that the read more..

  • Page - 312

    The userInfo Dictionary If you wanted to include more than just the poster with the notification, you would use the user info dictionary. Every notification has a variable called userInfo that can be attached to an NSDictionary filled with other information that you want to pass to the observers. In this case, read more..

  • Page - 313

    For the More Curious: Delegates and Notifications An object that has made itself the delegate of a standard Cocoa object is probably interested in receiving notifications from that object as well. For example, if you have implemented a delegate to handle the windowShouldClose: delegate method for a window, that read more..

  • Page - 314

    Challenge Make your application beep when it gives up its active status. NSApplication posts an NSApplicationDidResignActiveNotification notification. Your AppController is a delegate of NSApplication . NSBeep() will cause a system beep. read more..

  • Page - 315

    Chapter 15. Using Alert Panels Occasionally, you will want to warn the user about something by means of an Alert panel. Alert panels are easy to create. Most things in Cocoa are object oriented, but showing a modal Alert panel is typically done with a C function: NSRunAlertPanel() . Here is the declaration: int read more..

  • Page - 316

    would result in the Alert panel shown in Figure 15.2. Figure 15.2. Another Example Alert Panel Alert panels run modally; that is, other windows in the application don't receive events until the Alert panel has been dismissed. Alerts can also be run as a sheet. A sheet is a window that drops down in read more..

  • Page - 317

    To enable this behavior, open MyDocument.nib , select the table view, and open the Inspector. Allow the user to make multiple selections (Figure 15.4). Figure 15.4. Inspect TableView [View full size image] You now want the Delete button to send to MyDocument a message that will ask the user to confirm the read more..

  • Page - 318

    } This method will start the sheet. When the user clicks a button, the document object will get sent the alertEnded:code:context: message: - (void)alertEnded:(NSAlert *)alert code:(int)choice context:(void *)v { NSLog(@"Alert sheet ended"); // If the user chose "Delete", tell the read more..

  • Page - 319

    Chapter 15. Using Alert Panels Occasionally, you will want to warn the user about something by means of an Alert panel. Alert panels are easy to create. Most things in Cocoa are object oriented, but showing a modal Alert panel is typically done with a C function: NSRunAlertPanel() . Here is the declaration: int read more..

  • Page - 320

    would result in the Alert panel shown in Figure 15.2. Figure 15.2. Another Example Alert Panel Alert panels run modally; that is, other windows in the application don't receive events until the Alert panel has been dismissed. Alerts can also be run as a sheet. A sheet is a window that drops down in read more..

  • Page - 321

    To enable this behavior, open MyDocument.nib , select the table view, and open the Inspector. Allow the user to make multiple selections (Figure 15.4). Figure 15.4. Inspect TableView [View full size image] You now want the Delete button to send to MyDocument a message that will ask the user to confirm the read more..

  • Page - 322

    } This method will start the sheet. When the user clicks a button, the document object will get sent the alertEnded:code:context: message: - (void)alertEnded:(NSAlert *)alert code:(int)choice context:(void *)v { NSLog(@"Alert sheet ended"); // If the user chose "Delete", tell the read more..

  • Page - 323

    Challenge Add to the Alert sheet another button that says Keep, but no raise. Instead of deleting the employees, this button will simply set the raises of the selected employees to zero. read more..

  • Page - 324

    Chapter 16. Localization If the application you create is useful, you will want to share it with all the people of the world. Unfortunately, we don't all speak the same language. Suppose that you wish to make your RaiseMan application available to French speakers. We would say, "You are going to localize read more..

  • Page - 325

    Localizing a Nib File In Xcode, select—but do not open—MyDocument.nib, and bring up the Info panel. Click the Add Localization button (Figure 16.2). Figure 16.2. Create a French Version of MyDocument.nib [View full size image] read more..

  • Page - 326

    You will be prompted for a locale. Choose French. If you look in Finder, you will see that a copy of English.lproj/MyDocument.nib has been created in French.lproj . You will francophize this copy. In Xcode, under the Resources group, you will have two versions of MyDocument.nib : English and French, as shown in read more..

  • Page - 327

    Make your window look like Figure 16.4. Figure 16.4. Completed Interface [View full size image] To type in characters with accents, you will need to use the Option key. For example, to type é , type the e , while holding down the Option key, and then type e again. (In the International page of System read more..

  • Page - 328

    which key combinations create which characters.) At this point, you have created a localized resource. Note that if you make a lot of changes to your program, you may need to update both nib files (the French version and the English version). For this reason, it is a good idea to wait until the read more..

  • Page - 329

    Chapter 16. Localization If the application you create is useful, you will want to share it with all the people of the world. Unfortunately, we don't all speak the same language. Suppose that you wish to make your RaiseMan application available to French speakers. We would say, "You are going to localize read more..

  • Page - 330

    Localizing a Nib File In Xcode, select—but do not open—MyDocument.nib, and bring up the Info panel. Click the Add Localization button (Figure 16.2). Figure 16.2. Create a French Version of MyDocument.nib [View full size image] read more..

  • Page - 331

    You will be prompted for a locale. Choose French. If you look in Finder, you will see that a copy of English.lproj/MyDocument.nib has been created in French.lproj . You will francophize this copy. In Xcode, under the Resources group, you will have two versions of MyDocument.nib : English and French, as shown in read more..

  • Page - 332

    Make your window look like Figure 16.4. Figure 16.4. Completed Interface [View full size image] To type in characters with accents, you will need to use the Option key. For example, to type é , type the e , while holding down the Option key, and then type e again. (In the International page of System read more..

  • Page - 333

    which key combinations create which characters.) At this point, you have created a localized resource. Note that if you make a lot of changes to your program, you may need to update both nib files (the French version and the English version). For this reason, it is a good idea to wait until the read more..

  • Page - 334

    String Tables For each language, you can create several string tables. A string table is a file with the extension .strings . For example, if you had a Find panel, you might create a Find.strings file for each language. This file would have the phrases used by the Find panel, such as None found . The read more..

  • Page - 335

    Edit the new file to have the following text: "DELETE" = "Delete"; "SURE_DELETE" = "Do you really want to delete %d people?"; "CANCEL" = "Cancel"; Save it. (Don't forget the semicolons!) Now create a localized version of that file for French. Select the Localizable.strings file in Xcode, bring up the Info read more..

  • Page - 336

    (To create the u with the circumflex, type i while holding down the Option key, and then type u . To type é , type e while holding down the Option key, and then type e again.) When saving a file with unusual characters, you should use the Unicode (UTF-8) file encoding. In the Info panel for read more..

  • Page - 337

    table:nil]; Fortunately, there is a macro defined in NSBundle.h for this purpose: #define NSLocalizedString(key, comment) [[NSBundle mainBundle] localizedStringForKey:(key) read more..

  • Page - 338

    For the More Curious: ibtool Clearly, as you develop and localize many applications, you will develop a set of common translations. It would be handy to have an automated way to get the translated strings into a nib file. This is one of several uses for ibtool . The ibtool command, which is run from read more..

  • Page - 339

    For the More Curious: Explicit Ordering of Tokens in Format Strings As text is moved from language to language, the words change, as does their order. For example, in one language, the words may be laid out like this: "Ted wants a scooter." In another, the order might be "A scooter is what read more..

  • Page - 340

    Chapter 17. Custom Views All visible objects in an application are either windows or views. In this chapter, you will create a subclass of NSView . From time to time, you may need to create a custom view to do custom drawing or event handling. Even if you do not plan to do custom drawing or event read more..

  • Page - 341

    - (NSWindow *)window; Any view can have subviews, but most don't. The following five views commonly have subviews: 1. The content view of a window. 2. NSBox . The contents of a box are its subviews. 3. NSScrollView . A view that appears in a scroll view is a subview of the scroll view. The scroll read more..

  • Page - 342

    read more..

  • Page - 343

    Chapter 17. Custom Views All visible objects in an application are either windows or views. In this chapter, you will create a subclass of NSView . From time to time, you may need to create a custom view to do custom drawing or event handling. Even if you do not plan to do custom drawing or event read more..

  • Page - 344

    - (NSWindow *)window; Any view can have subviews, but most don't. The following five views commonly have subviews: 1. The content view of a window. 2. NSBox . The contents of a box are its subviews. 3. NSScrollView . A view that appears in a scroll view is a subview of the scroll view. The scroll read more..

  • Page - 345

    read more..

  • Page - 346

    Getting a View to Draw Itself In this section, you will create a very simple view that will appear and paint itself green. It will look like Figure 17.4. Figure 17.4. Completed Application [View full size image] Create a new project of type Cocoa Application. Name the project ImageFun. Using the File->New read more..

  • Page - 347

    Resize the view to fill most of the window. Open the Info panel, and set the class of the view to be StretchView (Figure 17.6). Figure 17.6. Set the Class of the View to StretchView [View full size image] Size Inspector Your StretchView object is a subview of the window's content view. This point raises an read more..

  • Page - 348

    Figure 17.7. Make the View Resize with the Window [View full size image] If you wanted the view to stay the same height, you could let the distance between the bottom of the view and the bottom of the superview grow and shrink. You could also let the distance between the right edge of the view and read more..

  • Page - 349

    Figure 17.9. What the Red Lines in the Size Inspector Mean Save and close the nib file. drawRect When a view needs to draw itself, it is sent the message drawRect: with the rectangle that needs to be drawn or redrawn. The method is called automatically—you never need to call it directly. Instead, if read more..

  • Page - 350

    You can use NSBezierPath to draw lines, circles, curves, and rectangles. You can use NSImage to create composite images on the view. In this example, you will fill the entire view with a green rectangle. Open StretchView.m and add the following code to the drawRect: method: - (void)drawRect:(NSRect)rect { NSRect read more..

  • Page - 351

    Note that your view knows its location as an NSRect called bounds . In this method, you fetched the bounds rectangle, set the current color to green, and filled the entire bounds rectangle with the current color. The NSRect that is passed as an argument to the view is the region that is read more..

  • Page - 352

    Drawing with NSBezierPath If you want to draw lines, ovals, curves, or polygons, you can use NSBezierPath . In this chapter, you have already used the NSBezierPath 's fillRect: class method to color your view. In this section, you will use NSBezierPath to draw lines connecting random points (Figure 17.11). Figure 17.11. read more..

  • Page - 353

    @end In StretchView.m , you will override initWithFrame: . As the designated initializer for NSView , initWithFrame: will be called automatically when an instance of your view is created. In your version of initWithFrame: , you will create the path object and fill it with lines to random points. Make StretchView.m look like read more..

  • Page - 354

    // Draw the path in white [[NSColor whiteColor] set]; [path stroke]; } @end Build and run your app. Pretty, eh? Okay, now try replacing [path stroke] with [path fill] . Build and run it. read more..

  • Page - 355

    NSScrollView In the art world, a larger work is typically more expensive than a smaller one of equal quality. Your beautiful view is lovely, but it would be more valuable if it were larger. How can it be larger yet still fit inside that tiny window? You are going to put it in a scroll view read more..

  • Page - 356

    As the window resizes, you want the scroll view to resize, but you do not want your document to resize. Open the Size Inspector, select Scroll View, and set the Size Inspector so that it resizes with the window (Figure 17.14). Figure 17.14. Make Scroll View Resize with Window [View full size image] read more..

  • Page - 357

    Note the width and height of the view. To select the document view, double-click inside the scroll view. You should see the title of the inspector change to Stretch View Size. Make the view about twice as wide and twice as tall as the scroll view. Set the Size Inspector so that the view will read more..

  • Page - 358

    read more..

  • Page - 359

    Creating Views Programmatically You will instantiate most of your views in Interface Builder. Every once in a while, you will need to create views programmatically. For example, assume that you have a pointer to a window and want to put a button on it. This code would create a button and put it on read more..

  • Page - 360

    For the More Curious: Cells NSControl inherits from NSView . With its graphics context, NSView is a relatively large and expensive object to create. When the NSButton class was created, the first thing someone did was to create a calculator with 10 rows and 10 columns of buttons. The performance was less read more..

  • Page - 361

    until the matrix has the correct number of rows and columns (Figure 17.18). Figure 17.18. A Matrix of Buttons [View full size image] An NSMatrix has a target and an action. A cell may also have a target and an action. If the cell is activated, the cell's target and action are used. If the target read more..

  • Page - 362

    For the More Curious: isFlipped Both PDF and PostScript use the standard Cartesian coordinate system, whereby y increases as you move up the page. Quartz follows this model by default. The origin is usually at the lower-left corner of the view. For some types of drawing, the math becomes easier if the read more..

  • Page - 363

    Challenge NSBezierPath can also draw Bezier curves. Replace the straight lines with randomly curved ones. (Hint: Look in the documentation for NSBezierPath .) read more..

  • Page - 364

    Chapter 18. Images and Mouse Events In the previous chapter, you drew lines connecting random points. A more interesting application would have been to write a drawing application. To write this sort of application, you will need to be able to get and handle mouse events. NSResponder NSView inherits from NSResponder . read more..

  • Page - 365

    Chapter 18. Images and Mouse Events In the previous chapter, you drew lines connecting random points. A more interesting application would have been to write a drawing application. To write this sort of application, you will need to be able to get and handle mouse events. NSResponder NSView inherits from NSResponder . read more..

  • Page - 366

    NSEvent An event object has all the information about what the user did to trigger the event. When you are dealing with mouse events, you might be interested in the following methods: - (NSPoint)locationInWindow This method returns the location of the mouse event. - (unsigned int)modifierFlags The integer tells you which read more..

  • Page - 367

    - (int)clickCount Was it a single-, double-, or triple-click? - (float)pressure If the user is using an input device that gives pressure (a tablet, for example), this method returns the pressure. It is between 0 and 1. - (float)deltaX; - (float)deltaY; - (float)deltaZ; These methods give the change in the position of the read more..

  • Page - 368

    Getting Mouse Events To get mouse events, you need to override the mouse event methods in StretchView.m : #pragma mark Events - (void)mouseDown:(NSEvent *)event { NSLog(@"mouseDown: %d", [event clickCount]); } - (void)mouseDragged:(NSEvent *)event { NSPoint p = [event locationInWindow]; NSLog(@"mouseDragged:%@", NSStringFromPoint(p)); } - read more..

  • Page - 369

    Using NSOpenPanel It would be fun to composite an image onto the view, but first, you need to create a controller object that will read the image data from a file. This is a good opportunity to learn how to use NSOpenPanel . Note that the RaiseMan application used the NSOpenPanel , but it was done read more..

  • Page - 370

    Change the Nib File In Xcode, create a new Objective-C class named AppController . In AppController.h , add an outlet for the StretchView and an action that will start the Open panel: #import <Cocoa/Cocoa.h> @class StretchView; @interface AppController : NSObject { IBOutlet StretchView *stretchView; } - (IBAction)showOpenPanel:(id)sender; Open read more..

  • Page - 371

    Figure 18.4. Inspect the Slider [View full size image] Bind the value of the slider to the AppController 's stretchView.opacity Key Path (Figure 18.5). Figure 18.5. Bind the Slider's Value [View full size image] Control-click on the AppController . Connect the stretchView outlet to the StretchView on the window (Figure 18.6). read more..

  • Page - 372

    [View full size image] Look at the main menu in your nib. Open the File menu and delete all menu items except Open. Control-drag to connect the menu item to the AppController 's showOpenPanel: action (Figure 18.7). Figure 18.7. Connect the Menu Item [View full size image] read more..

  • Page - 373

    Save the file. Edit the Code Edit AppController.m : Code View: #import "AppController.h" #import "StretchView.h" @implementation AppController - (void)openPanelDidEnd:(NSOpenPanel *)openPanel returnCode:(int)returnCode contextInfo:(void *)x { // Did they choose "Open"? if (returnCode == NSOKButton) { read more..

  • Page - 374

    This method brings up an Open panel as a sheet attached to the docWindow . The didEndSelector should have the following signature: - (void)openPanelDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; It should be implemented in the modal delegate. The path is the read more..

  • Page - 375

    Composite an Image onto Your View You will also need to change StretchView so that it uses the opacity and image . First, declare variables and methods in your StretchView.h file: #import <Cocoa/Cocoa.h> @interface StretchView : NSView { NSBezierPath *path; NSImage *image; float opacity; } @property (readwrite) read more..

  • Page - 376

    Also in StretchView.m , you need to add compositing of the image to the drawRect: method: - (void)drawRect:(NSRect)rect { NSRect bounds = [self bounds]; [[NSColor greenColor] set]; [NSBezierPath fillRect:bounds]; [[NSColor whiteColor] set]; [path fill]; if (image) { NSRect imageRect; read more..

  • Page - 377

    The View's Coordinate System The final bit of fun comes from being able to choose the location and dimensions of the image, based on the user's dragging. The mouseDown will indicate one corner of the rectangle where the image will appear, and the mouseUp will indicate the opposite corner. The final application read more..

  • Page - 378

    If b is nil , the point is converted from the window's coordinate system. Mouse events have their locations in the window's coordinate system, so you will nearly always have to convert the point to the local coordinate system. You are going to create variables to hold onto the corners of the rectangle read more..

  • Page - 379

    Declare the currentRect method in StretchView.h . So that the user will see something even if he or she has not dragged, initialize downPoint and currentPoint in the setImage: method: - (void)setImage:(NSImage *)newImage { [newImage retain]; [image release]; image = newImage; NSSize imageSize = [newImage size]; read more..

  • Page - 380

    Autoscrolling To add autoscrolling to your application, you will send the message autoscroll: to the clip view when the user drags. You will include the event as an argument. Open StretchView.m and add the following line to the mouseDragged: method: - (void)mouseDragged:(NSEvent *)event { NSPoint p = [event read more..

  • Page - 381

    For the More Curious: NSImage In most cases, it suffices to read in an image, resize it, and composite it onto a view, as you did in this exercise. An NSImage object has an array of representations. For example, your image might be a drawing of a cow. That drawing can be in PDF, a color read more..

  • Page - 382

    Challenge Create a new document-based application that allows the user to draw ovals in arbitrary locations and sizes. NSBezierPath has the following method: + (NSBezierPath *)bezierPathWithOvalInRect:(NSRect)rect; If you are feeling ambitious, add the ability to save and read files. If you are feeling extra ambitious, add undo read more..

  • Page - 383

    Chapter 19. Keyboard Events When the user types, where are the corresponding events sent? First, the window manager gets the event and forwards it to the active application. The active application forwards the keyboard events to the key window. The key window forwards the event to the "active" view. Which read more..

  • Page - 384

    [View full size image] Note that each window has its own first responder. Several windows may be open, but only the first responder of the key window gets the keyboard events. NSResponder We are interested in the following methods that are inherited from NSResponder : - (BOOL)acceptsFirstResponder Overridden by a subclass read more..

  • Page - 385

    Notifies the receiver that has become first responder in its NSWindow . - (void)keyDown:(NSEvent *)theEvent Informs the receiver that the user has pressed a key. - (void)keyUp:(NSEvent *)theEvent Informs the receiver that the user has released a key. - (void)flagsChanged:(NSEvent *)theEvent Informs the receiver that the user has pressed read more..

  • Page - 386

    Chapter 19. Keyboard Events When the user types, where are the corresponding events sent? First, the window manager gets the event and forwards it to the active application. The active application forwards the keyboard events to the key window. The key window forwards the event to the "active" view. Which read more..

  • Page - 387

    [View full size image] Note that each window has its own first responder. Several windows may be open, but only the first responder of the key window gets the keyboard events. NSResponder We are interested in the following methods that are inherited from NSResponder : - (BOOL)acceptsFirstResponder Overridden by a subclass read more..

  • Page - 388

    Notifies the receiver that has become first responder in its NSWindow . - (void)keyDown:(NSEvent *)theEvent Informs the receiver that the user has pressed a key. - (void)keyUp:(NSEvent *)theEvent Informs the receiver that the user has released a key. - (void)flagsChanged:(NSEvent *)theEvent Informs the receiver that the user has pressed read more..

  • Page - 389

    NSEvent In the previous chapter, we discussed NSEvent in terms of mouse events. Here are some of the methods commonly used when getting information about a keyboard event: - (NSString *)characters Returns the characters created by the event. - (BOOL)isARepeat Returns YES if the key event is a repeat caused by the read more..

  • Page - 390

    Create a New Project with a Custom View Create a new project of type Cocoa Application. Name the project TypingTutor. In Xcode, create an Objective-C NSView subclass and name it BigLetterView . Lay Out the Interface Open MainMenu.nib . Create an instance of your class by dragging out a CustomView placeholder read more..

  • Page - 391

    Drop two text fields (under Views & Cells -> Input & Values) on the window (Figure 19.5). Figure 19.5. Completed Interface [View full size image] Make Connections Now you need to create the loop of key views for your window. That is, you are setting the order in which the views will be selected read more..

  • Page - 392

    Set the right-hand text field's nextKeyView to be the BigLetterView (Figure 19.7). Figure 19.7. Set nextKeyView of Right-Hand Text Field [View full size image] Finally, set the nextKeyView of the BigLetterView to be the left-hand text field (Figure 19.8). This will enable the user to tab between the three views. read more..

  • Page - 393

    Figure 19.8. Set nextKeyView of the BigLetterView [View full size image] Which view, then, should be the firstResponder when the window first appears? To make the BigLetterView be the initial FirstResponder , right click on the window icon in the doc window and set the initialFirstResponder outlet to the BigLetterView read more..

  • Page - 394

    Save and close the nib file. Write the Code In this section, you will make your BigLetterView respond to key events. You will also make it accept first-responder status. The characters typed by the user will appear in the console. The completed application will look like Figure 19.10. Figure 19.10. Completed read more..

  • Page - 395

    In BigLetterView.h Your BigLetterView will have two instance variables and accessor methods for those variables. The bgColor variable will identify the background color of the view and will be an NSColor object. The string variable will hold on to the letter that the user most recently typed and will be an read more..

  • Page - 396

    Code View: #pragma mark Accessors - (void)setBgColor:(NSColor *)c { [c retain]; [bgColor release]; bgColor = c; [self setNeedsDisplay:YES]; } - (NSColor *)bgColor { return bgColor; } - (void)setString:(NSString *)c { c = [c copy]; [string release]; string = c; NSLog(@"The string is now %@", string); } - read more..

  • Page - 397

    The methods to become firstResponder are as follows: - (BOOL)acceptsFirstResponder { NSLog(@"Accepting"); return YES; } - (BOOL)resignFirstResponder { NSLog(@"Resigning"); [self setNeedsDisplay:YES]; return YES; } - (BOOL)becomeFirstResponder { NSLog(@"Becoming"); [self setNeedsDisplay:YES]; return YES; } Once read more..

  • Page - 398

    [self setString:@" "]; } @end Build and run your program. You should see that your view becomes the first responder. While it is first responder, it should take keyboard events and log them to the terminal. Also, note that you can Tab and Shift-Tab between the views (Figure 19.11). Figure 19.11. read more..

  • Page - 399

    For the More Curious: Rollovers Three mouse events were not discussed in Chapter 18: mouseMoved: , mouseEntered: , and mouseExited: . - (void)mouseMoved:(NSEvent *)event To receive mouseMoved: , the view's window needs to accept "mouse-moved" events. If it does, the mouseMoved: message is sent to the window's first responder. To read more..

  • Page - 400

    { isHighlighted = YES; [self setNeedsDisplay:YES]; } - (void)mouseExited:(NSEvent *)theEvent { isHighlighted = NO; [self setNeedsDisplay:YES]; } You would then check isHighlighted in your drawRect: method and draw the view appropriately. read more..

  • Page - 401

    The Fuzzy Blue Box Your BigLetterView gets a blue box around its edge when it is firstResponder . Note, however, that the box isn't nice and fuzzy like the box around text fields. You want the fuzzy blue box? It takes a little work. See where you draw the blue box in drawRect: in BigLetterView.m ? read more..

  • Page - 402

    Chapter 20. Drawing Text with Attributes The next step is to get the string to appear in our view. At the end of the chapter, your application will look like Figure 20.1. The character being displayed will change as you type. Figure 20.1. Completed Application NSFont Overall, the class NSFont has basically only read more..

  • Page - 403

    this method uses the default user font size. + (NSFont *)userFixedPitchFontOfSize:(float)fontSize + (NSFont *)userFontOfSize:(float)fontSize + (NSFont *)messageFontOfSize:(float)fontSize + (NSFont *)toolTipsFontOfSize:(float)fontSize + (NSFont *)titleBarFontOfSize:(float)fontSize These methods return the user's default font for the corresponding string types. Once again, a size of read more..

  • Page - 404

    Chapter 20. Drawing Text with Attributes The next step is to get the string to appear in our view. At the end of the chapter, your application will look like Figure 20.1. The character being displayed will change as you type. Figure 20.1. Completed Application NSFont Overall, the class NSFont has basically only read more..

  • Page - 405

    this method uses the default user font size. + (NSFont *)userFixedPitchFontOfSize:(float)fontSize + (NSFont *)userFontOfSize:(float)fontSize + (NSFont *)messageFontOfSize:(float)fontSize + (NSFont *)toolTipsFontOfSize:(float)fontSize + (NSFont *)titleBarFontOfSize:(float)fontSize These methods return the user's default font for the corresponding string types. Once again, a size of read more..

  • Page - 406

    NSAttributedString Sometimes, you want to display a string that has certain attributes for a range of characters. For example, suppose that you want to display the string "Big Nerd Ranch" and want the letters 0 through 2 to be underlined, the letters 0 through 7 to be green, and the letters 9 read more..

  • Page - 407

    Here are the names of the global variables for the most commonly used attributes, the type of object they correspond to, and their default values: NSFontAttributeName Font object; 12-point Helvetica NSForegroundColorAttributeName Color; black NSParagraphStyleAttributeName NSParagraphStyle object; the standard paragraph style NSUnderlineColorAttributeName Color; read more..

  • Page - 408

    Word: The attributed string can read and write simple .doc files. OpenOffice When you read a document in, you may want to know some things about it, such as the paper size. If you supply a place where the method can put a pointer to a dictionary, the dictionary will have all the extra information that read more..

  • Page - 409

    Drawing Strings and Attributed Strings Both NSString and NSAttributedString have methods that cause them to be drawn onto a view. NSAttributedString has the following methods: - (void)drawAtPoint:(NSPoint)aPoint Draws the receiver, with aPoint the lower-left corner of the string. - (void)drawInRect:(NSRect)rect Draws the receiver. All read more..

  • Page - 410

    Making Letters Appear Open BigLetterView.h . Add an instance variable to hold the attributes dictionary: #import <Cocoa/Cocoa.h> @interface BigLetterView : NSView { NSColor *bgColor; NSString *string; NSMutableDictionary *attributes; } Open BigLetterView.m . Create a method that creates the attributes dictionary with a font and read more..

  • Page - 411

    In the setString: method, tell the view that it needs to redisplay itself: - (void)setString:(NSString *)c { c = [c copy]; [string release]; string = c; NSLog(@"The string: %@", string); [self setNeedsDisplay:YES]; } Create a method that will display the string in the middle of a rectangle: - read more..

  • Page - 412

    Getting Your View to Generate PDF Data All the drawing commands can be converted into PDF by the AppKit framework. The PDF data can be sent to a printer or to a file. Note that the PDF will always look as good as possible on any device, because it is resolution independent. You have already read more..

  • Page - 413

    BOOL successful = [data writeToFile:path options:0 error:&error]; if (!successful) { NSAlert *a = [NSAlert alertWithError:error]; [a runModal]; } } Also, declare the action method read more..

  • Page - 414

    You will notice that multikeystroke characters (e.g., "é") are not handled by your BigLetterView . To make this possible, you would need to add several methods that the NSInputManager uses. This topic is beyond the scope of this book (I simply wanted to show you how to get keyboard events), but you read more..

  • Page - 415

    For the More Curious: NSFontManager Sometimes, you will have a font that is good but would be perfect if it were bold or italicized or condensed. NSFontManager can be used to make this sort of conversion. You can also use a font manager to change the size of the font. For example, imagine that you read more..

  • Page - 416

    Challenge 1 Give the letter a shadow. The NSShadow class has the following methods: - (id)init; - (void)setShadowOffset:(NSSize)offset; - (void)setShadowBlurRadius:(float)val; - (void)setShadowColor:(NSColor *)color; read more..

  • Page - 417

    Challenge 2 Add the Boolean variables bold and italic to your BigLetterView . Add check boxes that toggle these variables. If bold is YES , make the letter appear in boldface; if italic is YES , make the letter appear in italics. read more..

  • Page - 418

    Chapter 21. Pasteboards and Nil-Targeted Actions The pasteboard server (/usr/bin/pboard) is a process that runs on your Mac. Applications use the NSPasteboard class to write data into and to read data from that process. The pasteboard server makes possible such operations as copying, cutting, and pasting between read more..

  • Page - 419

    Clears whatever was on the pasteboard before and declares the types of data that theOwner will put on the pasteboard. Here are the global variables for the standard types: NSColorPboardType NSFileContentsPboardType NSFilenamesPboardType NSFontPboardType NSPDFPboardType NSPICTPboardType NSPostScriptPboardType NSRulerPboardType NSRTFPboardTyp NSRTFDPboardType NSStringPboardType read more..

  • Page - 420

    Chapter 21. Pasteboards and Nil-Targeted Actions The pasteboard server (/usr/bin/pboard) is a process that runs on your Mac. Applications use the NSPasteboard class to write data into and to read data from that process. The pasteboard server makes possible such operations as copying, cutting, and pasting between read more..

  • Page - 421

    Clears whatever was on the pasteboard before and declares the types of data that theOwner will put on the pasteboard. Here are the global variables for the standard types: NSColorPboardType NSFileContentsPboardType NSFilenamesPboardType NSFontPboardType NSPDFPboardType NSPICTPboardType NSPostScriptPboardType NSRulerPboardType NSRTFPboardTyp NSRTFDPboardType NSStringPboardType read more..

  • Page - 422

    Add Cut, Copy, and Paste to BigLetterView You will create methods named cut: , copy: , and paste: in the BigLetterView class. To make these methods easier to write, you will first create methods for putting data onto and reading data off a pasteboard. Add these methods to BigLetterView.m : Code View: - read more..

  • Page - 423

    - (IBAction)paste:(id)sender { NSPasteboard *pb = [NSPasteboard generalPasteboard]; if(![self readFromPasteboard:pb]) { NSBeep(); } } Declare these methods in BigLetterView.h : - (IBAction)cut:(id)sender; - (IBAction)copy:(id)sender; - (IBAction)paste:(id)sender; read more..

  • Page - 424

    Nil-Targeted Actions How is the right view sent the cut: , copy: , or paste: message? After all, there are many, many views. If you select a text field, it should get the message. When you select another view and then choose the Copy or Paste menu item, the message should go to the newly selected view. read more..

  • Page - 425

    The firstResponder of the main window and its responder chain, including the main window itself The main window's delegate The NSWindowController and then NSDocument object for the main window 5. The instance of NSApplication 6. The delegate of the NSApplication 7. The NSDocumentController This series of objects is known as the read more..

  • Page - 426

    Open the nib file. Note that the cut, copy, and paste items are connected to the icon labeled First Responder. The First Responder icon represents nil . It gives you something to drag to when you want an object to have a nil target (Figure 21.2). Figure 21.2. Check Menu Item [View full size image] The read more..

  • Page - 427

    For the More Curious: Which Object Sends the Action Message? The target on the cut, copy, and paste menu items is nil . We know that sending a message to nil will not do anything. In fact, all target/action messages are handled by NSApplication . It has the following method: - (BOOL)sendAction:(SEL)anAction read more..

  • Page - 428

    For the More Curious: Lazy Copying An application can implement copying to a pasteboard in a lazy manner. For example, imagine a graphics application that copies large images to the pasteboard in several formats: PICT, TIFF, PDF, and so on. You can imagine that copying all these formats onto the pasteboard read more..

  • Page - 429

    Challenge 1 You are putting the string on the pasteboard. Create the PDF for the view, and put that on the pasteboard, too. Now you will be able to copy the image of the letter into graphics programs. Test it using Preview's New from Clipboard menu item. (Don't break the string copy and paste: Put read more..

  • Page - 430

    Challenge 2 In the RaiseMan project, add a menu item that triggers the removeEmployee: method in MyDocument . read more..

  • Page - 431

    Chapter 22. Categories Although the engineers at Apple are very wise, one day you will think, "Golly, if only they had put that method on that class, my life would be so much easier." When this happens, you will want to create a category, a collection of methods that you would like added to read more..

  • Page - 432

    } NSRange r; r.location = 0; r.length = 1; return [self substringWithRange:r]; } @end Now you can use this method as if it were part of NSString . In BigLetterView.m , change readFromPasteboard: to look like this: - (BOOL)readFromPasteboard:(NSPasteboard *)pb { // Is there a string on the pasteboard? read more..

  • Page - 433

    Chapter 22. Categories Although the engineers at Apple are very wise, one day you will think, "Golly, if only they had put that method on that class, my life would be so much easier." When this happens, you will want to create a category, a collection of methods that you would like added to read more..

  • Page - 434

    } NSRange r; r.location = 0; r.length = 1; return [self substringWithRange:r]; } @end Now you can use this method as if it were part of NSString . In BigLetterView.m , change readFromPasteboard: to look like this: - (BOOL)readFromPasteboard:(NSPasteboard *)pb { // Is there a string on the pasteboard? read more..

  • Page - 435

    For the More Curious: Declaring Private Methods Often, you will have in your .m file methods defined that you do not want to advertise by declaring them in your .h file. These are known as private methods. If you call a private method before you declare or define it, you will get a warning from the read more..

  • Page - 436

    For the More Curious: Declaring Informal Protocols With Objective-C 2.0, you can flag parts of a protocol as @optional , and this is how you would declare delegate methods in Objective-C 2.0. But we needed a way to declare them before Objective-C 2.0. What we did was ugly. And we called this bit of ugliness read more..

  • Page - 437

    Chapter 23. Drag-and-Drop Drag-and-drop is little more than a flashy copy-and-paste operation. When the drag starts, some data is copied onto the dragging pasteboard. When the drop occurs, the data is read off the dragging pasteboard. The only thing that makes this technique trickier than copy-and-paste is that users read more..

  • Page - 438

    To be a drag source, your view must implement draggingSourceOperationMask ForLocal: . This method declares what operations the view is willing to participate in as a source. Add the following method to your BigLetterView.m : - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { return NSDragOperationCopy; } This method is read more..

  • Page - 439

    - (void)mouseDown:(NSEvent *)event { [event retain]; [mouseDownEvent release]; mouseDownEvent = event; } You will also need to create an image to drag. You can draw on an image just as you can on a view. To make the drawing appear on the image instead of on the screen, you must first lock read more..

  • Page - 440

    offset:NSMakeSize(0, 0) event:mouseDownEvent pasteboard:pb source:self slideBack:YES]; [anImage release]; } That's it. Build and run the application. You should be able to drag a letter off the view and read more..

  • Page - 441

    Chapter 23. Drag-and-Drop Drag-and-drop is little more than a flashy copy-and-paste operation. When the drag starts, some data is copied onto the dragging pasteboard. When the drop occurs, the data is read off the dragging pasteboard. The only thing that makes this technique trickier than copy-and-paste is that users read more..

  • Page - 442

    To be a drag source, your view must implement draggingSourceOperationMask ForLocal: . This method declares what operations the view is willing to participate in as a source. Add the following method to your BigLetterView.m : - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { return NSDragOperationCopy; } This method is read more..

  • Page - 443

    - (void)mouseDown:(NSEvent *)event { [event retain]; [mouseDownEvent release]; mouseDownEvent = event; } You will also need to create an image to drag. You can draw on an image just as you can on a view. To make the drawing appear on the image instead of on the screen, you must first lock read more..

  • Page - 444

    offset:NSMakeSize(0, 0) event:mouseDownEvent pasteboard:pb source:self slideBack:YES]; [anImage release]; } That's it. Build and run the application. You should be able to drag a letter off the view and read more..

  • Page - 445

    Make BigLetterView a Drag Destination Being a drag destination involves several parts. First, you need to declare your view to be a destination for the dragging of certain types. NSView has a method for this purpose: - (void)registerForDraggedTypes:(NSArray *)pboardTypes You typically call this method in your initWithFrame: read more..

  • Page - 446

    } Add Highlighting To signal the user that the drop is acceptable, your view will highlight itself. Add a highlighted instance variable to BigLetterView.h : @interface BigLetterView : NSView { NSColor *bgColor; NSString *string; NSMutableDictionary *attributes; NSEvent *mouseDownEvent; BOOL highlighted; } ... Now, you are read more..

  • Page - 447

    A third possibility also exists. If we have a pointer that should refer to an object that conforms to a particular protocol, we can declare it like this: id <MyProtocol> foo; NSDraggingInfo is in fact a protocol, not a class. All the dragging-destination methods expect an object that conforms to the read more..

  • Page - 448

    Test Open the nib file, and add another BigLetterView to the window. Delete the text fields. Make sure to set the nextKeyView for each BigLetterView so that you can tab between them (Figure 23.2). Figure 23.2. Set nextKeyView for Each BigLetterView [View full size image] Build and run the application. Note that read more..

  • Page - 449

    For the More Curious: Operation Mask For some apps, the negotiations of what operation will occur when the user drops can be quite complicated. After all, the source advertises its willingness to participate in some kinds of operations through draggingSourceOperationMaskForLocal: . The user may also indicate preferences by read more..

  • Page - 450

    Chapter 24. NSTimer An instance of NSButton has a target and an action (selector). When the button is clicked, the action message is sent to the target. Timers work in a similar way. A timer is an object that has a target, a selector, and a delay, which is given in seconds (Figure 24.1). Figure read more..

  • Page - 451

    An NSProgressIndicator will display how much time is left. After 2 seconds, the application will beep to indicate that the user took too long. Then the user is given 2 more seconds. You will create an AppController class. When the user clicks the Go button, an instance of NSTimer will be created. The read more..

  • Page - 452

    AppController . In AppController.h , give it two outlets and an action. You will also need a timer, an array for the letters, the index of the last letter displayed, and a count that indicates how long the current letter has been visible: #import <Cocoa/Cocoa.h> @class BigLetterView; @interface AppController : NSObject { read more..

  • Page - 453

    Select the BigLetterView on the left. From the Layout menu, choose the Embed Objects in -> Box menu item. Relabel the box Type here. Embed the other BigLetterView in a box, and relabel that box Match this. Drop an NSProgressIndicator on the window. Use the Inspector to make it not indeterminate. Set its read more..

  • Page - 454

    Chapter 24. NSTimer An instance of NSButton has a target and an action (selector). When the button is clicked, the action message is sent to the target. Timers work in a similar way. A timer is an object that has a target, a selector, and a delay, which is given in seconds (Figure 24.1). Figure read more..

  • Page - 455

    An NSProgressIndicator will display how much time is left. After 2 seconds, the application will beep to indicate that the user took too long. Then the user is given 2 more seconds. You will create an AppController class. When the user clicks the Go button, an instance of NSTimer will be created. The read more..

  • Page - 456

    AppController . In AppController.h , give it two outlets and an action. You will also need a timer, an array for the letters, the index of the last letter displayed, and a count that indicates how long the current letter has been visible: #import <Cocoa/Cocoa.h> @class BigLetterView; @interface AppController : NSObject { read more..

  • Page - 457

    Select the BigLetterView on the left. From the Layout menu, choose the Embed Objects in -> Box menu item. Relabel the box Type here. Embed the other BigLetterView in a box, and relabel that box Match this. Drop an NSProgressIndicator on the window. Use the Inspector to make it not indeterminate. Set its read more..

  • Page - 458

    Make Connections Control-drag from the button to the AppController object. Set the action to be stopGo: (Figure 24.7). Figure 24.7. Connect the Button to the AppController [View full size image] Bind the value of the NSProgressIndicator to the count attribute of AppController (Figure 24.8). Figure 24.8. Connect the inLetterView read more..

  • Page - 459

    Control-click on the AppController to display the Connection panel. Drag from inLetterView to the BigLetterView on the left. Drag from outLetterView to the BigLetterView on the right (Figure 24.9). Figure 24.9. Connect the inLetterView Outlet [View full size image] read more..

  • Page - 460

    Adding Code to AppController Implement the following methods in AppController.m : Code View: #import "AppController.h" #import "BigLetterView.h" #define MAX_COUNT (100) #define COUNT_STEP (5) @implementation AppController - (id)init { [super init]; // Create an array of letters letters = [[NSArray alloc] initWithObjects:@"a", @"s", read more..

  • Page - 461

    x = random() % [letters count]; } lastIndex = x; [outLetterView setString:[letters objectAtIndex:x]]; // Start the count again [self resetCount]; } - (IBAction)stopGo:(id)sender { if (timer == nil) { NSLog(@"Starting"); // Create a timer timer = [[NSTimer read more..

  • Page - 462

    For the More Curious: NSRunLoop NSRunLoop is an object that waits. It waits for events to arrive and then forwards them to NSApplication . It waits for timer events to arrive and then forwards them to NSTimer . You can even attach a network socket to the run loop, and it will wait for data to arrive read more..

  • Page - 463

    Challenge Change your ImageFun application so that autoscrolling is timer driven. Delete your mouseDragged: method from StretchView . In mouseDown: , create a repeating timer that invokes a method in the view every tenth of a second. In the invoked method, autoscroll using the current event. To get the current event, read more..

  • Page - 464

    Chapter 25. Sheets A sheet is simply an NSWindow instance that is attached to another window. The sheet comes down over the window, and the window stops getting events until the sheet is dismissed. Typically, you will compose a sheet as an offscreen window in your nib file. NSApplication has several methods read more..

  • Page - 465

    Your AppController will control the slider and the window, so you will need to add outlets for them. Also, your AppController will be sent a message when the user selects the Adjust speed... menu item or clicks the OK button, so you will need to add two action methods to the AppController . Figure read more..

  • Page - 466

    Add Outlets and Actions Edit AppController.h as follows: Code View: #import <Cocoa/Cocoa.h> @class BigLetterView; @interface AppController : NSObject { // Outlets IBOutlet BigLetterView *inLetterView; IBOutlet BigLetterView *outLetterView; IBOutlet NSWindow *speedSheet; // Data NSArray *letters; int lastIndex; // Time read more..

  • Page - 467

    Change the title of the menu item to Adjust Speed.... Control-drag from the menu item to the AppController . Set the action to be showSpeedSheet: (Figure 25.4). Figure 25.4. Connect the Menu Item [View full size image] Create a new window by dragging one out of the Library (under Application -> Windows). read more..

  • Page - 468

    Put a slider on the new window. To label the left end of the slider as Slow and the right end as Fast , drop two uneditable text fields onto the window. Add a button and change its title to OK . Inspect the slider, and set its range to be 1 to 10 (Figure 25.6). Figure 25.6. Inspect read more..

  • Page - 469

    Figure 25.7. Bind the Slider's Value to stepSize [View full size image] When the user clicks the OK button, it should send the AppController a message that will end the sheet. Control-drag from the button to the AppController , and choose endSpeedSheet: as the action (Figure 25.8). Figure 25.8. Set the target of read more..

  • Page - 470

    Save and close the nib file. Add Code In AppController.m , you defined a constant called COUNT_STEP . In the last section, the user went from 0 to 100 in steps of 5. In this section, you will make the step size a variable. If playing Fast , the user will get bigger steps than if playing Slow . read more..

  • Page - 471

    // Seed the random number generator srandom(time(NULL)); stepSize = 5; return self; } In incrementCount , replace COUNT_STEP with stepSize : - (void)incrementCount { [self willChangeValueForKey:@"count"]; count = count + stepSize; if (count > MAX_COUNT) { count = MAX_COUNT; } [self read more..

  • Page - 472

    Chapter 25. Sheets A sheet is simply an NSWindow instance that is attached to another window. The sheet comes down over the window, and the window stops getting events until the sheet is dismissed. Typically, you will compose a sheet as an offscreen window in your nib file. NSApplication has several methods read more..

  • Page - 473

    Your AppController will control the slider and the window, so you will need to add outlets for them. Also, your AppController will be sent a message when the user selects the Adjust speed... menu item or clicks the OK button, so you will need to add two action methods to the AppController . Figure read more..

  • Page - 474

    Add Outlets and Actions Edit AppController.h as follows: Code View: #import <Cocoa/Cocoa.h> @class BigLetterView; @interface AppController : NSObject { // Outlets IBOutlet BigLetterView *inLetterView; IBOutlet BigLetterView *outLetterView; IBOutlet NSWindow *speedSheet; // Data NSArray *letters; int lastIndex; // Time read more..

  • Page - 475

    Change the title of the menu item to Adjust Speed.... Control-drag from the menu item to the AppController . Set the action to be showSpeedSheet: (Figure 25.4). Figure 25.4. Connect the Menu Item [View full size image] Create a new window by dragging one out of the Library (under Application -> Windows). read more..

  • Page - 476

    Put a slider on the new window. To label the left end of the slider as Slow and the right end as Fast , drop two uneditable text fields onto the window. Add a button and change its title to OK . Inspect the slider, and set its range to be 1 to 10 (Figure 25.6). Figure 25.6. Inspect read more..

  • Page - 477

    Figure 25.7. Bind the Slider's Value to stepSize [View full size image] When the user clicks the OK button, it should send the AppController a message that will end the sheet. Control-drag from the button to the AppController , and choose endSpeedSheet: as the action (Figure 25.8). Figure 25.8. Set the target of read more..

  • Page - 478

    Save and close the nib file. Add Code In AppController.m , you defined a constant called COUNT_STEP . In the last section, the user went from 0 to 100 in steps of 5. In this section, you will make the step size a variable. If playing Fast , the user will get bigger steps than if playing Slow . read more..

  • Page - 479

    // Seed the random number generator srandom(time(NULL)); stepSize = 5; return self; } In incrementCount , replace COUNT_STEP with stepSize : - (void)incrementCount { [self willChangeValueForKey:@"count"]; count = count + stepSize; if (count > MAX_COUNT) { count = MAX_COUNT; } [self read more..

  • Page - 480

    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. Here, for example, the developer has started a sheet and inserted a phone number for the context read more..

  • Page - 481

    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 modal—that is, the user is prevented from sending events to any other window. To make a window modal, use the following read more..

  • Page - 482

    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 simply a string. For example, when passed the string "3/17/1975", the NSDateFormatter converts it into an NSDate object that represents the seventeenth day read more..

  • Page - 483

    it has to convert aString —what the user typed in—into an object. The formatter can return YES and set anObject to point to the new object. If the return is NO , the string could not be converted, and the errorPtr is set to indicate what went wrong. Note that errorPtr is a pointer to a read more..

  • Page - 484

    Create ColorFormatter.h In Xcode, create a new Objective-C class. Name it ColorFormatter . In ColorFormatter.h , change the superclass to NSFormatter , and add an instance variable: #import <Cocoa/Cocoa.h> @interface ColorFormatter : NSFormatter { NSColorList *colorList; } @end Save the file. Edit the Nib File Open MainMenu.nib . Drop a read more..

  • Page - 485

    Bind the value of the color well to the AppController 's inLetterView.bgColor (Figure 26.5). Figure 26.5. Bind Value of Color Well to bgColor of inLetterView [View full size image] Bind the value of the text field to the same Key Path (Figure 26.6). Figure 26.6. Bind Value of Text Field to bgColor of read more..

  • Page - 486

    Drop an NSObject in the doc window. Set its class to be ColorFormatter (Figure 26.7). Figure 26.7. Create an Instance of ColorFormatter [View full size image] Control-click on the text field to bring up its Connection panel. Set the formatter outlet to point to the ColorFormatter object (Figure 26.8). Figure 26.8. read more..

  • Page - 487

    NSColorList For this exercise, you will use an NSColorList , a dictionary of color objects that maps a name to an instance of NSColor objects. Several color lists come standard with Mac OS X. In particular, the color list named "Apple" includes many of the standard colors, such as purple and yellow. read more..

  • Page - 488

    Of course, you might want to set a couple of options. For example, you might want to do a case-insensitive search or a backward search—from the end of the string instead of the beginning. To search backward for the string "KA" in "abbakachakaza" in a case- insensitive manner, you would use read more..

  • Page - 489

    return nil; } - (NSString *)stringForObjectValue:(id)obj { // Not a color? if (![obj isKindOfClass:[NSColor class]]) { return nil; } // Convert to an RGB Color Space NSColor *color; color = [obj colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; // Get components as floats between 0 and 1 read more..

  • Page - 490

    } return NO; } } @end Build and run your application. You should be able to type in color names and see the background of the BigLetterView change accordingly. Also, if you use the color well, you should see the name of the color change in the text field. Try read more..

  • Page - 491

    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 simply a string. For example, when passed the string "3/17/1975", the NSDateFormatter converts it into an NSDate object that represents the seventeenth day read more..

  • Page - 492

    it has to convert aString —what the user typed in—into an object. The formatter can return YES and set anObject to point to the new object. If the return is NO , the string could not be converted, and the errorPtr is set to indicate what went wrong. Note that errorPtr is a pointer to a read more..

  • Page - 493

    Create ColorFormatter.h In Xcode, create a new Objective-C class. Name it ColorFormatter . In ColorFormatter.h , change the superclass to NSFormatter , and add an instance variable: #import <Cocoa/Cocoa.h> @interface ColorFormatter : NSFormatter { NSColorList *colorList; } @end Save the file. Edit the Nib File Open MainMenu.nib . Drop a read more..

  • Page - 494

    Bind the value of the color well to the AppController 's inLetterView.bgColor (Figure 26.5). Figure 26.5. Bind Value of Color Well to bgColor of inLetterView [View full size image] Bind the value of the text field to the same Key Path (Figure 26.6). Figure 26.6. Bind Value of Text Field to bgColor of read more..

  • Page - 495

    Drop an NSObject in the doc window. Set its class to be ColorFormatter (Figure 26.7). Figure 26.7. Create an Instance of ColorFormatter [View full size image] Control-click on the text field to bring up its Connection panel. Set the formatter outlet to point to the ColorFormatter object (Figure 26.8). Figure 26.8. read more..

  • Page - 496

    NSColorList For this exercise, you will use an NSColorList , a dictionary of color objects that maps a name to an instance of NSColor objects. Several color lists come standard with Mac OS X. In particular, the color list named "Apple" includes many of the standard colors, such as purple and yellow. read more..

  • Page - 497

    Of course, you might want to set a couple of options. For example, you might want to do a case-insensitive search or a backward search—from the end of the string instead of the beginning. To search backward for the string "KA" in "abbakachakaza" in a case- insensitive manner, you would use read more..

  • Page - 498

    return nil; } - (NSString *)stringForObjectValue:(id)obj { // Not a color? if (![obj isKindOfClass:[NSColor class]]) { return nil; } // Convert to an RGB Color Space NSColor *color; color = [obj colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; // Get components as floats between 0 and 1 read more..

  • Page - 499

    } return NO; } } @end Build and run your application. You should be able to type in color names and see the background of the BigLetterView change accordingly. Also, if you use the color well, you should see the name of the color change in the text field. Try read more..

  • Page - 500

    The delegate of the NSControl Note that bindings mechanism makes a nice Alert sheet when the formatting fails. The text field's delegate can also be informed of the failed formatting. If the formatter decides that the string is invalid, the delegate is sent the following error message: - (BOOL)control:(NSControl read more..

  • Page - 501

    Build and run your application. When validation fails, you will see on the console a message indicating what the string was and why it failed. read more..

  • Page - 502

    Checking Partial Strings You might want to create a formatter that prevents the user from typing letters that are not part of a color name. To make the formatter check the string after every keystroke, implement the following method: - (BOOL)isPartialStringValid:(NSString *)partial newEditingString:(NSString read more..

  • Page - 503

    proposedSelectedRange:(NSRange *)selPtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSel errorDescription:(NSString **)error { // Zero-length strings are fine if ([*partial length] == 0) { return YES; } NSString *match = [self read more..

  • Page - 504

    Formatters That Return Attributed Strings Sometimes, it is nice for the formatter to define not only the string that is to be displayed but also its attributes. For example, a number formatter might print the number in red if it is negative. For this purpose, you will use NSAttributedString . Your formatter read more..

  • Page - 505

    Chapter 27. Printing Code to handle printing is always relatively hard to write. Many factors are at play: pagination, margins, and page orientation, or landscape versus portrait. This chapter is designed to get you started on your journey toward the perfect printout. Compared to most operating systems, Mac OS X makes read more..

  • Page - 506

    - (BOOL)knowsPageRange:(NSRange *)rptr; // Where is each page? - (NSRect)rectForPage:(int)pageNum; As an example, you will add printing to the RaiseMan application. You will print the name and expected raise for as many people as will fit on the paper size that the user selected from the Print panel (Figure 27.2). Figure 27.2. read more..

  • Page - 507

    Also, import PeopleView.h at the top of MyDocument.m . In the MainMenu.nib file, note that the Print... menu item is nil-targeted, and its action is printDocument: . printDocument: will trigger printOperationWithSettings:error: (Figure 27.3). Figure 27.3. Connect Menu Item [View full size image] Create a class called PeopleView that read more..

  • Page - 508

    Code View: #import "PeopleView.h" #import "Person.h" @implementation PeopleView - (id)initWithPeople:(NSArray *)persons { // Call the superclass's designated initializer with some // dummy frame [super initWithFrame:NSMakeRect(0, 0, 700, 700)]; people = [persons copy]; // The attributes of the text to be printed attributes = read more..

  • Page - 509

    // Return the same page rect everytime return pageRect; } #pragma mark Drawing // The origin of the view is at the upper-left corner - (BOOL)isFlipped { return YES; } - (void)drawRect:(NSRect)r { NSRect nameRect; NSRect raiseRect; raiseRect.size.height = nameRect.size.height = lineHeight; nameRect.origin.x = pageRect.origin.x; read more..

  • Page - 510

    Chapter 27. Printing Code to handle printing is always relatively hard to write. Many factors are at play: pagination, margins, and page orientation, or landscape versus portrait. This chapter is designed to get you started on your journey toward the perfect printout. Compared to most operating systems, Mac OS X makes read more..

  • Page - 511

    - (BOOL)knowsPageRange:(NSRange *)rptr; // Where is each page? - (NSRect)rectForPage:(int)pageNum; As an example, you will add printing to the RaiseMan application. You will print the name and expected raise for as many people as will fit on the paper size that the user selected from the Print panel (Figure 27.2). Figure 27.2. read more..

  • Page - 512

    Also, import PeopleView.h at the top of MyDocument.m . In the MainMenu.nib file, note that the Print... menu item is nil-targeted, and its action is printDocument: . printDocument: will trigger printOperationWithSettings:error: (Figure 27.3). Figure 27.3. Connect Menu Item [View full size image] Create a class called PeopleView that read more..

  • Page - 513

    Code View: #import "PeopleView.h" #import "Person.h" @implementation PeopleView - (id)initWithPeople:(NSArray *)persons { // Call the superclass's designated initializer with some // dummy frame [super initWithFrame:NSMakeRect(0, 0, 700, 700)]; people = [persons copy]; // The attributes of the text to be printed attributes = read more..

  • Page - 514

    // Return the same page rect everytime return pageRect; } #pragma mark Drawing // The origin of the view is at the upper-left corner - (BOOL)isFlipped { return YES; } - (void)drawRect:(NSRect)r { NSRect nameRect; NSRect raiseRect; raiseRect.size.height = nameRect.size.height = lineHeight; nameRect.origin.x = pageRect.origin.x; read more..

  • Page - 515

    For the More Curious: Am I Drawing to the Screen? Often in an application, you will want to draw things differently on the screen than on the printer. For example, in a drawing program, the view might show a grid onscreen but not when printed on paper. In your drawRect: method, you can ask the read more..

  • Page - 516

    Challenge Add page numbers to the printout. read more..

  • Page - 517

    Chapter 28. Web Service Web services are getting a lot of hype. In the end, however, they are simply an HTTP request and response whereby each may be carrying XML data. So using a Web service from Cocoa is simply a matter of being able to send HTTP requests and receive responses. It also may read more..

  • Page - 518

    AmaZone In this exercise, you are going to write an application that uses the Amazon Web service to look up books by using keywords. The result of the search will be displayed in a table view. Double-clicking a row will open the page for that book in your Web brower. The app will look like Figure read more..

  • Page - 519

    Chapter 28. Web Service Web services are getting a lot of hype. In the end, however, they are simply an HTTP request and response whereby each may be carrying XML data. So using a Web service from Cocoa is simply a matter of being able to send HTTP requests and receive responses. It also may read more..

  • Page - 520

    AmaZone In this exercise, you are going to write an application that uses the Amazon Web service to look up books by using keywords. The result of the search will be displayed in a table view. Double-clicking a row will open the page for that book in your Web brower. The app will look like Figure read more..

  • Page - 521

    Lay Out the Interface Open MainMenu.nib . Drop an NSObject in the doc window. In the Identity Inspector, set its class to be AppController (Figure 28.5). Figure 28.5. Creating the AppController [View full size image] Drop a text field, a button, a progress indicator, and a table view (with three columns) on the read more..

  • Page - 522

    Control-drag to set the target and the action of the button. It should trigger the fetchBooks: method of the AppController . Control-click on the AppController to bring up the Connection panel, and connect all three outlets: tableView , searchField , and progress . Control-click on the table view to bring up the read more..

  • Page - 523

    You can think of XML data as a tree made up of nodes. Once we have fetched the data from Amazon, we will have an array of NSXMLNode objects: one for each row in the table view. One way to get data out of an XML node is to use XPath (XPath is a little like Key Paths but uses / read more..

  • Page - 524

    Write Code In AppController.h , add instance variables to hold on to the entire XML document and an array of only the nodes that represent books: NSXMLDocument *doc; NSArray *itemNodes; In AppController.m , the first thing you will need is my AWS ID. (If the ID stops working, it is because someone read more..

  • Page - 525

    timeoutInterval:30]; // Fetch the XML response NSData *urlData; NSURLResponse *response; NSError *error; urlData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response read more..

  • Page - 526

    Now that you have an array of nodes, you need an easy way to get the data you need from them. Add a method to AppController.m : - (NSString *)stringForPath:(NSString *)xp ofNode:(NSXMLNode *)n { NSError *error; NSArray *nodes = [n nodesForXPath:xp error:&error]; if (!nodes) { NSAlert *alert = [NSAlert read more..

  • Page - 527

    represents the Finder. - (void)openItem:(id)sender { int row = [tableView clickedRow]; if (row == -1) { return; } NSXMLNode *clickedItem = [itemNodes objectAtIndex:row]; NSString *urlString = [self stringForPath:@"DetailPageURL" read more..

  • Page - 528

    Challenge: Add a WebView At the moment, you are using NSWorkspace to open the Web page in another application. Perhaps the user would like the Web page to appear in a sheet in the existing application (Figure 28.9). Figure 28.9. Use WebView to Display Details [View full size image] The challenge, then, is read more..

  • Page - 529

    Then your controller can implement the following methods: - (void)webView:(WebView *)wv didStartProvisionalLoadForFrame:(WebFrame *)wf; - (void)webView:(WebView *)wv didFinishLoadForFrame:(WebFrame *)wf; - (void)webView:(WebView *)wv didFailProvisionalLoadWithError:(NSError *)error read more..

  • Page - 530

    Chapter 29. View Swapping Instead of bringing up a new window, you will often want to swap out a view and replace it with another. One easy way to do this is to change the content view of a box. Putting each view in its own nib results in a more modular design. In Mac OS 10.5, Apple read more..

  • Page - 531

    Get Started In Xcode, create a new Core Data Document-based Application, and name it Departments. Open up the MyDocument.nib file, and add a box and a pop-up button to the window (Figure 29.3). Figure 29.3. MyDocument.nib Double-click on the pop-up button to open the menu and remove all the menu items from the read more..

  • Page - 532

    #import <Cocoa/Cocoa.h> @interface MyDocument : NSPersistentDocument { IBOutlet NSBox *box; IBOutlet NSPopUpButton *popUp; NSMutableArray *viewControllers; } - (IBAction)changeViewController:(id)sender; @end Save the file. Back in Interface Builder, Control-click on File's Owner to bring up the Connection panel, and set the two read more..

  • Page - 533

    One view will be for looking at departments in a company. The other view will be for looking at the employees of a company. You will do the Departments view first. In Xcode, create an Objective-C class, and name it DepartmentViewController . In DepartmentViewController.h , make it a subclass of ManagingViewController : read more..

  • Page - 534

    (The view outlet is defined in NSViewController .) Save the nib file. Back in DepartmentViewController.m , give the controller a nib and a title in its init method: - (id)init { if (![super initWithNibName:@"DepartmentView" bundle:nil]) { return nil; } read more..

  • Page - 535

    Add View Swapping to MyDocument Now you need to create instances of the controllers in MyDocument and add them to the viewControllers array. Add this to MyDocument.m : #import "MyDocument.h" #import "DepartmentViewController.h" #import "EmployeeViewController.h" @implementation MyDocument - (id)init { [super init]; read more..

  • Page - 536

    ... A pop-up button is basically a button with a menu. When the nib file is loaded, you need to load the menu with an item for each controller. Add this code to MyDocument.m : - (void)windowControllerDidLoadNib:(NSWindowController *)wc { [super windowControllerDidLoadNib:wc]; NSMenu *menu = [popUp menu]; int i, read more..

  • Page - 537

    Chapter 29. View Swapping Instead of bringing up a new window, you will often want to swap out a view and replace it with another. One easy way to do this is to change the content view of a box. Putting each view in its own nib results in a more modular design. In Mac OS 10.5, Apple read more..

  • Page - 538

    Get Started In Xcode, create a new Core Data Document-based Application, and name it Departments. Open up the MyDocument.nib file, and add a box and a pop-up button to the window (Figure 29.3). Figure 29.3. MyDocument.nib Double-click on the pop-up button to open the menu and remove all the menu items from the read more..

  • Page - 539

    #import <Cocoa/Cocoa.h> @interface MyDocument : NSPersistentDocument { IBOutlet NSBox *box; IBOutlet NSPopUpButton *popUp; NSMutableArray *viewControllers; } - (IBAction)changeViewController:(id)sender; @end Save the file. Back in Interface Builder, Control-click on File's Owner to bring up the Connection panel, and set the two read more..

  • Page - 540

    One view will be for looking at departments in a company. The other view will be for looking at the employees of a company. You will do the Departments view first. In Xcode, create an Objective-C class, and name it DepartmentViewController . In DepartmentViewController.h , make it a subclass of ManagingViewController : read more..

  • Page - 541

    (The view outlet is defined in NSViewController .) Save the nib file. Back in DepartmentViewController.m , give the controller a nib and a title in its init method: - (id)init { if (![super initWithNibName:@"DepartmentView" bundle:nil]) { return nil; } read more..

  • Page - 542

    Add View Swapping to MyDocument Now you need to create instances of the controllers in MyDocument and add them to the viewControllers array. Add this to MyDocument.m : #import "MyDocument.h" #import "DepartmentViewController.h" #import "EmployeeViewController.h" @implementation MyDocument - (id)init { [super init]; read more..

  • Page - 543

    ... A pop-up button is basically a button with a menu. When the nib file is loaded, you need to load the menu with an item for each controller. Add this code to MyDocument.m : - (void)windowControllerDidLoadNib:(NSWindowController *)wc { [super windowControllerDidLoadNib:wc]; NSMenu *menu = [popUp menu]; int i, read more..

  • Page - 544

    Resizing the Window What if the two views are radically different sizes? Wouldn't it be nifty if the window would stretch and shrink to make the box fit the view perfectly? You are going to add that now. Open the view nib files, and make the two views different sizes. In MyDocument.nib , select the read more..

  • Page - 545

    Code View: - (void)displayViewController:(ManagingViewController *)vc { // End editing NSWindow *w = [box window]; BOOL ended = [w makeFirstResponder:w]; if (!ended) { NSBeep(); return; } NSView *v = [vc view]; // Compute the new window frame NSSize currentSize = [[box contentView] read more..

  • Page - 546

    Chapter 30. Core Data Relationships It is time to delve a bit deeper into Core Data. In Chapter 11, you dealt with a single entity (Car). In most applications, you will have multiple entities and relationships between them. Core Data supports to-one relationships and unordered to-many relationships. This exercise will read more..

  • Page - 547

    A Department will have an attribute deptName , a string, as well as a to-many relationship called employees with Employee . Finally, a Department will have a to- one relationship called manager with Employee . Add these properties (Figure 30.3). Figure 30.3. Department Entity [View full size image] Note that the read more..

  • Page - 548

    Chapter 30. Core Data Relationships It is time to delve a bit deeper into Core Data. In Chapter 11, you dealt with a single entity (Car). In most applications, you will have multiple entities and relationships between them. Core Data supports to-one relationships and unordered to-many relationships. This exercise will read more..

  • Page - 549

    A Department will have an attribute deptName , a string, as well as a to-many relationship called employees with Employee . Finally, a Department will have a to- one relationship called manager with Employee . Add these properties (Figure 30.3). Figure 30.3. Department Entity [View full size image] Note that the read more..

  • Page - 550

    Create Custom NSManagedObject Classes You will want to display an employee's full name, so you are going to create a custom class to hold employee data. This class will be a subclass of NSManagedObject . A department can be managed only by an employee who works for that department. When an employee who is read more..

  • Page - 551

    #import <CoreData/CoreData.h> @class Department; @interface Employee : NSManagedObject { } @property (retain) NSString *firstName; @property (retain) NSString *lastName; @property (retain) Department *department; @property (readonly) NSString *fullName; @end In Employee.m , implement the method fullName . - (NSString *)fullName { NSString *first = [self firstName]; NSString *last read more..

  • Page - 552

    - (void)addEmployeesObject*Employee *)value; - (void)removeEmployeesObject:Employee *)value; @end Now implement those two methods in Department.m . (Although we care about only the method for removing, they come in pairs; the remove will be ignored unless we also implement the add.) Code View: #import "Department.h" #import "Employee.h" read more..

  • Page - 553

    Lay Out the Interface Before you begin editing the nib files, a warning: There are a lot of bindings to make in this exercise. Be patient. Remember: In this book, you will never bind to a scroll view, a table view, or a cell. You will, however, bind to table columns. Watch the title of the read more..

  • Page - 554

    Use Table 30.1 to set the bindings. Bindings are set in the Bindings Inspector. Table 30.1. Bindings for DepartmentView.nib[a],[b] Object Binding To Controller Key Key Path Depts AC MOC File's Owner managedObjectContext ManagerPopUp AC Content set Depts AC selection employees EmployeeList AC Content set Depts AC selection employees Departments column Value Depts AC read more..

  • Page - 555

    [b] MOC = Managed Object Context On the last binding, use No selection for the No Selection Placeholder. Use Unnamed Department as the Null Placeholder. You can build and run your app. You should be able to add and remove departments. EmployeeView.nib Open EmployeeView.nib , and remove anything on the view. Add a read more..

  • Page - 556

    Last column Value Employees AC arrangedObjects lastName Dept column Content DeptPopUp AC arrangedObjects Dept column Content values DeptPopUp AC arrangedObjects deptName Dept column Selected object Employees AC arrangedObjects department [a] AC = array controller [b] MOC = Managed Object Context Build and run your app. You should now be able to add and read more..

  • Page - 557

    Events and nextResponder The event methods (e.g., mouseDown: and keyDown: ) defined in NSResponder typically simply forward the event on to the nextResponder . Thus, unhandled events flow up the responder chain. So, for example, when someone selects a row in a table view and presses the Delete key, that flows up read more..

  • Page - 558

    Chapter 31. Garbage Collection As long as you use only Objective-C objects, the garbage collector will do exactly what you want, without your needing to think about it. However, as soon as you start to malloc C data types and Core Foundation structures, you will need to be a bit more circumspect. When the read more..

  • Page - 559

    it looks like this: - (void)finalize { ...Do some last minute stuff here... [super finalize]; } Throughout this book, you have been writing "dual-mode code" that will work with or without the garbage collector. In this chaper and the next, however, you will be writing code that is designed to work only read more..

  • Page - 560

    Once again, if you want the reference to be strong, you will need to be explicit: __strong CFStringRef str; read more..

  • Page - 561

    Chapter 31. Garbage Collection As long as you use only Objective-C objects, the garbage collector will do exactly what you want, without your needing to think about it. However, as soon as you start to malloc C data types and Core Foundation structures, you will need to be a bit more circumspect. When the read more..

  • Page - 562

    it looks like this: - (void)finalize { ...Do some last minute stuff here... [super finalize]; } Throughout this book, you have been writing "dual-mode code" that will work with or without the garbage collector. In this chaper and the next, however, you will be writing code that is designed to work only read more..

  • Page - 563

    Once again, if you want the reference to be strong, you will need to be explicit: __strong CFStringRef str; read more..

  • Page - 564

    Polynomials Example In this example, you are going to create a Polynomial class that has a C array of float s and a CGColorRef . The Polynomial will draw itself, using CoreGraphics. A PolynomialView will display an array of Polynomial objects, as shown in Figure 31.2. Figure 31.2. Running Application [View full size read more..

  • Page - 565

    __strong CGFloat * terms; int termCount; __strong CGColorRef color; } - (float)valueAt:(float)x; - (void)drawInRect:(CGRect)b inContext:(CGContextRef)ctx; - (CGColorRef)color; @end Note that you explicitly marked the pointer to the C array and the CGColorRef as strong references. This will keep the garbage collector from read more..

  • Page - 566

    - (float)valueAt:(float)x { float result = 0; int i; for (i = 0; i < termCount; i++) { result = (result * x) + terms[i]; } return result; } // Draw using core graphics - (void)drawInRect:(CGRect)b inContext:(CGContextRef)ctx { NSLog(@"drawing"); CGContextSaveGState(ctx); // Scale and translate read more..

  • Page - 567

    What could have gone wrong? If you had forgotten the __strong directive, the CGColor and the C array would have been immediately deallocated by the garbage collector. This would have crashed your program in a sometimes strange and unpredictable manner. If you had forgotten to use NSAllocateCollectable() to read more..

  • Page - 568

    [self setNeedsDisplay:YES]; } - (void)drawRect:(NSRect)rect { NSRect bounds = [self bounds]; [[NSColor whiteColor] set]; [NSBezierPath fillRect:bounds]; // Get ahold of the core graphics context CGContextRef ctx = [[NSGraphicsContext currentContext] read more..

  • Page - 569

    Before building the application, make sure that the garbage collector is enabled. In Xcode, double-click on the target to bring up the Inspector panel. In the build settings, make sure that the garbage collector is required for all configurations (Figure 31.4). Figure 31.4. Turn on Garbage Collector [View full size read more..

  • Page - 570

    Instruments Instruments is a tool for analyzing a running program. The tool has many plug-ins, called instruments, that enable you to look at different aspects, usually performance related, of the running application. In this example, you are going to use the ObjectAllocations instrument to monitor the creation and destruction read more..

  • Page - 571

    Unpause the application. As you add and remove polynomials, you should see the Net # of Polynomial objects and CGColor structures rise and fall. If they never fall, you have a memory leak. If you click on Polynomial in the Category column, you can inspect the individual instances of Polynomial and how they read more..

  • Page - 572

    What about checking the leaking C arrays? Sadly, the C arrays you created are small general allocations, and there are a gazillion of those in your running application. Hunting them down would be difficult. Here is a stupid trick that will work: Make the allocations larger and of a specific size. Alter read more..

  • Page - 573

    For the More Curious: Weak References Sometimes, you will want to have an object pointer that should point to that object as long as it exists, but you do not want that pointer to prevent the garbage collector from deallocating the object. In this case, you can use a weak reference: __weak NSFont read more..

  • Page - 574

    Challenge: Do Bad Things Create memory leaks: Leak the C array and the CGColor structures when you remove. Observe the leaks in Instruments. Then fix them again. Crash your application: Make the garbage collector deallocate the C array and CGColor structure prematurely. Run in the debugger, and observe the resulting read more..

  • Page - 575

    Chapter 32. Core Animation As Mac OS X has evolved, it has used OpenGL more and more to use the power of modern graphics processors. To make some of these capabilities convenient for all programmers, Apple created CALayer in Mac OS X 10.5. You can think of a CALayer as a buffer that you can draw read more..

  • Page - 576

    The framework is /System/Library/Frameworks/QuartzCore.framework . Open the MainMenu.nib file. In the Animation Inspector, check the PolynomialView to make it CALayer -backed. (We say that the view wants a CALayer.) See Figure 32.3. Figure 32.3. Polynomial View Wants CALayer [View full size image] Add a button with the title read more..

  • Page - 577

    [View full size image] The Blast button will cause all the polynomials to move out of the view. Blasting a second time will bring them all back. Declare the method in PolynomialView.h . We are also going to need a BOOL to keep track of whether the polynomials have already been blasted off the read more..

  • Page - 578

    { NSRect bounds = [self bounds]; [[NSColor whiteColor] set]; [NSBezierPath fillRect:bounds]; } Create a stub for blastem: in PolynomialView.m : #import "PolynomialView.h" #import "Polynomial.h" #import <QuartzCore/QuartzCore.h> #define MARGIN (10) @implementation PolynomialView - (id)initWithFrame:(NSRect)frame { [super initWithFrame:frame]; read more..

  • Page - 579

    Chapter 32. Core Animation As Mac OS X has evolved, it has used OpenGL more and more to use the power of modern graphics processors. To make some of these capabilities convenient for all programmers, Apple created CALayer in Mac OS X 10.5. You can think of a CALayer as a buffer that you can draw read more..

  • Page - 580

    The framework is /System/Library/Frameworks/QuartzCore.framework . Open the MainMenu.nib file. In the Animation Inspector, check the PolynomialView to make it CALayer -backed. (We say that the view wants a CALayer.) See Figure 32.3. Figure 32.3. Polynomial View Wants CALayer [View full size image] Add a button with the title read more..

  • Page - 581

    [View full size image] The Blast button will cause all the polynomials to move out of the view. Blasting a second time will bring them all back. Declare the method in PolynomialView.h . We are also going to need a BOOL to keep track of whether the polynomials have already been blasted off the read more..

  • Page - 582

    { NSRect bounds = [self bounds]; [[NSColor whiteColor] set]; [NSBezierPath fillRect:bounds]; } Create a stub for blastem: in PolynomialView.m : #import "PolynomialView.h" #import "Polynomial.h" #import <QuartzCore/QuartzCore.h> #define MARGIN (10) @implementation PolynomialView - (id)initWithFrame:(NSRect)frame { [super initWithFrame:frame]; read more..

  • Page - 583

    Using CALayer and CAAnimation Now you will add layers containing the polynomials to the base layer. First, you need to create a method that will figure out a random off-view point. (You are going to slide the origin of the layer from that random point.) Add a method to PolynomialView.m : - read more..

  • Page - 584

    [layer setBorderColor:[p color]]; [layer setBorderWidth:3.5]; // The instance of Polynomial will do the drawing [layer setDelegate:p]; // Add the new layer to the base layer for the view [[self layer] addSublayer:layer]; // Render the layer [layer display]; // Make an animation that will move the layer on read more..

  • Page - 585

    // Choose a point to drag it off to NSPoint randPoint = [self randomOffViewPosition]; // Create the animation that will drive the motion offscreen CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; // The animation will let you stuff anything you want into its // dictionary. At read more..

  • Page - 586

    NSPoint r = [self randomOffViewPosition]; // Convert from NSPoint to CGPoint p = *(CGPoint *)&r; } [layer setPosition:p]; } [NSAnimationContext endGrouping]; blasted = !blasted; } Build and run that. Try the Blast button. Nice? Try resizing the read more..

  • Page - 587

    Build and run the app. Resize the window. CALayer In the exercise, you did explicit drawing on the CGContext of the CALayer in your Polynomial class. This mechanism allows you to do any sort of drawing that you can imagine on the CALayer . However, much of the time, you will simply want to control a few read more..

  • Page - 588

    Chapter 33. A Simple Cocoa/OpenGL Application This chapter is not designed to teach you OpenGL; if you want to learn OpenGL, read The OpenGL Programming Guide. This chapter is intended to show you how to do drawing with OpenGL in an application that is written using Cocoa. Like all other drawing in Cocoa, read more..

  • Page - 589

    Chapter 33. A Simple Cocoa/OpenGL Application This chapter is not designed to teach you OpenGL; if you want to learn OpenGL, read The OpenGL Programming Guide. This chapter is intended to show you how to do drawing with OpenGL in an application that is written using Cocoa. Like all other drawing in Cocoa, read more..

  • Page - 590

    Writing the Application Figure 33.1 shows the application that you will create. Figure 33.1. Completed Application Create a new Cocoa application project, and call it Gliss (short for "GL Bliss"). Under the Project menu, use Add to Project... to add the frameworks OpenGL.framework and GLUT.framework —both in read more..

  • Page - 591

    In the Library window, drag an NSOpenGLView from Cocoa -> Views & Cells -> Data Views onto the window (Figure 33.2). Figure 33.2. Drop an NSOpenGLView [View full size image] In the Identity Inspector, set the class of the view to be GlissView (Figure 33.3) Figure 33.3. Set the Class [View full size read more..

  • Page - 592

    Set the target of the matrix to be the GlissView , and set the action to be changeParameter: . Set the sliderMatrix outlet of the the GlissView to point to the matrix. (Be sure to create connections in both directions.) The first slider will control the X-coordinate of the light. Set its range from read more..

  • Page - 593

    The second slider will control the angle from which the scene is viewed. Set its range from –4 to 4, and give it an initial value of 0. It should have a tag of 1. The third slider will control from how far the scene is viewed. Set its range from 0.3 to 5, and give it an initial read more..

  • Page - 594

    Write Code Edit GlissView.h as follows: #import <Cocoa/Cocoa.h> @interface GlissView : NSOpenGLView { IBOutlet NSMatrix *sliderMatrix; float lightX, theta, radius; int displayList; } - (IBAction)changeParameter:(id)sender; @end Next, edit GlissView.m : Code View: #import "GlissView.h" #import <GLUT/glut.h> #define LIGHT_X_TAG 0 #define THETA_TAG 1 #define read more..

  • Page - 595

    { self = [super initWithCoder:c]; [self prepare]; return self; } // Called when the view resizes - (void)reshape { NSLog(@"reshaping"); // Convert up to window space, which is in pixel units. NSRect baseRect = [self convertRectToBase:[self bounds]]; // Now the result is glViewport()-compatible. glViewport(0, 0, read more..

  • Page - 596

    glEndList(); } else { glCallList(displayList); } // Flush to screen glFinish(); } @end Note that the OpenGL calls are broken into three parts: prepare , all the calls to be sent initially; reshape , all the calls to be sent when the view resizes; read more..

  • Page - 597

    Chapter 34. NSTask Each application that you have created is in fact a directory, and somewhere down in that directory is an executable file. To run an executable on a Unix machine, such as your Mac, a process is forked, and the new process executes the code in that file. Many executables are command read more..

  • Page - 598

    Chapter 34. NSTask Each application that you have created is in fact a directory, and somewhere down in that directory is an executable file. To run an executable on a Unix machine, such as your Mac, a process is forked, and the new process executes the code in that file. Many executables are command read more..

  • Page - 599

    ZIPspector You can use the /usr/bin/zipinfo tool for looking at the contents of a zip file. Find a zip file on your machine, and try running zipinfo in the Terminal like this (-1 is dash- one, not dash-el): # /usr/bin/zipinfo -1 /Users/aaron/myfile.zip greatfile.txt swellfile.rtf magnificent.pdf You are going to create an read more..

  • Page - 600

    34.2). Figure 34.2. Setting UTI [View full size image] In MyDocument.h , create outlets for an NSTableView and an NSArray for holding the filenames in the zip file: @interface MyDocument : NSDocument { IBOutlet NSTableView *tableView; NSArray *filenames; } @end Open MyDocument.nib . Add a table view to the window, and read more..

  • Page - 601

    Figure 34.3. Set dataSource Outlet [View full size image] Control-click on File's Owner to bring up its connection window. Drag to set the read more..

  • Page - 602

    tableView outlet (Figure 34.4). Figure 34.4. Set tableView Outlet [View full size image] In MyDocument.m , you are going override readFromURL:ofType:error: to create an NSTask that executes zipinfo . Also, create an NSPipe and connect it to the standardOut of the NSTask (Figure 34.5). Figure 34.5. Object Diagram read more..

  • Page - 603

    Here is the code: Code View: - (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError { // Which file are we getting the zipinfo for? NSString *filename = [absoluteURL path]; // Prepare a task object NSTask *task = [[NSTask alloc] init]; [task read more..

  • Page - 604

    // In case of revert [tableView reloadData]; return YES; } Now you need table view data source methods: - (int)numberOfRowsInTableView:(NSTableView *)v { return [filenames count]; } - (id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tc row:(NSInteger)row { read more..

  • Page - 605

    Asynchronous Reads As mentioned in Chapter 24, the run loop is the object that waits for events. Those may be keyboard, mouse, or timer events. These are all run loop data sources. You can also make a file handle a run loop data source. In this section, we are going to fork off a process that read more..

  • Page - 606

    iPing Now you are going to write a Cocoa app that uses NSTask to run ping (Figure 34.6). Figure 34.6. Completed Application [View full size image] In Xcode, create a new project of type Cocoa Application named iPing. Create a new Objective-C class named AppController . AppController needs two outlets, a variable read more..

  • Page - 607

    Open MainMenu.nib and drop a text view, a text field, and a button on the window. The button should be put in Toggle mode. The title should be Start Ping; the alternate title, Stop Ping Figure 34.7). Figure 34.7. Button Attributes [View full size image] Drag an NSObject out of the library. In the read more..

  • Page - 608

    Make the AppController the target of the button; its action should be startStopPing: . Set the outputView , hostField , and startButton outlets to point to the text view, the text field, and the button, respectively(Figure 34.9). Figure 34.9. Object Diagram [View full size image] In AppController.m , implement startStopPing: Code read more..

  • Page - 609

    nc = [NSNotificationCenter defaultCenter]; [nc removeObserver:self]; [nc addObserver:self selector:@selector(dataReady:) name:NSFileHandleReadCompletionNotification object:fh]; [nc addObserver:self read more..

  • Page - 610

    task = nil; [startButton setState:0]; } Build and run the application. read more..

  • Page - 611

    Challenge: .tar and .tgz files The zipinfo tool gives a listing of files in a zip file. You can get a similar listing for tar files by using the command line tar : # /usr/bin/tar tf MyFiles.tar If the tar file is also compressed, add a z to the flags: # /usr/bin/tar tzf MyFiles.tgz Extend ZIPspector to read more..

  • Page - 612

    Chapter 35. The End When I teach a class, it always ends with the "Feel-Good Talk," which delivers the following messages. The knowledge you have received from this experience never comes easy. You have learned a lot of stuff. Be proud. The only way to solidify what you have learned is to write read more..

  • Page - 613

    If you have exhausted all other possibilities, Apple's Developer Technical Support will answer your questions for a fee. I find the folks there consistently knowledgeable and helpful, and they have answered lots of questions for me. Join the Apple Developer Connection. It will give you access to the latest developer read more..

  • Page - 614

    Chapter 35. The End When I teach a class, it always ends with the "Feel-Good Talk," which delivers the following messages. The knowledge you have received from this experience never comes easy. You have learned a lot of stuff. Be proud. The only way to solidify what you have learned is to write read more..

  • Page - 615

    If you have exhausted all other possibilities, Apple's Developer Technical Support will answer your questions for a fee. I find the folks there consistently knowledgeable and helpful, and they have answered lots of questions for me. Join the Apple Developer Connection. It will give you access to the latest developer read more..

  • Page - 616

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] read more..

  • Page - 617

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] %@ 2nd 3rd 4th $ (in tokens) + in method names @ symbol 2nd .???? extension + prefix : (in method name) read more..

  • Page - 618

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Abstract classes 2nd Accented characters 2nd acceptsFirstResponder 2nd Accessor methods 2nd 3rd 4th 5th 6th Action 2nd [See also Target/action.] Action methods 2nd Active Build Configuration add: 2nd 3rd 4th read more..

  • Page - 619

    NSDocumentController NSKeyedArchiver 2nd 3rd NSKeyedUnarchiver 2nd NSWindowController 2nd universal type identifiers (UTIs) updateChangeCount: Arguments and methods 2nd 3rd Array controller 2nd 3rd Array Controller Attributes 2nd 3rd Array Controller Bindings 2nd Arrays aSelector read more..

  • Page - 620

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Background color 2nd 3rd becomeFirstResponder 2nd beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo: 2nd beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo: Berners-Lee, Tim Bézier path 2nd BigLetterView read more..

  • Page - 621

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] CAAnimation CALayer 2nd calendarDate Calendar format string tokens CAOpenGLLayer Capitalization 2nd 3rd 4th 5th carArrayController CarLot project C array 2nd caseInsensitiveCompare: Categories CATextLayer Cells CFMakeCollectable() read more..

  • Page - 622

    Conditional encoding Conditionally Sets Editable Console (log) containsObject: Continuous sliders 2nd 3rd 4th control: Controller classes 2nd Coordinate systems 2nd copy copy: Copy and paste operations Core animation CALayer CALayer and CAAnimation object diagram polynomials Core Data read more..

  • Page - 623

    Size Inspector view hierarchy view subclass cut: read more..

  • Page - 624

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Dalrymple, Mark Darwin dataForType: dataOfType: 2nd 3rd dataReady: dataSource 2nd 3rd dataWithPDFInsideRect: dateByAddingYears: Date formatter 2nd dateWithYear: dayOfCommonEra dayOfMonth dayOfWeek dayOfYear dealloc 2nd Deallocation read more..

  • Page - 625

    Document architecture Document-based application Document controller Document object Document types Drag-and-drop drag destination dragging-destination methods draggingSourceOperationMaskForLocal: 2nd draggingUpdated drag source highlighting operation mask and pasteboards read more..

  • Page - 626

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Editor view Embed objects in box 2nd Embed objects in matrix 2nd Embed objects in scroll view Employee entity EmployeeView.nib encodeBool:forKey: encodeConditionalObject:forKey encodeDouble:forKey encodeFloat:forKey encodeInt:forKey read more..

  • Page - 627

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Fetch (managed objects) 2nd 3rd File encoding and localization File's Owner 2nd Filesystem defaults File wrapper fileWrapperOfType: finalize message FirstLetter category firstResponder 2nd 3rd flagsChanged: Flipping a read more..

  • Page - 628

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Garbage collection dual-mode code 2nd finalize message Instruments malloc() non-object data types NSAllocateCollectable() 2nd 3rd polynomials read more..

  • Page - 629

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] .h file 2nd handleColorChange: Header file 2nd Helper objects connecting dataSource and delegates 2nd hidesOnDeactivate Highlighting, drag-and-drop hourOfDay HTML HTTP read more..

  • Page - 630

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] IBAction 2nd IBM IBOutlet ibtool Icon alert panel Icons id Identity Inspector 2nd 3rd image Image file formats ImageFun 2nd Image opacity 2nd Image representations Image View Bindings Image Well Immutability read more..

  • Page - 631

    iPing isa pointer isARepeat isDrawingToScreen isEqual: method isFlipped isOpaque isPartialStringValid:newEditingString:errorDescription: Italicized text Iterators read more..

  • Page - 632

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Java code Java interface Jobs, Steve JPG Justification (text) read more..

  • Page - 633

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Keyboard events BigLetterView 2nd custom view project firstResponder 2nd fuzzy blue box interpretKeyEvents: loop of key views NSEvent read more..

  • Page - 634

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] lastObject Late Night Cocoa podcast laterDate: Lazy copying length 2nd 3rd 4th 5th 6th Loading files to apps Localizable.strings Localization accented characters 2nd explicit ordering of tokens read more..

  • Page - 635

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Mac OS X Developer Tools speech synthesizer window server appearance main() 2nd 3rd Main event loop MainMenu.nib 2nd 3rd 4th 5th 6th mainWindow malloc() Managed Object Class read more..

  • Page - 636

    Modifier keys 2nd 3rd Modularity, and panels 2nd mouseDown: 2nd 3rd 4th 5th mouseDragged: 2nd 3rd 4th 5th mouseEntered: Mouse events autoscrolling clickCount compositing getting and image opacity 2nd NSEvent NSImage 2nd 3rd NSOpenPanel read more..

  • Page - 637

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Name keys name method NeXT Computer, Inc. nextKeyView 2nd nextResponder 2nd NeXT Software, Inc. NeXTSTEP Nib (NeXT Interface Builder) files 2nd 3rd 4th 5th nil 2nd 3rd 4th Nil-targeted actions read more..

  • Page - 638

    NSCAssert() NSClipView NSCoder 2nd 3rd NSCoding 2nd NSColorList NSControl 2nd NSController NSControl subclasses NSData 2nd 3rd 4th NSDate 2nd NSDateFormatter NSDatePicker 2nd NSDecimal 2nd NSDictionary 2nd NSDocument 2nd 3rd NSDocumentController 2nd NSDraggingInfo protocol NSDrawer NSEvent 2nd NSException NSFont NSFontManager 2nd read more..

  • Page - 639

    NSPanel 2nd NSPasteboard NSPathControl NSPersistentDocument 2nd 3rd NSPipe 2nd 3rd 4th NSPoint 2nd 3rd 4th 5th 6th NSPrintOperation NSProgressIndicator NSRange 2nd 3rd 4th 5th NSRect 2nd NSResponder 2nd 3rd 4th NSRuleEditor NSRunAlertPanel() NSSavePanel NSScannedOption 2nd NSScrollView 2nd NSSecureTextField NSShadow NSSize NSSlider read more..

  • Page - 640

    NSURLConnection 2nd NSURLRequest NSUserDefaults NSUserDefaultsController NSView 2nd 3rd 4th 5th 6th 7th NSViewController 2nd 3rd NSWindow 2nd 3rd 4th NSWindowController 2nd 3rd [See also View swapping.] NSWindow' s initialFirstResponder outlet NSXMLDocument 2nd NSXMLNode 2nd 3rd NULL Number formatter Number Formatter Attributes 2nd read more..

  • Page - 641

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Object(s) accessor methods archived autoreleased 2nd connecting copies Core Data defined delegates 2nd and key paths read more..

  • Page - 642

    opacity 2nd 3rd Open counterparts in same editor OpenGL 2nd OpenGL application OpenGL.framework OpenGL View Attributes openItem: OpenOffice openPanelDidEnd:returnCode:contextInfo: 2nd OpenStep Operation mask Operators @optional 2nd Ordered-to-many relationships otherMouseDown: otherMouseDragged: otherMouseUp: Outlets (instance variables) Overriding init read more..

  • Page - 643

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Pagination Panel Attributes Panels Partial strings, validating Password display bullets paste: pasteboardChangedOwner: Pasteboards BigLetterView cut: , copy: , and paste: Lazy copying nil-targeted actions read more..

  • Page - 644

    prepareWithInvocationTarget: 2nd 3rd pressure printDocument: printf Printing isDrawingToScreen NSPrintOperation pagination print-object (po) 2nd 3rd Private methods Progress Indicator Attributes Progress Indicator Bindings Project directory @property 2nd Property attributes Property list classes Property (NSManagedObjectModel) read more..

  • Page - 645

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Quartz 2nd QuartzCore framework 2nd Quicklook Quit menu item Quotation marks 2nd 3rd read more..

  • Page - 646

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] RaiseMan application Interface Builder NSArrayController .rsmn extension and undo Xcode RANDFLOAT() random() 2nd 3rd 4th 5th 6th 7th Random number generator application read more..

  • Page - 647

    Retain counts accessor methods autoreleased objects deallocation dog and leash analogy 2nd NSAutoreleasePool retain and release balance Return code 2nd rightMouseDown: rightMouseDragged: rightMouseUp: Rollovers .rsmn extension RTF RTFD Ruby programming language Run loop 2nd read more..

  • Page - 648

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Save panel savePDF: Saving (adding to apps) sayIt: 2nd 3rd 4th 5th Scanned Scroll view 2nd scrollWheel: Sculley, John Search strings for substrings secondNumber 2nd 3rd seed: method 2nd 3rd Seed button read more..

  • Page - 649

    showSpeedSheet: showWindow: 2nd sigint signal size Size Inspector 2nd 3rd sizeWithAttributes: Slider Attributes 2nd 3rd 4th 5th Slider Bindings 2nd 3rd Slider Cell Attributes Slider Inspector Sliders 2nd 3rd 4th Smalltalk (language) Snapshot Sort descriptors sortDescriptorsDidChange: Sorting sortUsingDescriptors: Speech synthesizer 2nd read more..

  • Page - 650

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Table Column Attributes 2nd Table Column Bindings 2nd Table view dataSource 2nd delegate Table View Attributes 2nd tableView 2nd 3rd 4th 5th 6th tableView:objectValueForTableColumn:row: 2nd Taligent read more..

  • Page - 651

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Unarchived (objects) unarchiveObjectWithData: Unarchiving [See Archiving/unarchiving.] unbind: method Undo undoManager 2nd [See also NSUndoManager .] undoManagerForTextView: Undo/redo 2nd Unicode 2nd Unicode UTF-8 Universal type identifiers read more..

  • Page - 652

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] valueForKey: valueForKeyPath: Version-control systems View(s) coordinate system flipping hierarchy [See also Custom views.] View-backing layer View class Views & Cells 2nd View subclass View read more..

  • Page - 653

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Weak references WebKit framework Web service AmaZone Amazon Web service AWS ID code fetchBooks: interface layout NSURL NSXMLDocument 2nd read more..

  • Page - 654

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] x- and y-coordinates 2nd Xcode breakpoints console and defaults documentation document-based application 2nd Foundation Tool and garbage collector read more..

  • Page - 655

    Index [SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Z] Zero-length strings 2nd 3rd 4th Zip files ZIPspector Zombies read more..

Write Your Review