Objective-Everything Release 5. Copyright ©1994-1998 by TipTop Software, Inc. All Rights Reserved.
if o: <then-part> else: <else-part>
If o is a generic ObjPy object, then <then-part> is executed iff o!=nil, otherwise, <else-part> is executed. E.g., not(nil) evaluates to true.
NSArray support: NSArrays are represented using ObjPySeqObject. ObjPySeqObject provides all of the functionality of the native Python sequence objects (Tuples, Lists, ...).
a=obj(["one", 2, "three"]) print type(a), a.clazz() # ==> <type 'ObjPySeqObject'> NS*MutableArray print a[1] # ==> 2 print a*2 # ==> (one, 2, three, one, 2, three) a[3:]=[4,"five"] print a[:] # ==> (one, 2, three, 4, five) del a[3] print a # ==> (one, 2, three, five) a.reverse() print a # ==> (five, three, 2, one) a.sort() print a # ==> (2, five, one, three) print len(a) # ==> 4 if a: print "non-empty" # ==> non-empty del a[:] if not a: print "empty" # ==> empty # etc.
NSDictionary support: NSDictionaries are represented using ObjPyMapObject. ObjPyMapObject provides all of the functionality of the native Python sequence objects (Dictionary).
d=obj({'one' : 'abc', 'two': 'xyz'}) print type(d), d.clazz() # ==> <type 'ObjPyMapObject'> NS*MutableDictionary print d.items() # ==> [('one', 'abc'), ('two', 'xyz')] print d['one'] # ==> abc print len(d) # ==> 2 del d['two'] d['xyz']=123 print d # ==> {one = abc; xyz = 123; } if d: print "non-empty" # ==> non-empty del d['xyz']; del d['one'] if not d: print "empty" # ==> empty # etc.
The (PyObject*) type: The ObjPy type system directly handles the (PyObject*) type. The PyObject* type conversion takes care of Python reference counting appropriately. E.g.:
cdef(""" int PyObject_Hash(PyObject*); PyObject* PyObject_Type(PyObject*); """)
o="Hello World!" print C.PyObject_Hash(o) # same as: hash(o) print C.PyObject_Type(o) # same as: type(o)
Reference counting. You never need to retain/release ObjPy objects. The Objective-Python system does it automatically behind the scenes! E.g.:
o=Class.NSObject() # o=Class.NSObject.alloc().init(); o.release() print o.retainCount() # ==> 1 # ... o=None # o is released now!
Note that NSAutoreleasePools are an exception to how the ObjPy system handles reference counting, since NSAutoreleasePools cannot be retained (i.e., their retain count is always 1) in OpenStep. NSAutoreleasePools are NOT automatically retained nor automatically released. To release a NSAutoreleasePool you must send it an explicit release message!
Normal object release/retain behavior --- objects are automatically retained/released:
a=Class.NSObject.alloc().init() print a.retainCount() # ==> 2 # ... a.release() # a is not dealloced yet a=None # a is released and dealloced now!
b=Class.NSObject() print b.retainCount() # ==> 1 # ... b=None # b is released and dealloced now!
Special NSAutoreleasePool retain/release behavior --- NSAutoreleasePools are NOT automatically retained/released. The following two are equivalent:
#1 p=Class.NSAutoreleasePool.alloc().init() print p.retainCount() # ==> 1 # ... # if we only do: p=None; pool p would not be released! p.release() # p is released now! p=None # be nice
#2 q=Class.NSAutoreleasePool() print q.retainCount() # ==> 1 # ... q.release() # q is released now! q=None # be nice
Here is an example showing how to use NSAutoreleasePools:
pool=Class.NSAutoreleasePool() o=Class.NSObject() print o.retainCount() # ==> 1 # ... o.retain() # ... o.autorelease() # ... print o.retainCount() # ==> greater than 1 since o is autoreleased! o=None # o is not dealloced yet!! pool.release() # releases the pool, and this releases/deallocates the object pool=None
Freeing stuff (in -dealloc). If you have an instance variable which is type (char*), and you want to free it (e.g., in a -dealloc method), simply assign it value None. E.g.:
def mydealloc(self): self['anObject']=nil # releases self->anObject self['aStr']=None # frees self->aStr super.dealloc()
XYZ=Class.NSObject.subclass('XYZ', 'id anObject; char *aStr; /*...*/')
XYZ.category('MyCategory', {
'-(void)dealloc' : mydealloc,
# ...
}