Source

pyobjc / Doc / intro.html

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>
An introduction to PyObjC</title>
<title>
Contents</title>
</head>
<body>
<h2>An introduction to PyObjC</h2>
<!-- :authors: Ronald Oussoren, Bob Ippolito
:contact: pyobjc-dev@lists.sourceforge.net
:URL: http://pyobjc.sourceforge.net/
:copyright: 2003-2005 The PyObjC Project -->
<h2>Contents</h2>
<ul>
<li><a href="#preface" id="id6" name="id6">Preface</a></li>
<li><a href="#objective-c-for-pyobjc-users" id="id7" name="id7">Objective-C for PyObjC users</a></li>
<li><a href="#overview-of-the-bridge" id="id8" name="id8">Overview of the bridge</a><ul>
<li><a href="#classes" id="id9" name="id9">Classes</a></li>
<li><a href="#messages-and-functions" id="id10" name="id10">Messages and Functions</a></li>
<li><a href="#reference-counting" id="id11" name="id11">Reference counting</a></li>
<li><a href="#informal-protocols" id="id12" name="id12">(Informal) protocols</a></li>
<li><a href="#cocoa-bindings" id="id13" name="id13">Cocoa Bindings</a></li>
<li><a href="#categories" id="id14" name="id14">Categories</a></li>
</ul>
</li>
<li><a href="#cocoa-for-python-programmers" id="id15" name="id15">Cocoa for Python programmers</a></li>
<li><a href="#notes-on-specific-tasks" id="id16" name="id16">Notes on specific tasks</a><ul>
<li><a href="#working-with-threads" id="id17" name="id17">Working with threads</a></li>
<li><a href="#finalizers" id="id18" name="id18">Finalizers</a></li>
<li><a href="#copying" id="id19" name="id19">Copying</a></li>
</ul>
</li>
<li><a href="#building-applications" id="id20" name="id20">Building applications</a><ul>
<li><a href="#py2app-setup-py" id="id21" name="id21">&quot;py2app&quot; :  setup.py</a></li>
<li><a href="#ide-approach-xcode" id="id22" name="id22">&quot;IDE approach&quot; : Xcode</a></li>
</ul>
</li>
</ul>
<h2><a href="#id6" name="preface">Preface</a></h2>
<p>PyObjC is a bridge between Python and Objective-C.  It allows you to write 
Python scripts that use and extend existing Objective-C class libraries, 
most importantly the <a href="http://developer.apple.com/referencelibrary/API_Fundamentals/Cocoa-api-date.html">Cocoa libraries</a> by <a href="http://www.apple.com/">Apple</a>.</p>
<p>This document describes how to use Objective-C class libraries from Python
scripts and how to interpret the documentation of those libraries from the 
point of view of a Python programmer.</p>
<h2><a href="#id7" name="objective-c-for-pyobjc-users">Objective-C for PyObjC users</a></h2>
<p>It is recommended that you take the time to understand a little bit about
Objective-C before jumping into PyObjC development.  The class libraries
that you will be using from Cocoa are not documented in Python, and their
documentation will be confusing without a grasp on the semantics and syntax
of Objective-C.</p>
<p>Objective-C is an object-oriented programming language implemented as a
superset of C that borrows heavily in concept and syntax from Smalltalk.
of C and borrows heavily from Smalltalk.  It features single inheritance with
dynamic dispatch and (in theory) multiple root classes.  This is basically the
same as Python with single inheritance.</p>
<p>An important difference between Python and Objective-C is that the latter is
not a pure object-oriented language.  Some values are not objects, but values
of plain C types, such as <code><span>int</span></code> and <code><span>double</span></code>.  These basic C types can 
be used as the types of arguments and the return value of methods.</p>
<p>Object allocation and initialization are explicit and separate actions in 
Objective-C. The former is done by the class-method <code><span>alloc</span></code>, while the
latter is done by instance methods whose name customarily starts with <code><span>init</span></code>.</p>
<p>Objective-C code looks just like plain C code, with some easily recognizable
Smalltalk-like extensions for the object-oriented parts of the language.  An
example class declaration (usually found in <code><span>.h</span></code> files) and implementation
(usually found in <code><span>.m</span></code> files) are listed below.  Class declarations are easily
recognized as blocks of code between <code><span>@interface</span></code> and <code><span>@end</span></code>, and similarly
the implementation is between <code><span>@implementation</span></code> and <code><span>@end</span></code>.  An expression
enclosed in brackets in Objective-C is called a message, and is the equivalent
to an instance method invocation in Python.  For example, this Objective-C code:</p>
<pre>
[aMutableArray addObject:@&quot;constant string&quot;];
</pre>
<p>Is equivalent in intent to the following in Python:</p>
<pre>
aList.append(u&quot;constant string&quot;)
</pre>
<p>Objective-C messages have three components: a target, a selector, and zero or
more arguments.  The target, <code><span>aMutableArray</span></code>, is the object or class
receiving the message.  The selector, <code><span>addObject:</span></code> uniquely identifies the
kind of message that is being sent.  Finally, the arguments,
<code><span>@&quot;constant</span> <span>string&quot;</span></code> are used by the implementation of the method upon
receipt of the message.  The syntax of Objective-C message dispatch is
deceptively similar to keyword arguments in Python, but they are actually
quite different.  Objective-C messages can not have default arguments, and all
arguments are passed in a specific order.  The components of a selector may not
be reordered.  Syntactically, one argument must be interleaved at every colon in
the selector.  The message:</p>
<pre>
[anArray indexOfObject:someObject inRange:someRange]
</pre>
<dl>
<dt>Target:</dt>
<dd><p><code><span>anArray</span></code></p>
</dd>
<dt>Selector:</dt>
<dd><p><code><span>indexOfObject:inRange:</span></code></p>
</dd>
<dt>Arguments:</dt>
<dd><p><code><span>someObject</span></code>, <code><span>someRange</span></code></p>
</dd>
</dl>
<p>As you'll see later, the straightforward translation of such a message to
Python is:</p>
<pre>
anArray.indexOfObject_inRange_(someObject, someRange)
</pre>
<p>This may be awkward and &quot;unpythonic&quot; at first, however this syntax is necessary
to preserve the semantics of Objective-C message dispatch.</p>
<p>A class declaration:</p>
<pre>
@interface MyClass : MySuperClass
{
    id  anInstanceVariable;
    int anotherInstanceVariable;
}

// A class method that returns an initialized instance of this class.
// Similar to an implementation of __call__ on the metaclass.
+instanceWithObject:(id)anObject andInteger:(int)anInteger;

// An instance method, the designated initializer for MyClass.
// Similar to an implementation of __new__ on MyClass.
-initWithObject:(id)anObject andInteger:(int)anInteger;

// An accessor, instance variables (attributes) are in a separate
// namespace and are considered &quot;private&quot; in Objective-C.  Conventionally,
// there is nothing similar to this in Python.
-(int)anotherInstanceVariable;
@end
</pre>
<p>A class implementation:</p>
<pre>
@implementation MyClass

// Note that a type is not declared for the return value.  Undeclared types
// are assumed to be &quot;id&quot;, which means any kind of instance.
+instanceWithObject:(id)anObject andInteger:(int)anInteger
{
    // 1. Create an instance of MyClass.
    // 2. Initialize it with its designated initializer
    //    &quot;initWithObject:andInteger:&quot;.
    // 3. Autorelease it, so that it does not leak memory.
    // 4. Return the new instance.
    //
    // NOTE:
    //   By convention,initializers (such as +new, -init, -copy)
    //   are the only methods that should return retained objects.
    //
    // NOTE:
    //   Since this is a class method, &quot;self&quot; refers to the class!
    //
    // Very roughly similar to:
    //   return self.__new__(anObject, anInteger)
    return [[[self alloc] initWithObject:anObject andInteger:anInteger] autorelease];
}

// Note that a type is not declared for the return value.  Undeclared types
// are assumed to be &quot;id&quot;, which means any kind of instance.
-initWithObject:(id)anObject andInteger:(int)anInteger
{
    // Call the designated initializer of the superclass.
    // Similar to:
    //     self = super(MyClass, self).__new__()
    self = [super init];

    // Bail if initialization of the superclass failed.
    // Similar to:
    //     if self is None:
    //         return None
    if (!self) {
        return nil;
    }

    // Set the instance variable (attribute).  The argument must be
    // retained, since it will persist as long as the instance does.
    // Similar to:
    //     # Reference counting is automatic in Python
    //     self.anInstanceVariable = anObject
    anInstanceVariable = [anObject retain];

    // Set the other instance variable.  Note that since anInteger is
    // a primitive &quot;C&quot; type, not an object, no reference counting takes
    // place.
    // Similar to:
    //     # Everything is an object in Python
    //     self.anotherInstanceVariable = anInteger
    anotherInstanceVariable = anInteger;

    // Like __new__ in Python, initializers in Objective-C must
    // explicitly return self.  Note that this is different from
    // __init__.
    // Similar to:
    //     return self
    return self;
}
    

// an accessor, instance variables (attributes) are in a separate
// namespace and are considered &quot;private&quot;
-(int)anotherInstanceVariable
{
    return anotherInstanceVariable;
}

// Since objects were retained as instance variables on this object,
// they must be freed when the object is.  This is similar to an
// implementation of __del__ in Python.  Since Objective-C has no
// cyclic garbage collection, this isn't discouraged like it is in
// Python.
-(void)dealloc
{
    // Very roughly similar to:
    //     del self.instanceVariable
    [instanceVariable release];

    // Very roughly similar to:
    //     super(MyClass, self).__del__()
    [super dealloc];
}

@end
</pre>
<p>Objective-C also features exceptions, but they are typically only used for
disaster recovery, not error handling, so you will not encounter them very
often.  Read <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/index.html">The Objective-C Programming Language</a> if you want to
know more about exceptions in Objective-C.</p>
<p>One thing to keep in mind when translating Objective-C snippets to Python is
that any message can be sent to <code><span>nil</span></code>, and the return value of that message
will be <code><span>nil</span></code>.  PyObjC translates <code><span>nil</span></code> to <code><span>None</span></code> when crossing the
bridge, so any such attempt will raise an <code><span>AttributeError</span></code>.</p>
<p>For more information about Objective-C see:</p>
<ul>
<li><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/index.html">The Objective-C Programming Language</a> at <a href="http://www.apple.com/">Apple</a>.</li>
</ul>
<h2><a href="#id8" name="overview-of-the-bridge">Overview of the bridge</a></h2>
<h3><a href="#id9" name="classes">Classes</a></h3>
<p>Objective-C classes are visible as (new-style) Python classes and can be 
subclassed just like normal Python classes.  All the usual introspection
mechanisms work as well, as do <code><span>__slots__</span></code> and descriptors.  The major 
differences between normal Python classes and Objective-C classes are the way 
that instances are created and initialized, and the fact that Objective-C
selectors look strange when translated to Python methods.</p>
<p>You can use multiple inheritance when subclassing an Objective-C class, so
long as the Objective-C class is the first base class and there is only one
Objective-C base class.  The Objective-C runtime does not support multiple
inheritance.  These mix-in classes should not contain different
implementations for Objective-C methods.  To achieve this behavior, Categories
should be used instead.</p>
<p>Another thing to keep in mind is that the names of Objective-C classes must
be globally unique per process, including across Python modules.  That is,
it is <i>not</i> possible to have two Python modules that define a class with the
same name.  It is conventional to choose class names with a short prefix that
uniquely identify your project or company.  For example, Apple uses <code><span>NS</span></code>
as the prefix for all classes in the <a href="http://developer.apple.com/referencelibrary/API_Fundamentals/Cocoa-api-date.html">Cocoa libraries</a>.  Note that the <code><span>NS</span></code>
prefix made much more sense when it was called NeXTstep, but persists to this
day for compatibility reasons.</p>
<p>As described in <a href="#objective-c-for-pyobjc-users">Objective-C for PyObjC users</a> the creation of Objective-C 
objects is a two-stage process.  To initialize objects, you first call a
class method to allocate the memory (typically <code><span>alloc</span></code>), and then call an
initializer (typically starts with <code><span>init</span></code>).  Some classes have class methods
which perform this behind the scenes, especially classes that create cached,
immutable, or singleton instances.</p>
<h3><a href="#id10" name="messages-and-functions">Messages and Functions</a></h3>
<p>Objective-C methods are bridged to Python methods.  Because Objective-C
message dispatch syntax can not be translated directly to Python, a few
simple translations must take place.  The rules for these translations are:</p>
<ol type="1">
<li>Replace all colons in the selector with underscores:<blockquote>
<ul>
<li><code><span>someMethod:withFoo:andBar:</span></code> translates to <code><span>someMethod_withFoo_andBar_</span></code></li>
</ul>
</blockquote>
</li>
<li>If the result <code><span>class</span></code> or <code><span>raise</span></code> (Python keywords), append two underscores:<blockquote>
<ul>
<li><code><span>class</span></code> translates to <code><span>class__</span></code></li>
<li><code><span>raise</span></code> translates to <code><span>raise__</span></code></li>
</ul>
</blockquote>
</li>
<li>Use this translated selector as you would a normal Python method.
The arguments must be passed in the same order, and the number of
arguments passed will normally be equal to the number of underscores
in the method name; exceptions to this rule and the behavior of &quot;result&quot;
are mentioned below.<blockquote>
<ul>
<li><code><span>result</span> <span>=</span> <span>[someObject</span> <span>someMethod:firstArg</span> <span>withFoo:foo</span> <span>andBar:bar];</span></code>
translates to
<code><span>result</span> <span>=</span> <span>someObject.someMethod_withFoo_andBar_(firstArg,</span> <span>foo,</span> <span>bar)</span></code></li>
</ul>
</blockquote>
</li>
</ol>
<p>Note that it is currently not possible to support methods with a variable
number of arguments from Python.  These selectors must be wrapped by
custom Objective-C code in order to be accessible by Python.</p>
<p>Wrapped/bridged methods (and functions) have the same number of arguments
as the corresponding Objective-C method or function, unless otherwise noted
in the documentation (<a href="api-notes-macosx.html">Notes on supported APIs and classes on Mac OS X</a> for
Cocoa on Mac OS X).</p>
<p>Most methods or functions that take or return pointers to values will be an
exception to this rule if it is callable from Python at all.  In Objective-C
terminology, there are three kinds of pointers that can be used in a method:</p>
<dl>
<dt><code><span>in</span></code>:</dt>
<dd><p>Used to pass data by reference to the function.  This is not a special
case from Python.</p>
</dd>
<dt><code><span>out</span></code>:</dt>
<dd><p>Used to pass data from the function (e.g. an additional return value).
From Python, these values will be missing from the argument list (there
will be more underscores than arguments passed).  See below for notes on
how <code><span>out</span></code> arguments change the return value.</p>
</dd>
<dt><code><span>inout</span></code>:</dt>
<dd><p>A combination of in and out (a value is passed by reference, and mutated
upon return).  Unlike <code><span>out</span></code>, these arguments remain in the argument list,
and thus do not have an effect on the number of arguments a method expects.
See below for notes on how <code><span>inout</span></code> arguments change the return value.</p>
</dd>
</dl>
<p>In order to determine what the return value of such an exceptional message will
look like, you must &quot;make a list&quot; of the return values with the following rules:</p>
<ol type="1">
<li>If the return type of the method or function is not <code><span>void</span></code>, add it to the
list.</li>
<li>For each argument in the method or function, add it to the list if it is
<code><span>out</span></code> or <code><span>inout</span></code>.</li>
</ol>
<p>After creating this list, you will have one of three cases:</p>
<dl>
<dt>Empty:</dt>
<dd><p>The return value of this call will always be <code><span>None</span></code>.</p>
</dd>
<dt>One element:</dt>
<dd><p>The return value of this call will correspond to the one element of the list.</p>
</dd>
<dt>More than one element:</dt>
<dd><p>The return value of this call will be a tuple in the same order as the list.</p>
</dd>
</dl>
<p>The rules for pass by reference arguments may look quite complicated, but
it turns out this is very straightforward when working with them.</p>
<p>As an example of a method with two output arguments, <code><span>NSMatrix</span></code> implements a
selector named <code><span>getNumberOfRows:columns:</span></code> with the following signature:</p>
<pre>
(void)getNumberOfRows:(int *)rowCount columns:(int *)columnCount
</pre>
<p>You use this method in python like this:</p>
<pre>
rowCount, columnCount = matrix.getNumberOfRows_columns_()
</pre>
<p>When a function or method has an array of values and the length of that array
as arguments, you can pass <code><span>None</span></code> as the length.  The length of the sequence
that is used for the array of values is passed to Objective-C as the length
argument.</p>
<p>Python's <code><span>array.array</span></code> type may be used to represent a C array if the
typestr and size match what is expected by the selector.  Numeric, numarray,
and other third party array types are not supported in PyObjC 1.3.</p>
<p>When you define methods in a subclass of an Objective-C class, the bridge has
to tell the Objective-C runtime what the signature of those methods is.  The
basic rule is that all arguments as well as the return value are objects (just
like with normal Python methods).  The bridge will automatically pick a better 
signature when it has more information available.  Specifically, if you 
override an existing method the bridge will assume you want to use the same
method signature.  Furthermore, if you implement a method in an (informal)
protocol known to the bridge it will use the signature from the corresponding
method in that signature.</p>
<p>The end result is that you rarely have to add information about the
signature of methods.  For the two most common cases where this is necessary,
we have provided convenience decorators (used like <code><span>staticmethod</span></code> or
<code><span>classmethod</span></code>):</p>
<dl>
<dt><code><span>objc.accessor</span></code>:</dt>
<dd><p>Use this to wrap a <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/">Key-Value Coding</a> or <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueObserving/">Key-Value Observing</a> compliant
accessor.</p>
</dd>
<dt><code><span>PyObjCTools.AppHelper.endSheetMethod</span></code>:</dt>
<dd><p>Use this to wrap the implementation of a sheet's &quot;didEndSelector&quot; callback.</p>
</dd>
</dl>
<p>For complete control of the mapping to Objective-C you can use the function
<code><span>objc.selector</span></code> to create custom descriptors. See the documentation of the
<code><span>objc</span></code> module for the arguments you can use with this function. It is
normally used like this:</p>
<pre>
class MyObject (NSObject):
        def someMethod_(self, arg):
                pass

        someMethod_ = objc.selector(someMethod_, ...)
