Source

pyobjc / Doc / tutorial_reading.html

Diff from to

Doc/tutorial_reading.html

 <h2>Understanding existing PyObjC examples</h2>
 <h2><a name="introduction">Introduction</a></h2>
 <p>This tutorial is aimed primarily at people with little or no background
-in ObjC and Cocoa, and it will help you to understand PyObjC programs
+in Objective-C and Cocoa, and it will help you to understand PyObjC programs
 written by other people, such as the examples included with the distribution.
 This document is actually not a true tutorial: you do not get to build anything,
 only read and examine things.</p>
 experience with PyObjC, Cocoa and especially Interface Builder.</p>
 <h2><a name="model-view-controller">Model-View-Controller</a></h2>
 <p>If you have used another GUI toolkit in the past it is essential that
-you understand that Cocoa is different. For this once this isn't marketing-speak:
-Cocoa is inherently different from common toolkits such as Tk, wxWindows,
-Carbon, win32 and all the other popular ones. Apple's documentation explains this,
-but in the introductory sections that are often quickly glanced over. It is a
-good idea to refer back to <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/AppArchitecture/index.html">Application Architecture</a> after reading this section. If you really
-want you can break out of the architecture sketched in this section, but
-then you are on your own, really: Cocoa and Interface Builder really
-expect you to follow this model.</p>
-<p>Cocoa is built on the Model-View-Controller paradigm (MVC). What this means
-is that the application code is going to be split into three parts:</p>
+you understand that Cocoa is different.  For this once this isn't
+marketing-speak: Cocoa is inherently different from common toolkits such as
+Tk, wxWindows, Carbon, MFC, etc.  Apple's documentation explains this, but
+such introductory text is often skipped.  It is a good idea to refer back to
+<a href="http://developer.apple.com/documentation/Cocoa/Conceptual/AppArchitecture/index.html">Application Architecture</a> after reading this section.  If you want, you can
+write code that does not follow the Model-View-Controller paradigm, but you
+would be on your own.  Cocoa and Interface Builder are designed to suit this
+model.</p>
+<p>Cocoa is built on the Model-View-Controller paradigm (MVC).  What this means
+is that the application code should be split into three parts:</p>
 <ul>
-<li>The <i>Model</i> is the actual data you are manipulating, plus the operations
-on it. It can be as big as a complete database engine or a scientific
-simulation, or as small as a routine that multiplies one floating point
-number (an amount of money in currency A) by another (the conversion
-rate from currency A to currency B), as in the currency converter
-application you built in the first tutorial.</li>
-<li>The <i>View</i> is what the user sees on-screen, plus his or her interaction
-with it.</li>
-<li>The <i>Controller</i> is the glue that binds these two together. In the
-currency converter example, it is the code that gets called when the user
-presses the &quot;Convert&quot; button, whereupon it gets the data from the &quot;amount&quot;
-and &quot;rate&quot; fields from the View, passes them to the Model for computation
-and sends the result back to the View.</li>
+<li>The <i>Model</i> is the storage of and operations on the data.  The model
+could be as complicated as a large database, or as simple as a
+currency conversion function that only knows how to multiply two floating
+point numbers, as in the Currency Converter application built in the first
+tutorial.</li>
+<li>The <i>View</i> is what the user sees and interacts with on-screen.</li>
+<li>The <i>Controller</i> is the glue that binds the Model and the View together.
+In the Currency Converter tutorial it is the callback that is triggered
+when the user presses the &quot;Convert&quot; button, which gets the data from the
+&quot;amount&quot; and &quot;rate&quot; fields of the View, passes them to the Model for
+computation and sends the result back to the View.</li>
 </ul>
-<p>To summarize: the Model knows nothing about dialogs and buttons and such,
-the View knows nothing about data and algorithms and the Controller ties it
-all together. For really tiny applications, such as the currency converter,
-you could do away with the Model and simply put that code right in the
-Controller. MVC purists say you should not do this, and it can indeed
-make your code harder to read (because the Controller will contain a mix
-of algorithms and glue code), but there is no architectural reason that
-stops you. If you combine the two classes it is customary to use the name
-you would use for your document class, so without &quot;Controller&quot;. Note that
-MVC is not specific to Cocoa, you can use the paradigm with any GUI toolkit,
-but Cocoa really steers you towards it.</p>
+<p>To summarize: the Model knows nothing about the user, the View knows nothing
+about the data and operations, and the Controller only knows how to relate
+the Model and the View.  For really tiny applications, such as the currency
+converter, it may be tempting to do away with the Model and simply put that
+code in the Controller.  You probably shouldn't do this, as it can make
+your code harder to read since it will be a mix of algorithms and glue code,
+however there is no technical limitation that prevents you from doing this.
+If you do combine the functionality of the model and controller, it is
+customary to name it as if it represented the document (without &quot;Controller&quot;).
+Note that the MVC paradigm is not specific to Cocoa and can be used with almost
+any GUI toolkit, but Cocoa is explicitly designed for this paradigm.</p>
 <p>You should have an MVC trio for every distinct unit of information in your
