Hilda Objective-C Support¶
Objective-C Classes¶
The same as symbols applies to Objective-C classes name resolution. You can either:
d = NSDictionary.new() # Call its `new` selector
# Which is equivalent to:
NSDictionary = p.objc_get_class('NSDictionary')
d = NSDictionary.new()
# Or you can use the IPython magic function
%objc
NSDictionary
This is possible only since NSDictionary is exported. In case it is not, you must call objc_get_class() explicitly.
As you can see, you can directly access all the class' methods.
Please look what more stuff you can do as shown below:
# Show the class' ivars
print(NSDictionary.ivars)
# Show the class' methods
print(NSDictionary.methods)
# Show the class' properties
print(NSDictionary.properties)
# View class' selectors which are prefixed with 'init'
print(NSDictionary.methods.filter_startswith('init'))
# You can of course use any of `SymbolList` over them, for example:
# this will `po` (print object) all those selectors returned value
NSDictionary.methods.filter_startswith('init').monitor(retval='po')
# Monitor each time any selector in NSDictionary is called
NSDictionary.monitor()
# `force_return` for some specific selector with a hard-coded value (4)
NSDictionary.methods.get('valueForKey:').address.monitor(force_return=4)
# Capture the `self` object at the first hit of any selector
# `True` for busy-wait for object to be captured
dictionary = NSDictionary.capture_self(True)
# Print a colored and formatted version for class layout
dictionary.show()
Objective-C Objects¶
In order to work with Objective-C objects, each symbol contains a property called
objc_symbol. After calling, you can work better with each object:
dict = NSDictionary.new().objc_symbol
dict.show() # Print object layout
# Just like class, you can access its ivars, method, etc...
print(dict.ivars)
# Except now they have values you can view
print(dict._ivarName)
# Or edit
dict._ivarName = value
# And of course you can call the object's methods
# Hilda will checks if the method returned an Objective-C object:
# - If so, call `objc_symbol` upon it for you
# - Otherwise, leave it as a simple `Symbol` object
arr = dict.objectForKey_('keyContainingNSArray')
# You can also call class-methods
# Hilda will call it using either the instance object,
# or the class object respectively of the use
newDict = dict.dictionary()
# Print the retrieved object
print(arr.po())
Also, working with Objective-C objects like this can be somewhat exhausting, so we created the ns/cf
helpers for building Foundation objects from Python values, plus decode_cf() and Symbol.py() for
converting them back:
import datetime
# Using `ns`/`cf` we can just pass a Python dictionary
function_requiring_a_specific_dictionary(p.ns({
'key1': 'string', # will convert to NSString
'key2': True, # will convert to NSNumber
'key3': b'1234', # will convert to NSData
'key4': datetime.datetime(2021, 1, 1) # will convert to NSDate
}))
# And also parse one back into Python
normal_python_dict = p.decode_cf(p.ns({
'key1': 'string', # will convert to NSString
'key2': True, # will convert to NSNumber
'key3': b'1234', # will convert to NSData
'key4': datetime.datetime(2021, 1, 1) # will convert to NSDate
}))
# Equivalent shortcut when you already have a Symbol
normal_python_dict = p.ns({
'key1': 'string',
'key2': True,
'key3': b'1234',
'key4': datetime.datetime(2021, 1, 1)
}).py()
As a last resort, if the object is not serializable for this to work, you can just run pure Objective-C code: