Source

pyobjc-docs / pyobjc-core / Doc / advanced / protocols.rst

Protocols

Introduction

Apple makes use of both formal and informal protocols in the Cocoa framework to specify methods that should be implemented by a class if it is to be used in a specific role. For example, a class to be used as a data source for an NSTableView must conform to the NSTableViewDataSource protocol.

A Formal protocol is implemented in Objective-C as follows:

@protocol NSFoo <NSSomeProtocol>
-(int)doesIt;
@end

Conforming to a formal protocol requires the interface of a class to explicitly declare that it implements that protocol, and the implementation must implement all methods of the protocol.

Informal protocols however are defined as categories on NSObject with no implementation:

@interface NSObject(FooDelegate)
-(void)optionalFooDelegateMethod;
@end

Conforming to an informal protocol is much like conforming to a protocol in Python: the class simply implements the methods as documented. In most cases, informal protocols are comprised entirely of optional methods (eg NSApplicationDelegate) and a check is made (i.e. -[NSObject respondsToSelector:]) before sending the message to the target.

Informal protocols and PyObjC

PyObjC has an explicit representation for informal protocols. This makes it possible to use the protocol description to provide better error messages and to automaticly deduce the method signatures for classes that implement an informal protocol.

Informal protocols are represented using instances of objc.informal_protocol. These instances are automatically added to a registry used by the class builder, so it is not necessary to explicitly state that a class implements an informal protocol.

PyObjC will automatically use the information in the informal_protocol objects to add the right method signatures to methods, and to warn about classes that partially implement a protocol. The only people who have to be concerned about these objects are the maintainers of wrappers around Objective-C frameworks: they have to keep these protocol wrappers up-to-date.

Formal protocols and PyObjC

PyObjC also has an explicit representation for formal protocols.

Formal protocols are represented as instances of objc.formal_protocol. Unlike informal protocols, it is necessary to explicitly declare conformance to formal protocols. However, all formal protocols in Cocoa are also described using objc.informal_protocol objects.

Declaring conformance to a formal protocol is done by using the formal protocol as a mix-in, and by implementing its methods:

NSLocking = objc.protocolNamed('NSLocking')

class MyLockingObject(NSObject, NSLocking):
    def lock(self):
        pass

    def unlock(self):
        pass

The class now formally implements the NSLocking protocol. This can be verified using the Objective-C introspection methods:

>>> MyLockingObject.pyobjc_classMethods.conformsToProtocol_(NSLocking)
1

This is useful for API's that require (and check) the implementation of formal protocols.

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.