</pre>
<h3><a href="#id11" name="reference-counting">Reference counting</a></h3>
<p>The <a href="http://developer.apple.com/referencelibrary/API_Fundamentals/Cocoa-api-date.html">Cocoa libraries</a>, and most (if not all) other class libraries for 
Objective-C use explicit reference counting to manage memory. The methods
<code><span>retain</span></code>, <code><span>release</span></code> and <code><span>autorelease</span></code> are used to manage these 
reference counts. You won't have to manage reference counts in Python, the
bridge does all that work for you (but see <a href="api-notes-macosx.html">Notes on supported APIs and classes 
on Mac OS X</a> for some advanced issues).</p>
<p>The only reasons reference counts are mentioned at all are to tell you about
ignoring them, and more importantly to introduce you to some issues w.r.t. 
reference counting.</p>
<p>It turns out that Cocoa uses a primitive form of <a href="http://www.python.org/doc/current/lib/module-weakref.html">weak references</a>. Those 
are not true <a href="http://www.python.org/doc/current/lib/module-weakref.html">weak references</a> as in Python, but use-cases where an object 
stores a reference to another object without increasing the reference count
for that other object. The bridge cannot solve the issues this introduces
for you, which means that you get hard crashes when you're not careful when
dealing with those <a href="http://www.python.org/doc/current/lib/module-weakref.html">weak references</a>.</p>
<p>The basic rule to deal with weak references is: make sure objects stays
alive as long as someone might have a weak reference to them. Due to the way
the bridge works, this means that you must make sure that you don't create
weak references from Objective-C to a plain Python object. The Python
object stays alive, but the proxy object as seen by the Objective-C code is
actually an autoreleased object that will be cleaned up unless the Objective-C
code increases its reference count.</p>
<p>The document <a href="api-notes-macosx.html">Notes on supported APIs and classes on Mac OS X</a> contains 
information about classes that work with weak references. The most important
are notification centers and <code><span>NSOutlineView</span></code>, to be exact: the outline view
stores weak references to the objects return by the method 
<code><span>outlineView:child:ofItem:</span></code> of its data source. The easiest way to avoid
crashes with outline views is to make sure that you model for the view uses
subclasses of <code><span>NSObject</span></code> to represent the nodes in the outline view.</p>
<p>Another gotcha is that <code><span>obj.setDelegate_()</span></code> often does <i>not</i> retain the
delegate, so a reference should be maintained elsewhere.</p>
<h3><a href="#id12" name="informal-protocols">(Informal) protocols</a></h3>
<p>Cocoa defines a number of formal and informal protocols that specify methods
that should be implemented by a class if it is to be used in a specific role,
such as the data source for an <code><span>NSTableView</span></code>.</p>
<p>Those protocols are represented by instances of <code><span>objc.informal_protocol</span></code>. The
only ones that have to care about these objects are the maintainers of 
wrappers around Objective-C frameworks: they have to keep these protocol
wrappers up-to-date.</p>
<p>PyObjC will automatically use the information in the <code><span>informal_protocol</span></code> 
objects to add the right method signatures to methods, and to warn about
classes that partially implement a protocol.</p>
<p>See <a href="protocols.html">PyObjC protocol support</a> for more information.</p>
<h3><a href="#id13" name="cocoa-bindings">Cocoa Bindings</a></h3>
<p>In Mac OS X 10.3 Apple introduced <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/">Cocoa Bindings</a>, a method to make it easier
to create and use <i>Controller</i> objects using <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueObserving/">Key-Value Observing</a> and <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/">Key-Value
Coding</a>.  In order to create accessors compatible with this, you
must use <code><span>objc.accessor</span></code> to create an appropriate selector descriptor.</p>
<h3><a href="#id14" name="categories">Categories</a></h3>
<p>Objective-C has a mechanism for modularize a class definition, it is possible
to add methods to an existing class in a separate compilation unit and even
a separate library. This mechanism is named categories and is used to enhance
existing classes, for splitting classes in several parts and to document
informal protocols.</p>
<p>An example of a category definition:</p>
<pre>
@interface NSObject (MyCategory)
- (NSSize)objectFootprint;
@end
</pre>
<p>This declares an additional category on <code><span>NSObject</span></code>. This category contains
a single method.</p>
<p>The function <code><span>objc.classAddMethods</span></code> can be used to get the same effect in
Python:</p>
<pre>
def objectFootprint(self):
        pass

