0
# Enhanced Classes
1
2
Python-friendly enhancements automatically added to native Objective-C classes, providing familiar Python interfaces like dictionary access, iteration support, and context managers. These enhancements make Cocoa objects more natural to use in Python code.
3
4
## Capabilities
5
6
### Foundation Class Enhancements
7
8
Enhanced methods automatically available on Foundation framework classes to provide Python-like behavior and improved usability.
9
10
#### NSAttributedString Enhancements
11
12
```python { .api }
13
def __len__(self):
14
"""
15
Returns the length of the attributed string.
16
17
Returns:
18
int: Number of characters in the attributed string
19
20
Example:
21
attr_string = NSAttributedString.alloc().initWithString_("Hello")
22
length = len(attr_string) # Returns 5
23
"""
24
```
25
26
#### NSCache Enhancements (Dictionary-like Interface)
27
28
```python { .api }
29
def __getitem__(self, key):
30
"""
31
Gets cached object for key using dictionary-style access.
32
33
Args:
34
key: Cache key
35
36
Returns:
37
Cached object or None if NSNull
38
39
Raises:
40
KeyError: If key not found in cache
41
42
Example:
43
cache = NSCache.alloc().init()
44
value = cache["user_data"] # Raises KeyError if not found
45
"""
46
47
def get(self, key, default=None):
48
"""
49
Gets cached object for key with optional default value.
50
51
Args:
52
key: Cache key
53
default: Value to return if key not found
54
55
Returns:
56
Cached object, None if NSNull, or default if not found
57
58
Example:
59
cache = NSCache.alloc().init()
60
value = cache.get("user_data", {}) # Returns {} if not found
61
"""
62
63
def __setitem__(self, key, value):
64
"""
65
Sets cached object for key using dictionary-style assignment.
66
67
Args:
68
key: Cache key
69
value: Object to cache (None values stored as NSNull)
70
71
Example:
72
cache = NSCache.alloc().init()
73
cache["user_data"] = user_object
74
cache["setting"] = None # Stored as NSNull
75
"""
76
77
def __delitem__(self, key):
78
"""
79
Removes cached object for key.
80
81
Args:
82
key: Cache key to remove
83
84
Example:
85
cache = NSCache.alloc().init()
86
del cache["old_data"]
87
"""
88
89
def clear(self):
90
"""
91
Removes all cached objects.
92
93
Example:
94
cache = NSCache.alloc().init()
95
cache.clear() # Empty cache
96
"""
97
```
98
99
#### NSHashTable Enhancements (Set-like Interface)
100
101
```python { .api }
102
def __len__(self):
103
"""
104
Returns the number of objects in the hash table.
105
106
Returns:
107
int: Count of objects in hash table
108
"""
109
110
def __iter__(self):
111
"""
112
Iterates over objects in the hash table.
113
114
Yields:
115
Objects stored in hash table (NSNull converted to None)
116
"""
117
118
def add(self, value):
119
"""
120
Adds object to hash table (None values stored as NSNull).
121
122
Args:
123
value: Object to add to hash table
124
"""
125
126
def remove(self, value):
127
"""
128
Removes object from hash table.
129
130
Args:
131
value: Object to remove (None converted to NSNull)
132
"""
133
134
def __contains__(self, value):
135
"""
136
Checks if hash table contains object.
137
138
Args:
139
value: Object to check for (None converted to NSNull)
140
141
Returns:
142
bool: True if object is in hash table
143
"""
144
145
def pop(self):
146
"""
147
Removes and returns arbitrary object from hash table.
148
149
Returns:
150
Arbitrary object from hash table (NSNull converted to None)
151
"""
152
153
def clear(self):
154
"""
155
Removes all objects from hash table.
156
"""
157
```
158
159
#### NSIndexSet Enhancements (Set-like Interface for Indices)
160
161
```python { .api }
162
def __len__(self):
163
"""
164
Returns the count of indices in the set.
165
166
Returns:
167
int: Number of indices in set
168
"""
169
170
def __iter__(self):
171
"""
172
Iterates over indices in ascending order.
173
174
Yields:
175
int: Indices in the set from lowest to highest
176
"""
177
178
def __reversed__(self):
179
"""
180
Iterates over indices in descending order.
181
182
Yields:
183
int: Indices in the set from highest to lowest
184
"""
185
186
def __eq__(self, other):
187
"""
188
Compares index sets for equality.
189
190
Args:
191
other: Another NSIndexSet to compare
192
193
Returns:
194
bool: True if index sets contain same indices
195
"""
196
197
def __ne__(self, other):
198
"""
199
Compares index sets for inequality.
200
201
Args:
202
other: Another NSIndexSet to compare
203
204
Returns:
205
bool: True if index sets contain different indices
206
"""
207
208
def __contains__(self, value):
209
"""
210
Checks if index set contains specific index.
211
212
Args:
213
value (int): Index to check for
214
215
Returns:
216
bool: True if index is in set
217
"""
218
```
219
220
#### NSMutableIndexSet Additional Enhancements
221
222
```python { .api }
223
def clear(self):
224
"""
225
Removes all indices from the set.
226
"""
227
228
def add(self, value):
229
"""
230
Adds index to the set.
231
232
Args:
233
value (int): Index to add
234
"""
235
236
def remove(self, value):
237
"""
238
Removes index from the set.
239
240
Args:
241
value (int): Index to remove
242
"""
243
```
244
245
#### Basic Mapping Enhancements
246
247
Classes enhanced with dictionary-like interface for key-value access to their underlying data stores.
248
249
```python { .api }
250
# NSMergeConflict (mutable dictionary interface)
251
def __getitem__(self, key): ...
252
def __setitem__(self, key, value): ...
253
def __delitem__(self, key): ...
254
def __len__(self): ...
255
def __iter__(self): ...
256
def keys(self): ...
257
def values(self): ...
258
def items(self): ...
259
def get(self, key, default=None): ...
260
def clear(self): ...
261
def update(self, other): ...
262
263
# NSUbiquitousKeyValueStore (read-only dictionary interface)
264
def __getitem__(self, key): ...
265
def __len__(self): ...
266
def __iter__(self): ...
267
def keys(self): ...
268
def values(self): ...
269
def items(self): ...
270
def get(self, key, default=None): ...
271
272
# NSUserDefaults (read-only dictionary interface)
273
def __getitem__(self, key): ...
274
def __len__(self): ...
275
def __iter__(self): ...
276
def keys(self): ...
277
def values(self): ...
278
def items(self): ...
279
def get(self, key, default=None): ...
280
```
281
282
#### NSLocale Enhancements (Dictionary-like Access)
283
284
```python { .api }
285
def __getitem__(self, key):
286
"""
287
Gets locale information for key using dictionary-style access.
288
289
Args:
290
key: Locale information key (NSLocale constants)
291
292
Returns:
293
Locale-specific information for key
294
295
Example:
296
locale = NSLocale.currentLocale()
297
country = locale[NSLocaleCountryCode]
298
currency = locale[NSLocaleCurrencyCode]
299
"""
300
```
301
302
#### NSIndexPath Enhancements
303
304
```python { .api }
305
def __len__(self):
306
"""
307
Returns the length of the index path.
308
309
Returns:
310
int: Number of indices in the path
311
"""
312
313
def __getitem__(self, index):
314
"""
315
Gets index at specific position in the path.
316
317
Args:
318
index (int): Position in the index path
319
320
Returns:
321
int: Index value at position
322
"""
323
324
def __add__(self, index):
325
"""
326
Creates new index path with additional index appended.
327
328
Args:
329
index (int): Index to append
330
331
Returns:
332
NSIndexPath: New index path with appended index
333
"""
334
```
335
336
#### NSURL Enhancements
337
338
```python { .api }
339
def __fspath__(self):
340
"""
341
Returns file system path for use with pathlib and os.path.
342
343
Returns:
344
str: File system path string
345
346
Example:
347
url = NSURL.fileURLWithPath_("/Users/user/document.txt")
348
path = os.path.dirname(url) # Uses __fspath__ automatically
349
pathlib_path = pathlib.Path(url) # Also works
350
"""
351
```
352
353
### AppKit Class Enhancements
354
355
Enhanced methods automatically available on AppKit framework classes.
356
357
#### NSFontDescriptor Enhancements (Dictionary-like Access)
358
359
```python { .api }
360
def __getitem__(self, key):
361
"""
362
Gets font attribute value using dictionary-style access.
363
364
Args:
365
key: Font attribute key (NSFontAttributeName constants)
366
367
Returns:
368
Font attribute value
369
370
Raises:
371
KeyError: If attribute key not found
372
373
Example:
374
descriptor = NSFontDescriptor.fontDescriptorWithName_size_("Helvetica", 12)
375
family = descriptor[NSFontFamilyAttribute]
376
size = descriptor[NSFontSizeAttribute]
377
"""
378
379
def get(self, key, default=None):
380
"""
381
Gets font attribute value with optional default.
382
383
Args:
384
key: Font attribute key
385
default: Value to return if key not found
386
387
Returns:
388
Font attribute value or default
389
390
Example:
391
descriptor = NSFontDescriptor.fontDescriptorWithName_size_("Helvetica", 12)
392
traits = descriptor.get(NSFontTraitsAttribute, {})
393
weight = traits.get(NSFontWeightTrait, 0.0) if traits else 0.0
394
"""
395
```
396
397
### Context Manager Classes
398
399
Classes that provide Python context manager support for managing macOS system behaviors during critical operations.
400
401
```python { .api }
402
class NSDisabledAutomaticTermination:
403
"""
404
Context manager for temporarily disabling automatic application termination.
405
406
Prevents macOS from automatically terminating the application during
407
critical operations that must complete without interruption.
408
409
Usage:
410
with NSDisabledAutomaticTermination():
411
# Critical work that shouldn't be interrupted
412
save_all_documents()
413
perform_cleanup_operations()
414
"""
415
416
class NSDisabledSuddenTermination:
417
"""
418
Context manager for temporarily disabling sudden application termination.
419
420
Prevents macOS from suddenly terminating the application (e.g., during
421
logout or shutdown) while important operations are in progress.
422
423
Usage:
424
with NSDisabledSuddenTermination():
425
# Critical work that needs to complete
426
export_user_data()
427
synchronize_with_server()
428
"""
429
```
430
431
### Safe NSObject Method Enhancements
432
433
Enhanced NSObject methods that provide safe selector execution with proper exception handling.
434
435
```python { .api }
436
def pyobjc_performSelectorOnMainThread_withObject_waitUntilDone_(self, sel, obj, wait):
437
"""
438
Safely executes selector on main thread with exception handling.
439
440
Args:
441
sel: Selector to execute
442
obj: Object argument to pass to selector
443
wait (bool): Whether to wait for completion
444
445
Returns:
446
Result of selector execution or None if exception occurred
447
"""
448
449
def pyobjc_performSelectorOnMainThread_withObject_modes_(self, sel, obj, modes):
450
"""
451
Safely executes selector on main thread in specific run loop modes.
452
453
Args:
454
sel: Selector to execute
455
obj: Object argument to pass to selector
456
modes: List of run loop modes for execution
457
458
Returns:
459
Result of selector execution or None if exception occurred
460
"""
461
462
def pyobjc_performSelectorOnMainThread_withObject_(self, sel, obj):
463
"""
464
Safely executes selector on main thread and returns result.
465
466
Args:
467
sel: Selector to execute
468
obj: Object argument to pass to selector
469
470
Returns:
471
Result of selector execution or None if exception occurred
472
"""
473
474
def pyobjc_performSelector_onThread_withObject_waitUntilDone_(self, sel, thread, obj, wait):
475
"""
476
Safely executes selector on specific thread with exception handling.
477
478
Args:
479
sel: Selector to execute
480
thread: NSThread to execute on
481
obj: Object argument to pass to selector
482
wait (bool): Whether to wait for completion
483
484
Returns:
485
Result of selector execution or None if exception occurred
486
"""
487
488
def pyobjc_performSelector_onThread_withObject_modes_(self, sel, thread, obj, modes):
489
"""
490
Safely executes selector on thread in specific run loop modes.
491
492
Args:
493
sel: Selector to execute
494
thread: NSThread to execute on
495
obj: Object argument to pass to selector
496
modes: List of run loop modes for execution
497
498
Returns:
499
Result of selector execution or None if exception occurred
500
"""
501
502
def pyobjc_performSelector_onThread_withObject_(self, sel, thread, obj):
503
"""
504
Safely executes selector on thread and returns result.
505
506
Args:
507
sel: Selector to execute
508
thread: NSThread to execute on
509
obj: Object argument to pass to selector
510
511
Returns:
512
Result of selector execution or None if exception occurred
513
"""
514
515
def pyobjc_performSelectorInBackground_withObject_(self, sel, obj):
516
"""
517
Safely executes selector in background thread.
518
519
Args:
520
sel: Selector to execute
521
obj: Object argument to pass to selector
522
523
Returns:
524
None (executes asynchronously)
525
"""
526
527
def pyobjc_performSelector_withObject_afterDelay_(self, sel, obj, delay):
528
"""
529
Safely executes selector after specified delay.
530
531
Args:
532
sel: Selector to execute
533
obj: Object argument to pass to selector
534
delay (float): Delay in seconds before execution
535
536
Returns:
537
None (executes asynchronously)
538
"""
539
540
def pyobjc_performSelector_withObject_afterDelay_inModes_(self, sel, obj, delay, modes):
541
"""
542
Safely executes selector after delay in specific run loop modes.
543
544
Args:
545
sel: Selector to execute
546
obj: Object argument to pass to selector
547
delay (float): Delay in seconds before execution
548
modes: List of run loop modes for execution
549
550
Returns:
551
None (executes asynchronously)
552
"""
553
```
554
555
## Usage Examples
556
557
### Dictionary-like Collection Access
558
559
```python
560
import Foundation
561
562
# NSCache with dictionary interface
563
cache = Foundation.NSCache.alloc().init()
564
cache.setName_("MyCache")
565
566
# Dictionary-style access
567
cache["user_session"] = user_session_data
568
cache["app_preferences"] = preferences_dict
569
570
# Get with default
571
session = cache.get("user_session", create_default_session())
572
573
# Check and remove
574
if "old_cache_key" in cache:
575
del cache["old_cache_key"]
576
577
# Clear all cached data
578
cache.clear()
579
```
580
581
### Set-like Collection Operations
582
583
```python
584
import Foundation
585
586
# NSMutableIndexSet with set interface
587
selected_rows = Foundation.NSMutableIndexSet.indexSet()
588
589
# Add indices like a set
590
selected_rows.add(0)
591
selected_rows.add(5)
592
selected_rows.add(10)
593
594
# Iterate over selected indices
595
for row_index in selected_rows:
596
print(f"Row {row_index} is selected")
597
598
# Check membership
599
if 5 in selected_rows:
600
print("Row 5 is selected")
601
602
# Set operations
603
other_selection = Foundation.NSIndexSet.indexSetWithIndex_(3)
604
selected_rows.addIndexes_(other_selection)
605
606
# Clear selection
607
selected_rows.clear()
608
```
609
610
### Hash Table Operations
611
612
```python
613
import Foundation
614
615
# Create hash table with strong memory semantics
616
hash_table = Foundation.NSHashTable.hashTableWithOptions_(
617
Foundation.NSPointerFunctionsStrongMemory
618
)
619
620
# Add items like a set
621
hash_table.add("item1")
622
hash_table.add("item2")
623
hash_table.add(None) # Automatically converted to NSNull
624
625
# Iterate over items
626
for item in hash_table:
627
print(f"Hash table contains: {item}") # None values converted back
628
629
# Check membership and remove
630
if "item1" in hash_table:
631
hash_table.remove("item1")
632
633
# Get arbitrary item
634
if len(hash_table) > 0:
635
random_item = hash_table.pop()
636
print(f"Removed item: {random_item}")
637
```
638
639
### Enhanced String and Path Operations
640
641
```python
642
import Foundation
643
import os
644
import pathlib
645
646
# NSAttributedString length
647
attr_string = Foundation.NSAttributedString.alloc().initWithString_("Hello, World!")
648
print(f"String length: {len(attr_string)}") # Uses __len__ enhancement
649
650
# NSURL path integration
651
file_url = Foundation.NSURL.fileURLWithPath_("/Users/user/Documents/file.txt")
652
653
# Use with standard Python path operations
654
directory = os.path.dirname(file_url) # Uses __fspath__ enhancement
655
file_path = pathlib.Path(file_url) # Also uses __fspath__
656
parent_dir = file_path.parent
657
file_exists = file_path.exists()
658
```
659
660
### Font Descriptor Dictionary Access
661
662
```python
663
import AppKit
664
665
# Create font descriptor
666
descriptor = AppKit.NSFontDescriptor.fontDescriptorWithName_size_("Helvetica Neue", 14)
667
668
# Dictionary-style access to attributes
669
family_name = descriptor[AppKit.NSFontFamilyAttribute]
670
font_size = descriptor[AppKit.NSFontSizeAttribute]
671
672
# Safe access with defaults
673
traits = descriptor.get(AppKit.NSFontTraitsAttribute, {})
674
if traits:
675
weight = traits.get(AppKit.NSFontWeightTrait, 0.0)
676
slant = traits.get(AppKit.NSFontSlantTrait, 0.0)
677
print(f"Font weight: {weight}, slant: {slant}")
678
679
# Create modified descriptor
680
bold_descriptor = descriptor.fontDescriptorWithSymbolicTraits_(
681
AppKit.NSFontBoldTrait
682
)
683
```
684
685
### Context Managers for System Behavior
686
687
```python
688
import Foundation
689
690
# Disable automatic termination during critical operations
691
with Foundation.NSDisabledAutomaticTermination():
692
# Perform critical work that shouldn't be interrupted
693
backup_user_data()
694
synchronize_settings()
695
cleanup_temporary_files()
696
# Automatic termination re-enabled automatically
697
698
# Disable sudden termination during data operations
699
with Foundation.NSDisabledSuddenTermination():
700
# Ensure these operations complete even during shutdown
701
save_document_changes()
702
commit_database_transaction()
703
# Sudden termination re-enabled automatically
704
```
705
706
### Safe Selector Execution
707
708
```python
709
import Foundation
710
import AppKit
711
712
# Create string object
713
string_obj = Foundation.NSString.stringWithString_("hello world")
714
715
# Safe execution on main thread
716
uppercased = string_obj.pyobjc_performSelectorOnMainThread_withObject_waitUntilDone_(
717
"uppercaseString",
718
None, # no argument needed
719
True # wait for result
720
)
721
print(f"Uppercased: {uppercased}")
722
723
# Background execution with error handling
724
def background_processing():
725
result = string_obj.pyobjc_performSelectorInBackground_withObject_(
726
"capitalizedString",
727
None
728
)
729
# Result will be None if executed in background
730
731
# Delayed execution
732
string_obj.pyobjc_performSelector_withObject_afterDelay_(
733
"uppercaseString",
734
None,
735
2.0 # Execute after 2 seconds
736
)
737
```
738
739
### Locale Information Access
740
741
```python
742
import Foundation
743
744
# Get current locale
745
locale = Foundation.NSLocale.currentLocale()
746
747
# Dictionary-style access to locale information
748
country_code = locale[Foundation.NSLocaleCountryCode]
749
language_code = locale[Foundation.NSLocaleLanguageCode]
750
currency_code = locale[Foundation.NSLocaleCurrencyCode]
751
currency_symbol = locale[Foundation.NSLocaleCurrencySymbol]
752
753
print(f"Country: {country_code}")
754
print(f"Language: {language_code}")
755
print(f"Currency: {currency_code} ({currency_symbol})")
756
757
# Create specific locale and access its properties
758
us_locale = Foundation.NSLocale.localeWithLocaleIdentifier_("en_US")
759
us_currency = us_locale[Foundation.NSLocaleCurrencyCode] # "USD"
760
```
761
762
### Index Path Operations
763
764
```python
765
import Foundation
766
767
# Create index path for table view
768
section_0_row_5 = Foundation.NSIndexPath.indexPathForRow_inSection_(5, 0)
769
770
# Enhanced operations
771
path_length = len(section_0_row_5) # Returns 2 (section and row)
772
section = section_0_row_5[0] # Get section index
773
row = section_0_row_5[1] # Get row index
774
775
# Create new path by adding index
776
extended_path = section_0_row_5 + 3 # Adds index 3 to path
777
778
print(f"Original path length: {path_length}")
779
print(f"Section: {section}, Row: {row}")
780
print(f"Extended path: {extended_path}")
781
```
782
783
## Automatic Enhancement Application
784
785
All these enhancements are applied automatically when the respective framework modules are imported:
786
787
```python
788
import Foundation # Automatically applies Foundation enhancements
789
import AppKit # Automatically applies AppKit enhancements
790
791
# Enhancements are immediately available on all instances
792
cache = Foundation.NSCache.alloc().init()
793
cache["key"] = "value" # Dictionary-style access works immediately
794
795
descriptor = AppKit.NSFontDescriptor.fontDescriptorWithName_size_("Arial", 12)
796
family = descriptor[AppKit.NSFontFamilyAttribute] # Dictionary access works
797
```
798
799
The enhancements provide a more Pythonic interface to Cocoa objects while maintaining full compatibility with standard Objective-C methods and patterns.