:mod:`objc` -- The PyObjC bridge
The module :mod:`objc` is the core of PyObjC and provides the automatic bridging between Python and Objective-C. It also provides a number of utility functions and types that make it easier to integrate Python and Objective-C code.
The module :mod:`objc` defines a number of functions whose names start with an underscore. Those functions are private and should not be used, they can be removed from release without warning.
NOTE: This document is currently mostly an exhaustive list of stuff and needs to be reorganised once I've filled in the technical details.
Accessing classes and protocols
Dynamic modification of classes
A helper class for adding a category to an existing Objecive-C class (subclass of :c:type:`NSObject`).
class NSObject (Category(NSObject)): def method(self): pass
The metaclass uses :func:`classAddMethods` to add the methods in the category body to the base class.
The name of the class must be the same as the argument to :class:`Category`.
PyObjC automaticly manages Cocoa reference counts for you, the functions in this section help in finetuning this behaviour.
The functions in this section are present as support code for PyObjC's unittests and are not part of the stable API. Please let us know if you use these functions in your code.
|the bundle_identifier argument for a call to :func:`loadBundle`|
|the bundle_path argument for a call to :func:`loadBundle`|
|param metadict:||the dictionary with metadata, usually the __dict__ of a module generated by the metadata compiler.|
|a capsule object with function definitions, see :func:`loadFunctionList` for more information.|
|additional values to add to the module dictionary|
|param parents:||a list of parent modules, the module behaves as if those modules were imported using from parent parent import *, but lazily fetches definitions on first access.|
This class is the metatype for Objective-C classes and provides no user-visible behavior.
This class is the root class for Objective-C classes, that is all wrappers for Objective-C classes are a subclass of this class. It is not possible to instantiate instances of Objective-C classes by using the class as a callable, instances are created using the standard Objective-C mechanisms instead.
Methods of the underlying :c:type:`NSString` class can be accessed at as methods of the python type, unless they have the same name as a method of the built-in Unicode type.
Instances of :c:type:`NSString` can be mutable. Mutations to mutable Cocoa strings are not reflected in instances of :class:`pyobjc_unicode`, use :meth:`nsstring` and explict conversion to the built-in unicode type when you work with mutable :c:type:`NSString` values.
Cocoa strings are wrapped using a subclass of the built-in unicode string to get better interaction between Python and Cocoa. Because Cocoa strings are instances of the built-in unicode type they can be passed to functions in extension modules that expect unicode arguments (in particular the file system access APIs such as :func:`open`).
This type is used to represent an Objective-C method.
|param function:||The Python callable that is used for the method. Can be a :class:`classmethod` , but not a :class:`staticmethod`.|
|param selector:||The Objective-C selector for the method. The default is calculated from the __name__ attribute for function|
|The type encoding for the method, the default signature assumes that all arguments and the result are objects (or 'void' when the function does not contain a return statement with a value).|
|Used to specify if a method is a class method (default is :data:`True` if function is a :class:`classmethod` and :data:`False` otherwise)|
|Alternative method for specifying the method return type, using the syntax of :c:func:`Py_BuildValue`.|
|Alternative method for specifying argument types, using the syntax of :c:func:`Py_BuildValue`.|
|Specify if the method is required (defaults to :data:`True`), used in the definition of protocols.|
The arguments returnType and argumentTypes are deprecated in PyObjC 2.5, they are confusing and can only specify a subset of types.
Creates a descriptor for accessing an Objective-C instance variable. This should only be used in the definition of an Objective-C subclass, the bridge will use this information to create an instance variable with the same name on the Objective-C class itself.
|param name:||Name of the instance variable. The name defaults to the name the instance variable is bound to in a class definition.|
|param type:||Type encoding for the instance varialble. Defaults to :data:`_C_ID` (that is, an object)|
|param isOutlet:||If :data:`True` the instance variable is used as an outlet, by default the instance variable is not an outlet.|
Sharing an ivar object between multiple class definitions is not supported.
This class is used to specify which methods are part of an informal protocol in Objective-C. Informal protocols are a documentation construct in Objective-C and as such are not present in the Objective-C runtime (as opposed to formal protocols).
Informal protocols are used by the bridge to automaticly update method signatures when a class appears to implement an informal protocol. This makes it possible the define a large subset of Cocoa functionality without manually setting method signatures.
|param name:||Name of the protocol|
|A sequence of :class:`selector` instances, all of which should have no callable.|
This class is used to represent formal protocols in Python, and is comparabile with the "@protocol" construct in Objective-C.
|param name:||The name of the protocol|
|param supers:||A list of protocols this protocol inherits from|
|A sequence of :class:`selector` instances, all of which should have no callable.|
Constructing new protocols is supported on a subset of Mac OS X platforms:
- All 32-bit programs
- 64-bit programs starting from Mac OS X 10.7, but only when PyObjC was build with the 10.7 SDK (or later)
The interface of this class gives the impression that a protocol instance is an Objective-C object. That was true in earlier versions of Mac OS X, but not in more recent versions.
A C array of unspecified length. Instances of this type cannot be created in Python code.
This type is used when the API does not specify the amount of items in an array in a way that is usable by the bridge.
Access through a :class:`varlist` object can easily read beyond the end of the wrapped C array. Read the Apple documentation for APIs that return a varlist to determine how many elements you can safely access.
This class is used to represent the actual implementation of an Objective-C method (basicly a C function). Instances behave the same as unbound methods: you can call them but need to specify the "self" argument.
This is a subclass of :class:`super <__builtin__.super>` that works properly for Objective-C classes as well as regular Python classes.
Objective-C type strings
The Objective-C runtime and the PyObjC bridge represent the types of instance variables and methods arguments and return values as a string with a compact representation. The Python representation of that string is a byte string (that is type :class:`bytes` in Python 3.x and :class:`str` in Python 2.x).
The representation for basic types is a single character, the table below lists symbolic constants in the for those constants.
|:const:`_C_ID`||:c:type:`id` (an Objective-C instance)|
|:const:`_C_CLASS`||an Objective-C class|
|:const:`_C_SEL`||a method selector|
|:const:`_C_BOOL`||:c:type:`bool` (or :c:type:`_Bool`)|
|:const:`_C_ULNG_LNG`||:c:type:`unsigned long long`|
|:const:`_C_UNDEF`||"other" (such a function)|
|:const:`_C_CHARPTR`||C string (:c:type:`char*`)|
|:const:`_C_CHAR_AS_TEXT`||:c:type:`char` when uses as text or a byte array|
|:const:`_C_CHAR_AS_INT`||:c:type:`int8_t` (or :c:type:`char` when|
|used||as a number)|
More complex types can be represented using longer type strings:
a pointer to some type is :const:`_C_PTR` followed by the type string of the pointed-to type.
a bitfield in a structure is represented as :const:`_C_BFLD` followed by an integer with the number of bits.
Note that PyObjC cannot convert bitfields at this time.
a C structure is represented as :const:`_C_STRUCT_B` followed by the struct name, followed by :const:`'='`, followed by the encoded types of all fields followed by :const:`_C_STRUCT_E`. The field name (including the closing equals sign) is optional.
a C union is represented as :const:`_C_UNION_B` followed by the struct name, followed by :const:`'='`, followed by the encoded types of all fields followed by :const:`_C_UNION_E`. The field name (including the closing equals sign) is optional.
Note that PyObjC cannot convert C unions at this time.
Additional annotations for method and function arguments
Method arguments can have prefixes that closer describe their functionality. Those prefixes are inheritted from Distributed Objects are not used by the Objective-C runtime, but are used by PyObjC.
- When a pointer argument is an input argument it is prefixed by :const:`_C_IN`.
- When a pointer argument is an output argument it is prefixed by :const:`_C_OUT`.
- When a pointer argument is an input and output argument it is prefixed by :const:`_C_INOUT`.
- Distributed objects uses the prefix :const:`_C_BYCOPY` to tell that a value should be copied to the other side instead of sending a proxy reference. This is not used by PyObjC.
- Distributed objects uses the prefix :const:`_C_ONEWAY` on the method return type to tell that the method result is not used and the caller should not wait for a result from the other side. This is not used by PyObjC.
When a pointer argument to a function prefixed by :const:`_C_IN`, :const:`_C_OUT` or :const:`_C_INOUT` the brige assumes that it is a pass by reference argument (that is, a pointer to a single value), unless other information is provided to the bridge.
TODO: Write how to write Objective-C code to ensure that the right prefixes are added by the compiler.
Special encoded types
The table below shows constants for a number of C types that are used in Cocoa but are not basic C types.
A number of Objective-C APIs have one argument that is a context pointer, which is a :c:type:`void*`. In Objective-C your can pass a pointer to an arbitrary value, in Python this must be an integer.
PyObjC provides a :data:`context` object that can be used to allocate unique integers and map those to objects.
(NOTE: The markup below here is probably incorrect)
Interacting with @synchronized blocks
PyObjC provides an API that implements locking in the same way as the @synchronized statement in Objective-C.
with object_lock(anNSObject): pass
This class represents the mutex that protects an Objective-C object for the @synchronized statement. This can be used as a context manager for the with statement, but can also be used standalone.
Archiving Python and Objective-C objects
It is possible to use an :c:type:`NSKeyedArchiver` to store any Python object that can be pickled in an Objective-C serialized data object.
Due to technical details it is not possible to pickle an Objective-C object, unless someone explicitly implements the pickle protocol for such an object.
Both Python and Objective-C have support for properties, which are object attributes that are accessed using attribute access syntax but which result in a method call.
The Python built-in :class:`property <__builtin__.property__` is used to define new properties in plain Python code. These properties don't full interoperate with Objective-C code though because they do not necessarily implement the Objective-C methods that mechanisms like Key-Value Coding use to interact with a class.
PyObjC therefore has a number of property classes that allow you to define new properties that do interact fully with the Key-Value Coding and Observation frameworks.
TODO: Implement method for enabling properties on existing classes and tell why that is off by default and when it will be turned on by default.
TODO: The description is way to minimal, even the design document contained more information.
|param name:||Name of the property, the default is to extract the name from the class dictionary|
|Is this a read-only property? The default is a read-write property.|
|param copy:||Should the default setter method copy values? The default retains the new value without copying.|
|param dynamic:||If this argument is :data:`True` the property will not generate default accessor, but will rely on some external process to create them.|
|param ivar:||Name of the instance variable that's used to store the value. When this value is :data:`None` the name will be calculated from the property name. If it is :data:`NULL` there will be no instance variable.|
|param typestr:||The Objective-C type for this property, defaults to an arbitrary object.|
|A sequence of names of properties the value of this property depends on.|
During the class definition you can add accessor methods by using the property as a decorator
It is possible to override property accessor in a subclass:
class MySubclass (MyObject): @MyObject.prop.getter def getter(self): return "the world"
This can also be used to convert a read-only property to a read-write one by adding a setter accessor.
Properties for structured types
Key-Value Coding is slightly different for structured types like sets and lists (ordered and unordered collections). For this reason PyObjC also provides subclasses of :class:`object_property` that are tuned for these types.
This property implements a list-like property. When you access the property you will get an object that implements the :class:`MutableSequence` ABC, and that will generate the correct Key-Value Observation notifications when the datastructure is updated.
This property implements a set-like property. When you access the property you will get an object that implements the :class:`MutableSet` ABC, and that will generate the correct Key-Value Observation notifications when the datastructure is updated.
This property is like an :class:`object_property`, but has an empty NSMutableDictionary object as its default value. This type is mostly provided to have a complete set of property types.
These collection properties are at this time experimental and do not yet provide proper hooks for tweaking their behavior. Future versions of PyObjC will provide such hooks (for example a method that will be called when an item is inserted in an array property).