-program. In case of a simple dialog-style application such as Currency Converter
-you will have one such trio. Most applications, however, will have at least
+program.  In case of a simple dialog-style application such as Currency Converter
+you will have one such trio.  Most applications, however, will have at least
 two: one for the application itself and one for the &quot;documents&quot; the application
-handles. These may be real documents (i.e. files), but they could also be more
-abstract. If your application does scientific simulation and you want to be
-able to open two simulation windows at the same time you should use the
-document model.</p>
+handles.  These may be real documents (i.e. files), but a document can be more
+abstract.  For example, if your application does scientific simulations that
+run in separate windows, each simulation could be a document.</p>
 <h2><a name="the-nib-file">The NIB file</a></h2>
 <p>Cocoa and Interface Builder strongly encourage you to use a NIB file
-per MVC trio. Again: follow this encouragement unless you are sure what
-you are doing.</p>
+per MVC trio.   You should follow this encouragement unless you are sure
+that you know what you are doing.</p>
 <p>This brings us to the second big difference between Cocoa and other GUI
-toolkits: almost all the boilerplate code is in the NIB, and therefore
-the source of Cocoa programs, especially example programs that do little
-real work, will look stunningly small if you are familiar with, say,
-Tkinter.</p>
+toolkits: almost all of the boilerplate code is replaced by the NIB.
+The source of Cocoa programs that do little work, especially example programs,
+will typically be much shorter than the equivalent with other toolkits.</p>
 <p>The NIB file is <i>not</i> a description of dialogs and menus and buttons, as you 
-would get out of interface-builders for other toolkits. There, at startup
-something will read the description, create the buttons and hand the finished
-dialog to your code. A NIB file is more: it contains a complete set of frozen
-objects, conceptually similar to a pickle in Python. You tell Interface Builder
-knows about all the relevant classes in your application, the instances you
+would get out of interface-builders for other toolkits.  A NIB file is more:
+it contains a archived object graph that represents the GUI, conceptually
+similar to a pickle in Python.  You tell Interface Builder
+about all the relevant classes in your application, the instances you
 want to create from those classes, and how the classes should connect to
-each other. Interface Builder the actually instantiates the classes, makes
+each other.  Interface Builder the actually instantiates the classes, makes
 all the connections and at that point freezes and stores the whole lot.</p>