objc.classAddMethods(NSObject, [objectFootprint])
</pre>
<p>This is not very clear, PyObjC therefore also provides the following 
mechanism, implemented on top of <code><span>objc.classAddMethods</span></code>:</p>
<pre>
class NSObject (objc.Category(NSObject)):
        def objectFootprint(self):
                pass
</pre>
<p>To make it clear that <code><span>objc.Category</span></code> performs a special task the name in
the class definition must be the same as the <code><span>__name__</span></code> of the argument
to <code><span>objc.Category</span></code>.</p>
<h2><a href="#id15" name="cocoa-for-python-programmers">Cocoa for Python programmers</a></h2>
<p>Cocoa frameworks are mapped onto Python packages with the same name; that is
the classes, constants and functions from the AppKit framework are available
after you import <code><span>AppKit</span></code> in your Python script.</p>
<p>These helper modules contain <i>only</i> functions, constants and classes that 
wrap items in the corresponding framework. All utility functions and classes 
are located in the <code><span>PyObjCTools</span></code> package and <code><span>objc</span></code> module. Note that it
is possible to use <code><span>pydoc</span></code> (or the <code><span>help()</span></code>) function with the framework
wrappers, but that this is not very useful for the entire module due to the
size of these modules.</p>
<p>This makes it easier to find documentation for an item: if you import it 
from the wrapper module for an Objective-C framework the documentation for
that item can be found in the documentation for the framework; otherwise the
item is documented in the PyObjC documentation.</p>
<p>The module <code><span>PyObjCTools.NibClassBuilder</span></code> can be used to make working with 
NIB files more convenient. This module can be used to extract information 
about classes from NIB files, both as a standalone tool generating source code 
and during runtime. See the online documentation for this module for more
information.</p>
<p>PyObjC includes a number of examples that show how to use Cocoa from
Python. The <a href="../Examples/00ReadMe.html">PyObjC Example index</a> contains an overview of those examples.</p>
<p>More information on Cocoa programming can be found at:</p>
<ul>
<li><a href="http://developer.apple.com/documentation/Cocoa/Cocoa.html">Cocoa documentation at the Apple developer website</a></li>
<li><a href="http://developer.apple.com/samplecode/Cocoa/index.html">Cocoa examples at the Apple developer website</a></li>
<li><a href="http://www.stepwise.com/">stepwise.com</a></li>
<li>Your local bookstore or library</li>
</ul>
<h2><a href="#id16" name="notes-on-specific-tasks">Notes on specific tasks</a></h2>
<h3><a href="#id17" name="working-with-threads">Working with threads</a></h3>
<p>When you create a thread and want to use PyObjC from that thread you will
have to create an <code><span>NSAutoreleasePool</span></code> in that thread and clean it up when
you're done. The easiest way to that is to create an instance of that class
bound to a local variable. If the thread is long-lived you may want to arrange
for recycling the pool once in a while.</p>
<h3><a href="#id18" name="finalizers">Finalizers</a></h3>
<p>In Python you can use the method <code><span>__del__</span></code> to clean up resources when your
object is garbage collected. In Objective-C/Cocoa this is done with a method 
named <code><span>dealloc</span></code>.</p>
<p>In Python subclasses of Objective-C classes you can use either convention. You
should pick one convention for your own code, the order in which <code><span>__del__</span></code>
and <code><span>dealloc</span></code> methods are called is undefined.</p>
<h3><a href="#id19" name="copying">Copying</a></h3>
<p>It is possible to implement the <code><span>NSCopying</span></code> protocol in your classes. Some
care must be taken when you inherit from a class that already implements 
that protocol.</p>
<p>Some classes copy the template object manually, you'll have to copy your 
own fields manually in that case. Other classes use a convenience function
that creates the copy. In that case you wont have to copy your own fields.
However, the fields in the copy will rever to the same objects as the 
fields in the original (that is, the copy will share some state with the
original). This is no problem when the fields rever to immutable values (such
as integers), but is probably not what you want when the fields rever to
mutable values (such as lists).</p>
<p>NOTE: PyObjC might introduce a helper class when you inherit from a class
that implements <code><span>NSCopying</span></code>. You should not rely on the existance of this
class.</p>
<p>NOTE2: You shouldn't assign to <code><span>SomeClass.copyWithZone_</span></code> unless that class
already implements <code><span>copyWithZone:</span></code>. If you do you may end up with seemingly
random memory coruption.</p>
<h2><a href="#id20" name="building-applications">Building applications</a></h2>
<p>There are two different ways to build applications with PyObjC. py2app
should be the preferred method, however using the Xcode template can
be convenient for development.</p>
<h3><a href="#id21" name="py2app-setup-py">&quot;py2app&quot; :  setup.py</a></h3>
<p>The PyObjC installer includes a copy of the <code><span>py2app</span></code> package. This package
offers a way to build distutils scripts for building (standalone)
applications and plugin bundles.</p>
<p>An example <code><span>setup.py</span></code> script:</p>
<pre>
from distutils.core import setup
import py2app

setup(
    app = [&quot;iClass.py&quot;],
    data_files = [&quot;English.lproj&quot;],
)
</pre>
<p>During development you typically invoke it from the command line like this:</p>
<pre>
python setup.py py2app -A
</pre>
<p>This will build an application bundle in a folder named <code><span>dist</span></code> in the
current folder. The <code><span>-A</span></code> option tells <code><span>py2app</span></code> to add symbolic
links for data folders and files and an Alias to your main script,
allowing you quickly rebuild the application without doing a full dependency
scan, with the additional bonus that you can edit them without rebuild. To
build a standalone application, simply do not use the <code><span>-A</span></code> option.
Note that if you are using a version of Python shipped with your operating
system, it will not be included in the application.  Otherwise, your
application will include stripped down version of the Python runtime that
you ran setup.py with.</p>
<p>For more information about <code><span>py2app</span></code> usage, read through some of the
<code><span>setup.py</span></code> scripts used by the examples in the <a href="../Examples/00ReadMe.txt">Examples</a> folder.
On any <code><span>setup.py</span></code> script that imports <code><span>py2app</span></code>, you can use the
following command to see the list of options:</p>
<pre>
python setup.py py2app --help
</pre>
<h3><a href="#id22" name="ide-approach-xcode">&quot;IDE approach&quot; : Xcode</a></h3>
<p>PyObjC includes a number of Xcode templates that can be used to 
develop applications. Those templates are used like any other
Xcode template. The only non-obvious detail is that you have to
add your sources as resources, but Project Builder usually does the right
thing when you add a new file.</p>
<p>The templates will build an application that makes use of the installed copy
<code><span>/System/Library/Frameworks/Python.framework</span></code> (e.g. the one shipped by
Apple in Mac OS X 10.3) and will copy the PyObjC modules into the application
bundle. This means that this application bundle <i>should</i> be useable on any
Mac OS X 10.3 system, if you do not have any additional dependencies.  Using
py2app to deploy your application is a more reliable method, and builds more
compact bundles.</p>
<p>See <a href="Xcode-Templates.html">the documentation for the templates</a> for more details.</p>
</body>
</html>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.