0
# Protocol Support
1
2
Protocol management, formal and informal protocol definition, and protocol conformance checking. Protocols in Objective-C define interfaces that classes can implement, similar to interfaces in other languages. PyObjC provides comprehensive support for working with both formal and informal protocols.
3
4
## Capabilities
5
6
### Protocol Discovery and Access
7
8
Functions for finding and accessing existing Objective-C protocols.
9
10
```python { .api }
11
def protocolNamed(name: str):
12
"""
13
Get an Objective-C protocol by name.
14
15
Args:
16
name (str): Name of the protocol to retrieve
17
18
Returns:
19
The protocol object, or None if not found
20
21
Usage:
22
ns_copying = objc.protocolNamed("NSCopying")
23
if ns_copying:
24
print("Found NSCopying protocol")
25
"""
26
27
def protocolsForClass(cls):
28
"""
29
Get all protocols implemented by a class.
30
31
Args:
32
cls: The Objective-C class to examine
33
34
Returns:
35
list: List of protocol objects implemented by the class
36
37
Usage:
38
protocols = objc.protocolsForClass(NSString)
39
for protocol in protocols:
40
print(f"NSString implements: {protocol.name}")
41
"""
42
43
def protocolsForProcess():
44
"""
45
Get all protocols available in the current process.
46
47
Returns:
48
list: List of all registered protocol objects
49
50
Usage:
51
all_protocols = objc.protocolsForProcess()
52
print(f"Found {len(all_protocols)} protocols")
53
"""
54
```
55
56
### Protocol Definition
57
58
Functions for defining new formal and informal protocols.
59
60
```python { .api }
61
def formal_protocol(name: str, supers, selectors):
62
"""
63
Define a new formal Objective-C protocol.
64
65
Args:
66
name (str): Name for the new protocol
67
supers: Parent protocols (can be None)
68
selectors: Dictionary of method selectors and their signatures
69
70
Returns:
71
The newly created protocol object
72
73
Usage:
74
my_protocol = objc.formal_protocol(
75
"MyCustomProtocol",
76
(objc.protocolNamed("NSObject"),),
77
{
78
"doSomething": objc.signature("v@:"),
79
"getSomething": objc.signature("@@:")
80
}
81
)
82
"""
83
84
def informal_protocol(name: str, selectors):
85
"""
86
Define a new informal Objective-C protocol.
87
88
Args:
89
name (str): Name for the informal protocol
90
selectors: Dictionary of optional method selectors
91
92
Informal protocols define optional methods that classes may implement.
93
They are used for delegation patterns and optional functionality.
94
95
Usage:
96
objc.informal_protocol(
97
"MyDelegate",
98
{
99
"willStartProcessing": objc.signature("v@:"),
100
"didFinishProcessing:": objc.signature("v@:@")
101
}
102
)
103
"""
104
```
105
106
### Protocol Class
107
108
The Protocol class represents Objective-C protocol objects.
109
110
```python { .api }
111
class Protocol:
112
"""
113
Represents an Objective-C protocol object.
114
115
Provides access to protocol metadata, method signatures,
116
and conformance information.
117
"""
118
119
def name(self) -> str:
120
"""Get the protocol name."""
121
122
def conformsToProtocol_(self, protocol) -> bool:
123
"""Check if this protocol conforms to another protocol."""
124
125
def methodDescriptionForSelector_isRequiredMethod_isInstanceMethod_(
126
self, selector: str, required: bool, instance: bool
127
):
128
"""Get method description for a specific selector."""
129
```
130
131
## Usage Examples
132
133
### Working with Existing Protocols
134
135
```python
136
import objc
137
from Foundation import NSString, NSMutableString
138
139
# Get the NSCopying protocol
140
copying_protocol = objc.protocolNamed("NSCopying")
141
if copying_protocol:
142
print(f"Protocol name: {copying_protocol.name()}")
143
144
# Check if NSString conforms to NSCopying
145
protocols = objc.protocolsForClass(NSString)
146
if copying_protocol in protocols:
147
print("NSString implements NSCopying")
148
```
149
150
### Defining a Custom Formal Protocol
151
152
```python
153
import objc
154
155
# Define a formal protocol
156
drawable_protocol = objc.formal_protocol(
157
"Drawable",
158
None, # No parent protocols
159
{
160
"draw": objc.signature("v@:"),
161
"drawInRect:": objc.signature("v@:{CGRect=dddd}"),
162
"canDraw": objc.signature("c@:")
163
}
164
)
165
166
# Create a class that implements the protocol
167
class MyDrawableView(NSView):
168
169
def draw(self):
170
"""Required method from Drawable protocol."""
171
# Drawing implementation
172
pass
173
174
@objc.signature("v@:{CGRect=dddd}")
175
def drawInRect_(self, rect):
176
"""Draw in a specific rectangle."""
177
# Rectangle-specific drawing
178
pass
179
180
def canDraw(self):
181
"""Check if drawing is possible."""
182
return True
183
```
184
185
### Defining an Informal Protocol for Delegation
186
187
```python
188
import objc
189
190
# Define an informal protocol for delegation
191
objc.informal_protocol(
192
"MyProcessorDelegate",
193
{
194
"processorWillStart:": objc.signature("v@:@"),
195
"processor:didProcessItem:": objc.signature("v@:@@"),
196
"processor:didFailWithError:": objc.signature("v@:@@"),
197
"processorDidFinish:": objc.signature("v@:@")
198
}
199
)
200
201
# Create a processor class that uses the delegate
202
class MyProcessor(NSObject):
203
204
def setDelegate_(self, delegate):
205
self._delegate = delegate
206
207
def startProcessing(self):
208
# Notify delegate if it implements the method
209
if hasattr(self._delegate, 'processorWillStart_'):
210
self._delegate.processorWillStart_(self)
211
212
# Do processing...
213
for item in self._items:
214
if hasattr(self._delegate, 'processor_didProcessItem_'):
215
self._delegate.processor_didProcessItem_(self, item)
216
217
# Notify completion
218
if hasattr(self._delegate, 'processorDidFinish_'):
219
self._delegate.processorDidFinish_(self)
220
221
# Create a delegate class
222
class MyDelegate(NSObject):
223
224
def processorWillStart_(self, processor):
225
print("Processing started")
226
227
def processor_didProcessItem_(self, processor, item):
228
print(f"Processed item: {item}")
229
230
def processorDidFinish_(self, processor):
231
print("Processing completed")
232
```
233
234
### Protocol Conformance Checking
235
236
```python
237
import objc
238
from Foundation import NSArray, NSString
239
240
# Check what protocols a class implements
241
string_protocols = objc.protocolsForClass(NSString)
242
array_protocols = objc.protocolsForClass(NSArray)
243
244
print("NSString protocols:")
245
for protocol in string_protocols:
246
print(f" - {protocol.name()}")
247
248
print("NSArray protocols:")
249
for protocol in array_protocols:
250
print(f" - {protocol.name()}")
251
252
# Check if a specific protocol is implemented
253
copying_protocol = objc.protocolNamed("NSCopying")
254
if copying_protocol in string_protocols:
255
print("NSString implements NSCopying")
256
257
# Check protocol inheritance
258
coding_protocol = objc.protocolNamed("NSCoding")
259
if coding_protocol and copying_protocol:
260
conforms = coding_protocol.conformsToProtocol_(copying_protocol)
261
print(f"NSCoding conforms to NSCopying: {conforms}")
262
```
263
264
### Creating Protocol-Conforming Classes
265
266
```python
267
import objc
268
from Foundation import NSObject
269
270
# Create a class that explicitly conforms to NSCopying
271
class MyCopiableClass(NSObject):
272
273
def initWithValue_(self, value):
274
self = objc.super(MyCopiableClass, self).init()
275
if self is None:
276
return None
277
self._value = value
278
return self
279
280
def copyWithZone_(self, zone):
281
"""Implement NSCopying protocol."""
282
return MyCopiableClass.alloc().initWithValue_(self._value)
283
284
def value(self):
285
return self._value
286
287
# Verify the class works with copying
288
original = MyCopiableClass.alloc().initWithValue_("Hello")
289
copy = original.copy()
290
291
print(f"Original value: {original.value()}") # "Hello"
292
print(f"Copy value: {copy.value()}") # "Hello"
293
print(f"Same object: {original is copy}") # False
294
```