-<p>When your NIB is read the objects are thawed, the connections restored and
-the objects get a running start. Again, this is conceptually similar
-to how unpickling works.</p>
-<blockquote>
-<p>The section above explains a lot of the strangeness in PyObjC
-programs: why you don't create windows and other dialogs (they
-already exist); why you shouldn't do initialization in <code><span>__init__</span></code>
-(because it will be called at some undefined point in time, while
-reading the NIB) but in <code><span>awakeFromNib:</span></code> in stead; why you don't
-have to create and initialize the attributes that tie your
-objects together (they are already tied together).</p>
-<p><code><span>awakeFromNib:</span></code> is very similar in nature to <code><span>__setstate__</span></code> for
-a pickled Python object, but it happens after all objects have been
-unserialized.</p>
-</blockquote>
+<p>Unarchival of a NIB happens in two phases.  The objects are restored using the
+<code><span>NSCoding</span></code> protocol (<code><span>initWithCoder:</span></code> is similar to <code><span>__setstate__</span></code> of
+Python's <code><span>pickle</span></code> protocol), and then each object is sent an
+<code><span>awakeFromNib:</span></code> message so that they may do any initialization that depends
+on a fully restored object graph (<code><span>pickle</span></code> does not have this functionality
+built-in).</p>
+<p>The section above explains a lot of the strangeness in AppKit-based PyObjC
+applications:</p>
+<ul>
+<li>Windows and dialogs are typically not explicitly created, because they were
+instantiated by the NIB.</li>
+<li>Initialization is not always done in <code><span>__init__</span></code> or equivalent, because
+the object graph may not be completely unarchived until the first
+<code><span>awakeFromNib:</span></code> is called.</li>
+<li>Attributes that reference other objects are not typically set explicitly,
+but are done by the NIB file during unarchival.</li>
+</ul>
 <p>This also explains why you want separate NIB files for each MVC trio:
-the objects and classes in a NIB file are all unpickled together. In other
-words: if you had created your document window in your application NIB
+the objects and classes in a NIB file are all unarchived together.  In other
+words, if you had created your document window in your application NIB
 (even if you set it to &quot;hidden&quot; initially so it does not show up) it would
 become very difficult to create a second window for a new document.</p>
 <p>If you think about the consequences of this section for a while it will
 become clear why all the boilerplate code is missing from Cocoa applications:
-you don't need it. The NIB file usually contains all of the things that need to
-be done for the Views objects, as is often the case with other gui-builders.
-But in addition the NIB also contains a large proportion of your Model
-functionality: creating the View and Controller objects and tying the
-lot together.</p>
+you don't need it.  Like the output of other gui-builders, a NIB usually
+contains enough information to recreate the view objects, but a NIB can also
+contain a large proportion of the setup for your Model and Controller
+functionality.  This is especially true when using <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/">Cocoa Bindings</a>.</p>
 <h2><a name="delegates">Delegates</a></h2>
 <p>If you are familiar with other object-oriented GUI toolkits such as MFC
 another thing to notice is that Cocoa applications often use a <i>delegate</i>
-object where other toolkits would use a subclass. For example: it is not
-common to use your own subclass in stead of <code><span>NSApplication</span></code> for the
-main application object. In stead, <code><span>NSApplication</span></code> objects have a helper
-called its <code><span>delegate</span></code>. The application object will attempt to inform
-its delegate of all sorts of things happening, and the delegate implements
-only the methods for the events in which it is interested.</p>
-<p>For example, the method <code><span>applicationShouldTerminate:</span></code> on the delegate
+object where other toolkits would use a subclass.  For example: it is not
+common to use your own subclass of <code><span>NSApplication</span></code> for the main application
+object.  <code><span>NSApplication</span></code> objects have a helper called its <code><span>delegate</span></code>.
+The application object will attempt to inform its delegate many interesting
+events, and the delegate implements only the methods for the events it is
+interested in.</p>
+<p>For example, the method <code><span>applicationShouldTerminate:</span></code> of the delegate
 is called just before the application quits, and it has a chance to return
-<code><span>NO</span></code> if you don't want to quit just yet.</p>
+<code><span>NO</span></code> if it is not appropriate to quit just yet.</p>
 <h2><a name="examining-a-nib-file">Examining a NIB file</a></h2>
-<p>Let us examine the final NIB of the Currency Converter tutorial with this in mind.
-If you open it and look at the main window (the one with &quot;MainMenu.nib&quot; as
-its title) and select the &quot;Instances&quot; pane you see six objects. Two of these
-have a greyed-out name (&quot;File's Owner&quot; and &quot;First Responder&quot;): these have
-been created for you by Apple. The other four are created by you. Actually:
-&quot;Main Menu&quot; was created by Apple as a convenience, but you are free to modify
-it. The &quot;File's Owner&quot; is either the Controller or the combined Model-Controller
-object, in this case it is the application itself, an instance of <code><span>NSApplication</span></code>.
-Because this application is not a document-based application the MVC trio
-for the actual conversion window are in here too: <code><span>Converter</span></code>, <code><span>Window</span></code> and
-<code><span>ConverterController</span></code> respectively.</p>
+<p>Let us examine the final NIB of the Currency Converter tutorial with this in
+mind.  If you open it and look at the main window (titled &quot;MainMenu.nib&quot;)
+and select the &quot;Instances&quot; pane you should see six objects.  Two of these
+have greyed-out names (&quot;File's Owner&quot; and &quot;First Responder&quot;), these are present
+in every nib can not be changed.  The &quot;File's Owner&quot; is either the Controller
+or the combined Model-Controller object, and is specified by the application
+when it loads the NIB.  For the main nib, which is loaded automatically by
+<code><span>NSApplicationMain</span></code> or <code><span>PyObjCTools.AppHelper.runEventLoop</span></code>, this will be
+the instance of <code><span>NSApplication</span></code>.  Currency Converter is not a document-based
+application, so the MVC trio for the conversion window are in here too.  These
+are named <code><span>Converter</span></code>, <code><span>Window</span></code> and <code><span>ConverterController</span></code> respectively.</p>
 <p>Let us have a look at the <code><span>ConverterController</span></code> object by double clicking it.
 The &quot;MainMenu.nib&quot; window goes to the &quot;Classes&quot; tab, and an info window shows up.
 In the &quot;MainMenu.nib&quot; window the <code><span>ConverterController</span></code> class is selected, and
-you can see it is a subclass of <code><span>NSObject</span></code>. Having the same name for the class
+you can see it is a subclass of <code><span>NSObject</span></code>.  Having the same name for the class
 and the instance is common in Cocoa programs, the main exception being the File
 Owner object.</p>
-<p>The info window shows more information on the <code><span>ConverterController</span></code> class. It
-should pop open to the &quot;attributes&quot; page. In the &quot;Outlets&quot; tab you see that instances
+<p>The info window shows more information on the <code><span>ConverterController</span></code> class.  It
+should pop open to the &quot;attributes&quot; page.  In the &quot;Outlets&quot; tab you see that instances
 of this class have four attributes, <code><span>converter</span></code>, <code><span>rateField</span></code>, <code><span>dollarField</span></code>
-and <code><span>totalField</span></code>. In any instance of <code><span>ConverterController</span></code> you can connect these
-to other objects, as we shall see below. The &quot;Actions&quot; tab shows that there are two
+and <code><span>totalField</span></code>.  In any instance of <code><span>ConverterController</span></code> you can connect these
+to other objects, as we shall see below.  The &quot;Actions&quot; tab shows that there are two
 methods <code><span>convert:</span></code> and <code><span>invertRate:</span></code>, and again you can arrange for these to
 be called on instances of your <code><span>ConverterController</span></code> on certain events by
 making connections.</p>
-<p>So let us now look at the connections for our <code><span>ConverterController</span></code> <i>instance</i>. Select
+<p>So let us now look at the connections for our <code><span>ConverterController</span></code> <i>instance</i>.  Select
 the &quot;Instances&quot; tab in the main window, select <code><span>ConverterController</span></code> and set the info
-window to show &quot;Connections&quot;. You now see all the outlets defined in the class.
+window to show &quot;Connections&quot;.  You now see all the outlets defined in the class.
 Select one, and in the lower half of the info window you will see which object it connects
-to. Moreover, a blue line will also link the object representations in the main window and
+to.  Moreover, a blue line will also link the object representations in the main window and
 in the dialog preview window.</p>
 <p>Finding out who calls your <code><span>convert:</span></code> method is more difficult, though, with this view.
 But, if you select the &quot;Convert&quot; button in the dialog you will see that its <code><span>target</span></code>
-action will go to the <code><span>ConverterController.convert:</span></code> method.</p>
+action will go to the <code><span>ConverterController.convert_</span></code> method.</p>
 <p>Luckily there is a way to find such incoming connections without reverting to guessing.
 For instance, you will be hard put to find who, if anyone, calls 
-<code><span>ConverterController.invertRate:</span></code>. The solution: go to the &quot;MainMenu.nib&quot; window and
-look at the top of the vertical scrollbar. There are two little icons there, one with
-lines and one with squares, with the squares being highlighted. Press it. The view will change
+<code><span>ConverterController.invertRate_</span></code>.  The solution: go to the &quot;MainMenu.nib&quot; window and
+look at the top of the vertical scrollbar.  There are two little icons there, one with
+lines and one with squares, with the squares being highlighted.  Press it.  The view will change
 to a scrollable list with objects in the left column and an indication of connections
-in the right column. You can now see our ConverterController object has four
-outgoing connections (the ones we found earlier) and two incoming connections. Click
-on the incoming connections icon. The view will change again and ConverterController
-will probably scroll out of sight. Locate it, and see that there are two lines
-going out of the ConverterController object. One goes to <code><span>NSButton(Convert)</span></code>
-and is labeled <code><span>convert:</span></code>, we knew about that already. The other one goes to an
+in the right column.  You can now see our ConverterController object has four
+outgoing connections (the ones we found earlier) and two incoming connections.  Click
+on the incoming connections icon.  The view will change again and ConverterController
+will probably scroll out of sight.  Locate it, and see that there are two lines
+going out of the ConverterController object.  One goes to <code><span>NSButton(Convert)</span></code>
+and is labeled <code><span>convert:</span></code>, we knew about that already.  The other one goes to an
 object <code><span>NSMenuItem(Invert</span> <span>Exchange</span> <span>Rate)</span></code> and is labeled <code><span>invertRate:</span></code>, so that
-is where calls to <code><span>invertRate:</span></code> come from. And if you look at where this
+is where calls to <code><span>invertRate:</span></code> come from.  And if you look at where this
 <code><span>NSMenuItem</span></code> sits in the object hierarchy you find that it is an entry in the
 &quot;Edit&quot; menu in the menubar.</p>
 <h2><a name="examining-an-apple-example">Examining an Apple example</a></h2>
-<p>This section remains to be written. Contributions will be gratefully accepted:-)</p>
+<p>This section remains to be written.  Contributions will be gratefully accepted :-)</p>
 </body>
 </html>