kivy / pyobjus

Access Objective-C classes from Python
https://pyobjus.readthedocs.io
MIT License
177 stars 47 forks source link

autoclass('NSString', ... ) => 'TypeError: expected bytes, str found' #76

Open HeRo002 opened 3 years ago

HeRo002 commented 3 years ago

After converting the Print() statements in https://github.com/kivy/pyobjus/blob/master/examples/using_autoclass.py from Python2 to Python3 I deployed it on the iPhone 7 simulator in Xcode ver. 12.4 on MacOS Catalina ver. 10.15.7. The first few statements work fine, but line 17:

NSString = autoclass('NSString', load_class_methods=['alloc'], load_instance_methods=['init', 'initWithString:', 'UTF8String'])

results in this error:

Traceback (most recent call last):
  File "/Users/henrik/pyobjus-original-example-ny-ios/YourApp/main.py", line 17, in <module>
  File "pyobjus/pyobjus.pyx", line 719, in pyobjus.pyobjus.autoclass
  File "pyobjus/pyobjus.pyx", line 556, in pyobjus.pyobjus.class_get_partial_methods
TypeError: expected bytes, str found
2021-03-19 20:57:08.013155+0100 pyobjus-original-example-ny[12926:512737] Application quit abnormally!
2021-03-19 20:57:08.021033+0100 pyobjus-original-example-ny[12926:512737] Leaving
misl6 commented 3 years ago

We should update the examples (or the code), so please keep the issue open.

Meanwhile, you should be able to get it working by using:

NSString = autoclass('NSString', load_class_methods=[b'alloc'], load_instance_methods=[b'init', b'initWithString:', b'UTF8String'])
HeRo002 commented 3 years ago

Yes! Thank you! That works!

I don't have any experience with suggesting changes to code here on github. But here comes my updated - and working - version of https://github.com/kivy/pyobjus/blob/master/examples/using_autoclass.py :

from pyobjus import autoclass

# First we load NSString into pyobjus
NSString = autoclass('NSString')

# Then we can call some class methods of NSString
text = NSString.stringWithUTF8String_('some string')

# Now we can call instance methods
print("1. text.UTF8String() = ", text.UTF8String())

# If you want to improve performance of you app, consider following
print("2. dir(NSString) = ", dir(NSString))

# As you can see, there is a lot of methods which pyobjus is loaded for us.
# If we don't need all of them, we can load only those which we need. Eg:
NSString = autoclass('NSString', load_class_methods=[b'alloc'], load_instance_methods=[b'init', b'initWithString:', b'UTF8String'])

# So if we now see content on NSString object, we will see that we have much less subobjects in NSString
print("3. dir(NSString) (again, now reduced) = ", dir(NSString))

instance = NSString.alloc()
# we limited instance method which will be load also
print("4. dir(instance) = ", dir(instance))

# because we haven't loaded initWithUTF8String: method, this will raise exception
try:
    instance.initWithUTF8String_('some string')
except:
    print("5. EXCEPTION!")

# But we loaded initWithString: method, so we can use that one
print("6. instance.initWithString_(text).UTF8String() = ", instance.initWithString_(text).UTF8String())

# And if you want to reset autoclass caching system, so we can use all methods in next steps,
# you simply need to run this line of code
NSString = autoclass('NSString', reset_autoclass=True)
print("7. dir(NSString) (again) = ", dir(NSString))
text = NSString.stringWithUTF8String_('some string')
print("8. text.UTF8String() = ", text.UTF8String())
print("9. dir(NSString.alloc()) = ", dir(NSString.alloc()))