• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/pyobjc-45/pyobjc/pyobjc-core-2.5.1/Doc/sphinx_build/html/_sources/tutorials/
1======================================
2Understanding existing PyObjC examples
3======================================
4
5Introduction
6------------
7
8This tutorial is aimed primarily at people with little or no background
9in Objective-C and Cocoa, and it will help you to understand PyObjC programs
10written by other people, such as the examples included with the distribution.
11This document is actually not a true tutorial: you do not get to build anything,
12only read and examine things.
13
14It is strongly suggested that you first do the
15:doc:`Creating your first PyObjC application <firstapp>` tutorial to get some hands-on
16experience with PyObjC, Cocoa and especially Interface Builder.
17
18Model-View-Controller
19---------------------
20
21If you have used another GUI toolkit in the past it is essential that
22you understand that Cocoa is different.  For this once this isn't
23marketing-speak: Cocoa is inherently different from common toolkits such as
24Tk, wxWindows, Carbon, MFC, etc.  Apple's documentation explains this, but
25such introductory text is often skipped.  It is a good idea to refer back to
26`Application Architecture`__ after reading this section.  If you want, you can
27write code that does not follow the Model-View-Controller paradigm, but you
28would be on your own.  Cocoa and Interface Builder are designed to suit this
29model.
30
31.. __: http://developer.apple.com/documentation/Cocoa/Conceptual/AppArchitecture/index.html
32
33Cocoa is built on the Model-View-Controller paradigm (MVC).  What this means
34is that the application code should be split into three parts:
35
36-   The *Model* is the storage of and operations on the data.  The model
37    could be as complicated as a large database, or as simple as a
38    currency conversion function that only knows how to multiply two floating
39    point numbers, as in the Currency Converter application built in the first
40    tutorial.
41
42-   The *View* is what the user sees and interacts with on-screen.
43
44-   The *Controller* is the glue that binds the Model and the View together.
45    In the Currency Converter tutorial it is the callback that is triggered
46    when the user presses the "Convert" button, which gets the data from the
47    "amount" and "rate" fields of the View, passes them to the Model for
48    computation and sends the result back to the View.
49  
50To summarize: the Model knows nothing about the user, the View knows nothing
51about the data and operations, and the Controller only knows how to relate
52the Model and the View.  For really tiny applications, such as the currency
53converter, it may be tempting to do away with the Model and simply put that
54code in the Controller.  You probably shouldn't do this, as it can make
55your code harder to read since it will be a mix of algorithms and glue code,
56however there is no technical limitation that prevents you from doing this.
57If you do combine the functionality of the model and controller, it is
58customary to name it as if it represented the document (without "Controller").
59Note that the MVC paradigm is not specific to Cocoa and can be used with almost
60any GUI toolkit, but Cocoa is explicitly designed for this paradigm.
61
62You should have an MVC trio for every distinct unit of information in your
63program.  In case of a simple dialog-style application such as Currency
64Converter you will have one such trio.  Most applications, however, will have
65at least two: one for the application itself and one for the "documents" the
66application handles.  These may be real documents (i.e. files), but a document
67can be more abstract.  For example, if your application does scientific
68simulations that run in separate windows, each simulation could be a document.
69
70The NIB file
71------------
72
73Cocoa and Interface Builder strongly encourage you to use a NIB file
74per MVC trio.   You should follow this encouragement unless you are sure
75that you know what you are doing.
76
77This brings us to the second big difference between Cocoa and other GUI
78toolkits: almost all of the boilerplate code is replaced by the NIB.
79The source of Cocoa programs that do little work, especially example programs,
80will typically be much shorter than the equivalent with other toolkits.
81
82The NIB file is *not* a description of dialogs and menus and buttons, as you 
83would get out of interface-builders for other toolkits.  A NIB file is more:
84it contains a archived object graph that represents the GUI, conceptually
85similar to a pickle in Python.  You tell Interface Builder
86about all the relevant classes in your application, the instances you
87want to create from those classes, and how the classes should connect to
88each other.  Interface Builder the actually instantiates the classes, makes
89all the connections and at that point freezes and stores the whole lot.
90
91Unarchival of a NIB happens in two phases.  The objects are restored using the
92``NSCoding`` protocol (``initWithCoder:`` is similar to ``__setstate__`` of
93Python's ``pickle`` protocol), and then each object is sent an
94``awakeFromNib:`` message so that they may do any initialization that depends
95on a fully restored object graph (``pickle`` does not have this functionality
96built-in).
97
98The section above explains a lot of the strangeness in AppKit-based PyObjC
99applications:
100
101*   Windows and dialogs are typically not explicitly created, because they were
102    instantiated by the NIB.
103
104*   Initialization is not always done in ``__init__`` or equivalent, because
105    the object graph may not be completely unarchived until the first
106    ``awakeFromNib:`` is called.
107
108*   Attributes that reference other objects are not typically set explicitly,
109    but are done by the NIB file during unarchival.
110	
111This also explains why you want separate NIB files for each MVC trio:
112the objects and classes in a NIB file are all unarchived together.  In other
113words, if you had created your document window in your application NIB
114(even if you set it to "hidden" initially so it does not show up) it would
115become very difficult to create a second window for a new document.
116
117If you think about the consequences of this section for a while it will
118become clear why all the boilerplate code is missing from Cocoa applications:
119you don't need it.  Like the output of other gui-builders, a NIB usually
120contains enough information to recreate the view objects, but a NIB can also
121contain a large proportion of the setup for your Model and Controller
122functionality.  This is especially true when using `Cocoa Bindings`__.
123
124.. __: http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/
125
126Delegates
127---------
128
129If you are familiar with other object-oriented GUI toolkits such as MFC
130another thing to notice is that Cocoa applications often use a *delegate*
131object where other toolkits would use a subclass.  For example: it is not
132common to use your own subclass of ``NSApplication`` for the main application
133object.  ``NSApplication`` objects have a helper called its ``delegate``.
134The application object will attempt to inform its delegate many interesting
135events, and the delegate implements only the methods for the events it is
136interested in.
137
138For example, the method ``applicationShouldTerminate:`` of the delegate
139is called just before the application quits, and it has a chance to return
140``NO`` if it is not appropriate to quit just yet.
141
142Examining a NIB file
143--------------------
144
145Let us examine the final NIB of the Currency Converter tutorial with this in
146mind.  If you open it and look at the main window (titled "MainMenu.nib")
147and select the "Instances" pane you should see six objects.  Two of these
148have greyed-out names ("File's Owner" and "First Responder"), these are present
149in every nib can not be changed.  The "File's Owner" is either the Controller
150or the combined Model-Controller object, and is specified by the application
151when it loads the NIB.  For the main nib, which is loaded automatically by
152``NSApplicationMain`` or ``PyObjCTools.AppHelper.runEventLoop``, this will be
153the instance of ``NSApplication``.  Currency Converter is not a document-based
154application, so the MVC trio for the conversion window are in here too.  These
155are named ``Converter``, ``Window`` and ``ConverterController`` respectively.
156
157Let us have a look at the ``ConverterController`` object by double clicking it.
158The "MainMenu.nib" window goes to the "Classes" tab, and an info window shows
159up.  In the "MainMenu.nib" window the ``ConverterController`` class is
160selected, and you can see it is a subclass of ``NSObject``.  Having the same
161name for the class and the instance is common in Cocoa programs, the main
162exception being the File Owner object.
163
164The info window shows more information on the ``ConverterController`` class.
165It should pop open to the "attributes" page.  In the "Outlets" tab you see that
166instances of this class have four attributes, ``converter``, ``rateField``,
167``dollarField`` and ``totalField``.  In any instance of ``ConverterController``
168you can connect these to other objects, as we shall see below.  The "Actions"
169tab shows that there are two methods ``convert:`` and ``invertRate:``, and
170again you can arrange for these to be called on instances of your
171``ConverterController`` on certain events by making connections.
172
173So let us now look at the connections for our ``ConverterController``
174*instance*.  Select the "Instances" tab in the main window, select
175``ConverterController`` and set the info window to show "Connections".  You 
176now see all the outlets defined in the class.  Select one, and in the lower 
177half of the info window you will see which object it connects to.  Moreover, a 
178blue line will also link the object representations in the main window and
179in the dialog preview window.
180
181Finding out who calls your ``convert:`` method is more difficult, though, with
182this view.  But, if you select the "Convert" button in the dialog you will see
183that its ``target`` action will go to the ``ConverterController.convert_``
184method.
185
186Luckily there is a way to find such incoming connections without reverting to
187guessing.  For instance, you will be hard put to find who, if anyone, calls 
188``ConverterController.invertRate_``.  The solution: go to the "MainMenu.nib"
189window and look at the top of the vertical scrollbar.  There are two little
190icons there, one with lines and one with squares, with the squares being
191highlighted.  Press it.  The view will change to a scrollable list with objects 
192in the left column and an indication of connections in the right column.  You
193can now see our ConverterController object has four outgoing connections (the
194ones we found earlier) and two incoming connections.  Click on the incoming
195connections icon.  The view will change again and ConverterController will
196probably scroll out of sight.  Locate it, and see that there are two lines
197going out of the ConverterController object.  One goes to ``NSButton(Convert)``
198and is labeled ``convert:``, we knew about that already.  The other one goes to
199an object ``NSMenuItem(Invert Exchange Rate)`` and is labeled ``invertRate:``,
200so that is where calls to ``invertRate:`` come from.  And if you look at where
201this ``NSMenuItem`` sits in the object hierarchy you find that it is an entry
202in the "Edit" menu in the menubar.
203
204Examining an Apple example
205--------------------------
206
207This section remains to be written.  Contributions will be gratefully accepted
208:-)
209