What Readers Are Saying About Programming Cocoa with Ruby This isn’t just a book on RubyCocoa; it is probably the best book I’ve seen that explains Cocoa technology. It actually explains how some of the core technologies, especially bindings, work instead of just show- ing an example of how to use them. Allison Newman Cocoa application developer Learning a new API is hard enough, but learning a new API and a new programming language at the same time can be overwhelming. Pro- gramming Cocoawith Ruby is written for those of us used to a lan- guage like Ruby or Python who want to learn about all the great stuff Cocoa has to offer. Jeremy McAnally Developer, entp The influence of Smalltalk on Ruby and Objective-C is considerable. It shouldn’t be a surprise then that Cocoa, whose native tongue is Objective-C, can be effectively learned and programmed from Ruby in a way that captures the succinctness and expressiveness of this newly popular scripting language. Brian’s book is a great introduc- tion to the agile development of Cocoa apps, it serves as a primer on Cocoa, and it demonstrates sound and thoughtful development prac- tices and hygiene throughout. Jerry Kuch Principal engineer, EMC Corporation Programming Cocoa with Ruby Create Compelling Mac Apps Using RubyCocoa Brian Marick The Pragmatic Bookshelf Raleigh,NorthCarolina Dallas,Texas Many of the designations used by manufacturers and sellers to distinguish their prod- uctsareclaimedastrademarks.Wherethosedesignationsappearinthisbook,andThe Pragmatic Programmers, LLC was aware of a trademark claim, the designations have been printed in initial capital letters or in all capitals. The Pragmatic Starter Kit, The PragmaticProgrammer,PragmaticProgramming,PragmaticBookshelfandthelinkingg devicearetrademarksofThePragmaticProgrammers,LLC. Every precaution was taken in the preparation of this book. However, the publisher assumesnoresponsibility for errorsor omissions,or for damagesthatmay result from theuseofinformation(includingprogramlistings)containedherein. Our Pragmatic courses, workshops, and other products can help you and your team create better software and have more fun. For more information, as well as the latest Pragmatictitles,pleasevisitusat http://www.pragprog.com Copyright©2009BrianMarick. Allrightsreserved. Nopartofthispublicationmaybereproduced,storedinaretrievalsystem,ortransmit- ted, in any form, or by any means, electronic,mechanical,photocopying, recording, or otherwise,withoutthepriorconsentofthepublisher. PrintedintheUnitedStatesofAmerica. ISBN-10:1-934356-19-0 ISBN-13:978-1-934356-19-7 Printedonacid-freepaper. P1.0printing,July2009 Version:2009-8-6 Contents 1 Introduction 11 1.1 What Is Cocoa? . . . . . . . . . . . . . . . . . . . . . . . 12 1.2 What Is RubyCocoa? . . . . . . . . . . . . . . . . . . . . 12 1.3 What’s It Like to Learn Cocoa Using Ruby? . . . . . . . 12 1.4 RubyCocoa? That’s So Last Year! . . . . . . . . . . . . . 13 1.5 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.6 Versions . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.7 Our Example App . . . . . . . . . . . . . . . . . . . . . . 16 1.8 Centuries of the Bookmaker’s Art: Scorned . . . . . . . 18 1.9 Some Terminology . . . . . . . . . . . . . . . . . . . . . 19 1.10 Service After the Sale . . . . . . . . . . . . . . . . . . . . 19 1.11 Solving Problems . . . . . . . . . . . . . . . . . . . . . . 19 1.12 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . 20 2 How Do We Get This Thing Started? 22 2.1 A Program That Prints . . . . . . . . . . . . . . . . . . . 23 2.2 Putting an Item in the Status Bar . . . . . . . . . . . . 26 2.3 Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.4 An Application Bundle . . . . . . . . . . . . . . . . . . . 31 2.5 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 35 I A First Realistic App 36 3 Working with Interface Builder and Xcode 37 3.1 The Basics . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.2 Creating and Editing Classes in Xcode . . . . . . . . . . 48 3.3 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . 55 3.4 SynchronizingInterface Builder and Xcode . . . . . . . 57 3.5 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . 58 3.6 Overriding Window Behavior with a Delegate . . . . . . 60 CONTENTS 6 3.7 Try This Yourself . . . . . . . . . . . . . . . . . . . . . . 61 3.8 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4 One Good App Observes Another 62 4.1 Notifications Within an App . . . . . . . . . . . . . . . . 62 4.2 Notifications Between Apps . . . . . . . . . . . . . . . . 67 4.3 The App to Fenestrate . . . . . . . . . . . . . . . . . . . 70 4.4 Putting Notification Handling Behind the GUI . . . . . 71 4.5 Reopening Objective-C Classes . . . . . . . . . . . . . . 73 4.6 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 73 II Reshaping Fenestra 75 5 A Better GUI 76 5.1 Toggle Buttons . . . . . . . . . . . . . . . . . . . . . . . 77 5.2 The Default Button . . . . . . . . . . . . . . . . . . . . . 78 5.3 Combo Box Items . . . . . . . . . . . . . . . . . . . . . . 79 5.4 The Initial First Responder . . . . . . . . . . . . . . . . 80 5.5 Try This Yourself . . . . . . . . . . . . . . . . . . . . . . 80 5.6 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6 Decoupled Controllers 82 6.1 Ignorant Objects . . . . . . . . . . . . . . . . . . . . . . 83 6.2 Extracting Subclasses . . . . . . . . . . . . . . . . . . . 85 6.3 Reacting to Button State . . . . . . . . . . . . . . . . . . 90 6.4 Using Nibs to Avoid Dependencies . . . . . . . . . . . . 90 6.5 Initializing Combo Boxes . . . . . . . . . . . . . . . . . . 92 6.6 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 93 7 Notifications Connect Decoupled Objects 94 7.1 Controllers . . . . . . . . . . . . . . . . . . . . . . . . . . 94 7.2 Translators and the Rising Tide of Ugliness . . . . . . . 96 7.3 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 99 8 More Expressive Code 100 8.1 A DSL for Notifications . . . . . . . . . . . . . . . . . . . 101 8.2 RubyCocoa Has Two Ways of Referringto Superclasses 103 8.3 Shorthand for Posting Notifications . . . . . . . . . . . 103 8.4 Try This Yourself . . . . . . . . . . . . . . . . . . . . . . 105 8.5 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Reporterratum thiscopyis(P1.0printing,July2009) CONTENTS 7 III Project Mechanics 108 9 Bundling Gems and Libraries with Your App 109 9.1 Manual Control . . . . . . . . . . . . . . . . . . . . . . . 110 9.2 Standaloneify . . . . . . . . . . . . . . . . . . . . . . . . 114 9.3 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 116 10 Project Organization, Builds, and Your Favorite Editor 117 10.1 Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 10.2 Using Xcode with Hierarchical Project Folders . . . . . 119 10.3 Running in Place . . . . . . . . . . . . . . . . . . . . . . 121 10.4 Building Without Xcode . . . . . . . . . . . . . . . . . . 121 10.5 Using InterfaceBuilder with Hierarchical Project Folders123 10.6 Startinga New Project . . . . . . . . . . . . . . . . . . . 124 10.7 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 125 IV Declarative Data Handling 126 11 Persistent User Preferences 127 11.1 The User PreferencesSystem . . . . . . . . . . . . . . . 128 11.2 Storing Custom Objects as Preferences . . . . . . . . . 131 11.3 Using Archived Objects. . . . . . . . . . . . . . . . . . . 139 11.4 Views Can Pull Data . . . . . . . . . . . . . . . . . . . . 143 11.5 Try This Yourself: A Sticky Window . . . . . . . . . . . 145 11.6 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 149 12 Creating a Preference Panel in a New Nib 150 12.1 Creating a Nib . . . . . . . . . . . . . . . . . . . . . . . . 151 12.2 Drawing the Panel . . . . . . . . . . . . . . . . . . . . . 153 12.3 Hooking the Panel to the App . . . . . . . . . . . . . . . 155 12.4 The Nib File’s Owner . . . . . . . . . . . . . . . . . . . . 158 12.5 IB’s First Responder Pseudo-Object . . . . . . . . . . . 159 12.6 Memory Leaks . . . . . . . . . . . . . . . . . . . . . . . . 160 12.7 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 161 13 Implementing a Preference Panel with Cocoa Bindings 162 13.1 Binding a Simple Value . . . . . . . . . . . . . . . . . . 162 13.2 Binding an Array of Hashes . . . . . . . . . . . . . . . . 166 13.3 Formatters . . . . . . . . . . . . . . . . . . . . . . . . . . 172 13.4 Value Transformers . . . . . . . . . . . . . . . . . . . . . 177 Reporterratum thiscopyis(P1.0printing,July2009) CONTENTS 8 13.5 Adding and Deleting Table Rows . . . . . . . . . . . . . 182 13.6 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 184 14 Setting Up Bindings with Code 185 14.1 Oh No! Terminology! . . . . . . . . . . . . . . . . . . . . 185 14.2 Using Rooted Keypaths in Code . . . . . . . . . . . . . . 189 14.3 Subclassing NSArrayController . . . . . . . . . . . . . . 189 14.4 bind_toObject_withKeyPath_options . . . . . . . . . . . 192 14.5 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 196 V Fun with Tables 197 15 Prologue: Folders and Tests 198 15.1 Disk Layout . . . . . . . . . . . . . . . . . . . . . . . . . 198 16 Selections and Editing 202 16.1 An Example of Creating Tests: The Add Method . . . . 202 16.2 Working with an Uncooperative Control . . . . . . . . . 212 16.3 Try This Yourself . . . . . . . . . . . . . . . . . . . . . . 220 16.4 Building Setup Methods . . . . . . . . . . . . . . . . . . 227 16.5 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 229 17 Buttons in Tables 230 17.1 Cells. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 17.2 Making the Change . . . . . . . . . . . . . . . . . . . . . 231 17.3 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 233 18 A Formatter with Two Wrinkles 234 18.1 The Formatter Code . . . . . . . . . . . . . . . . . . . . 235 18.2 Calling Methods That Take Reference Arguments . . . 237 18.3 Breaking Encapsulation in Tests . . . . . . . . . . . . . 240 18.4 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 242 19 Picking Files with Open Panels 243 19.1 NSOpenPanel . . . . . . . . . . . . . . . . . . . . . . . . 243 19.2 A Design for Using NSOpenPanel in Fenestra . . . . . . 246 19.3 Try This Yourself: PreferencesController Tests . . . . . 248 19.4 Try This Yourself: The NSOpenPanel Controller . . . . 256 19.5 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Reporterratum thiscopyis(P1.0printing,July2009) CONTENTS 9 20 Drag and Drop 261 20.1 How Drag and Drop Works . . . . . . . . . . . . . . . . 261 20.2 Designing the GUI . . . . . . . . . . . . . . . . . . . . . 263 20.3 A Template for the Solution . . . . . . . . . . . . . . . . 264 20.4 Utility Classes and Modules . . . . . . . . . . . . . . . . 265 20.5 Try This Yourself: Lively Dragging Info . . . . . . . . . . 268 20.6 Try This Yourself: Drag and Drop . . . . . . . . . . . . . 275 20.7 Does It Work? . . . . . . . . . . . . . . . . . . . . . . . . 280 20.8 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 281 21 Epilogue: A Wonderful World of Tests 282 21.1 Test-Driven Design . . . . . . . . . . . . . . . . . . . . . 282 21.2 To Learn More . . . . . . . . . . . . . . . . . . . . . . . . 285 VI Wrapping Up 286 22 Fit and Finish 287 22.1 Saving the Window Position Until the Next Launch . . 287 22.2 Tab Behavior. . . . . . . . . . . . . . . . . . . . . . . . . 288 22.3 Using NSMatrix to Organize Buttons . . . . . . . . . . . 289 22.4 Sizing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 22.5 Cleaning Up the Menu Bar . . . . . . . . . . . . . . . . 297 22.6 The About Window . . . . . . . . . . . . . . . . . . . . . 297 22.7 Changing the Application’s Name . . . . . . . . . . . . . 299 23 Adding Help 301 23.1 Help Book Basics . . . . . . . . . . . . . . . . . . . . . . 301 23.2 Creating a Help Book . . . . . . . . . . . . . . . . . . . . 302 23.3 Editing Pages . . . . . . . . . . . . . . . . . . . . . . . . 303 23.4 Hooking a Help Book into an App. . . . . . . . . . . . . 309 23.5 A Workflow for Creating Help Book Pages . . . . . . . . 311 23.6 Tooltips . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 24 Document-Based Applications 313 24.1 The Major Players . . . . . . . . . . . . . . . . . . . . . . 314 24.2 The Responder Chain. . . . . . . . . . . . . . . . . . . . 316 24.3 Creating a New Document . . . . . . . . . . . . . . . . . 319 24.4 Opening and Saving Documents . . . . . . . . . . . . . 328 24.5 Editing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 24.6 Learning More . . . . . . . . . . . . . . . . . . . . . . . . 333 Reporterratum thiscopyis(P1.0printing,July2009) CONTENTS 10 25 MacRuby 334 25.1 Getting MacRuby . . . . . . . . . . . . . . . . . . . . . . 337 25.2 MacRuby Basics . . . . . . . . . . . . . . . . . . . . . . . 337 25.3 A MacRuby Checklist . . . . . . . . . . . . . . . . . . . . 339 25.4 What Now? . . . . . . . . . . . . . . . . . . . . . . . . . . 343 VII Reference 344 26 The Objective-C Bridge and Bridge Metadata 345 26.1 An Unexpected Return Value . . . . . . . . . . . . . . . 345 26.2 What Information Can Be Found at Runtime? . . . . . 346 26.3 Supplementing Runtime Information . . . . . . . . . . 347 26.4 Our Own Private Metadata. . . . . . . . . . . . . . . . . 348 26.5 Finding Out More . . . . . . . . . . . . . . . . . . . . . . 349 27 The Underpinnings of Cocoa Bindings 350 27.1 Requirements . . . . . . . . . . . . . . . . . . . . . . . . 350 27.2 Our Goal . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 27.3 Declaring Observed Properties . . . . . . . . . . . . . . 352 27.4 Observing Changes . . . . . . . . . . . . . . . . . . . . . 353 27.5 Implementing bind_toObject_withKeyPath_options . . 355 27.6 Changing the Value of an Observed Key . . . . . . . . . 356 27.7 In Summary... . . . . . . . . . . . . . . . . . . . . . . . . 357 27.8 Postscript: Observing Changes to Collections . . . . . . 359 A Glossary 361 B Bibliography 372 Index 376 Reporterratum thiscopyis(P1.0printing,July2009)
Description: