Forum Archive

OneTimeCode

AlbertoAEC

Hello!
I want to make a dialog that ask for a received sms code.
The oficial form is by a parameter of the UITextField but in Pythonista there is not implemented yet. How can I make it by ObjC? I can not import UIKit by ObjCClass because Pythonista drops an error.

https://stackoverflow.com/questions/39631168/automatic-otp-verification-in-ios

Thanks you in advance.
alberto

mikael

@AlbertoAEC, you can use the objc_instance property to get the ObjC instance of the textfield. Although, I cannot find a textContentType property there nor in a subview, and if I did, I would not know what value to set in Python, as the (numeric?) values of the ObjC contants are not documented.

cvp

@AlbertoAEC I don't understand why but

tf = ui.TextField()
tfo = ObjCInstance(tf)
tfo.textField().textContentType = 0

Gives an error

TypeError: expected 4 arguments, got 1

I'm sorry but I can't help anymore

AlbertoAEC

@mikael @cvp Thank you guys for the quick responses.

As far as I understand, the value of the textContentType is a Structure of the type UITextContentType. I think is a internal constant but I don’t know how to get it from pythonista.

Here is the official documentation:
https://developer.apple.com/documentation/uikit/uitextcontenttype/2980930-onetimecode

cvp

@AlbertoAEC I've read it but I don't understand why it says it waits for4 arguments. The structure doesn't seem to have 4 fields...

JonB

print(tfo.textField().setTextContentType_.encoding)

JonB

UITextContentType is an alias for nsString.

Try

UIContentTypeOneTimeCode=c_void_p.in_dll(c, 'UIContentTypeOneTimeCode')
if UIContentTypeOneTimeCode:
   UIContentTypeOneTimeCode = ObjCInstance(UIContentTypeOneTimeCode)

tf=ui.TextField()
tfo=tf.objc_instance.textField()
tfo.setTextContentType_(UIContentTypeOneTimeCode)
JonB

@JonB
if that gives a symbol not found, you might try
UIContentTypeOneTimeCode=ns('UIContentTypeOneTimeCode')

cvp

@JonB yes symbol not found, then TypeError: expected 4 arguments, got 1 in

tfo.setTextContentType_(UIContentTypeOneTimeCode)

As I got early

JonB

@cvp can you print that line I had before to print the encoding?

JonB

or if encoding is not found, try

print(tfo.setTextContentType_.method_cache['0/'][0].encoding) 
cvp

@JonB b'v0@0:0@"NSString"0'

cvp

@JonB print(tfo.setTextContentType_.method_cache['0/'][0].encoding)
AttributeError: 'ObjCInstanceMethod' object has no attribute 'method_cache'

cvp

@JonB tfo.setTextContentType_(UIContentTypeOneTimeCode)
File "/var/containers/Bundle/Application/FED7F8B2-4F86-4833-BCFB-C2F8803CD0F1/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 874, in call
raise TypeError('expected %i arguments, got %i' % (len(argtypes) - 2, len(args)))
TypeError: expected 4 arguments, got 1

JonB

you might also try

tfo.setTextContentType_(UITextContentTypeOneTime, argtypes=[c_void_p], restype=None)

which should fix a botched encoding parse.

cvp

@JonB replaced by

tfo.setTextContentType_(UIContentTypeOneTimeCode, argtypes=[c_void_p], restype=None)

Then crash
```
Fatal Python error: Aborted

Current thread 0x000000016fd07000 (most recent call first):
File "/var/containers/Bundle/Application/FED7F8B2-4F86-4833-BCFB-C2F8803CD0F1/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 897 in call
File "/private/var/mobile/Containers/Shared/AppGroup/668A7D98-7216-47ED-917D-AA0B6173167E/Pythonista3/Documents/MesTests/test6.py", line 12 in


Objective-C exception details:

NSInvalidArgumentException: -[UITextField String"]: unrecognized selector sent to instance 0x103a99c00

Stack trace:

0 CoreFoundation 0x00000001ee36feb8 + 252
1 libobjc.A.dylib 0x00000001ed541a40 objc_exception_throw + 56
2 CoreFoundation 0x00000001ee288d04 + 0
3 UIKitCore 0x000000021b162b38 + 280
4 CoreFoundation 0x00000001ee3757b8 + 1412
5 CoreFoundation 0x00000001ee37745c _CF_forwarding_prep_0 + 92
6 Py3Kit 0x00000001013f0044 ffi_call_SYSV + 68
7 Py3Kit 0x00000001013ebe10 ffi_call_int + 940
8 Py3Kit 0x00000001013e68bc _ctypes_callproc + 700
9 Py3Kit 0x00000001013e0178 PyCFuncPtr_call + 524
10 Py3Kit 0x0000000101210794 PyObject_Call + 124
11 Py3Kit 0x00000001012d9f24 _PyEval_EvalFrameDefault + 12284
12 Py3Kit 0x00000001012dd818 _PyEval_EvalCodeWithName + 3132
13 Py3Kit 0x00000001012de160 _PyFunction_FastCallDict + 340
14 Py3Kit 0x00000001012109bc _PyObject_FastCallDict + 304
15 Py3Kit 0x0000000101210ae4 _PyObject_Call_Prepend + 148
16 Py3Kit 0x0000000101210794 PyObject_Call + 124
17 Py3Kit 0x0000000101270c5c slot_tp_call + 180
18 Py3Kit 0x0000000101210970 _PyObject_FastCallDict + 228
19 Py3Kit 0x0000000101210dbc _PyObject_FastCallKeywords + 192
20 Py3Kit 0x00000001012dcabc call_function + 428
21 Py3Kit 0x00000001012d92c4 _PyEval_EvalFrameDefault + 9116
22 Py3Kit 0x00000001012dd818 _PyEval_EvalCodeWithName + 3132
23 Py3Kit 0x00000001012d6e9c PyEval_EvalCode + 56
24 Py3Kit 0x00000001013061c4 PyRun_FileExFlags + 188
25 Py3Kit 0x0000000101305658 PyRun_SimpleFileExFlags + 252
26 Py3Kit 0x0000000100bac174 -[PYK3Interpreter doRunWithOptions:] + 1176
27 Foundation 0x00000001eee2239c + 336
28 CoreFoundation 0x00000001ee3001cc + 24
29 CoreFoundation 0x00000001ee30014c + 88
30 CoreFoundation 0x00000001ee2ffa30 + 176
31 CoreFoundation 0x00000001ee2fa8fc + 1040
32 CoreFoundation 0x00000001ee2fa1cc CFRunLoopRunSpecific + 436
33 Foundation 0x00000001eecef404 + 300
34 Foundation 0x00000001eecef2b0 + 148
35 Py3Kit 0x0000000100baabb0 -[PYK3Interpreter setupInterpreterThreadRunLoop] + 252
36 Foundation 0x00000001eee221ac + 1040
37 libsystem_pthread.dylib 0x00000001edf8b2ac + 128
38 libsystem_pthread.dylib 0x00000001edf8b20c _pthread_start + 48
39 libsystem_pthread.dylib 0x00000001edf8ecf4 thread_start + 4

End of exception details.```

JonB

you might also need a load_framework('UIKit') before defining the constant via in_dll

cvp

@JonB

load_framework('UIKit')
UIContentTypeOneTimeCode=c_void_p.in_dll(c, 'UIContentTypeOneTimeCode')

Gives

    UIContentTypeOneTimeCode=c_void_p.in_dll(c, 'UIContentTypeOneTimeCode')
ValueError: dlsym(RTLD_DEFAULT, UIContentTypeOneTimeCode): symbol not found

Thus I use

UIContentTypeOneTimeCode=ns('UIContentTypeOneTimeCode')

As you adviced

cvp

@JonB could you remember me the meaning of

b'v0@0:0@"NSString"0'
JonB

Yeah, objc_util gets confused with that.
Restart pyrhonista and try again - the argtypes/restype keywords only work the first time the uiinstancemethod is created I think.

Can you try
c_void_p.in_dll(c,'UITextContentTypeURL')

An see if it complains about symbol not found?

cvp

@JonB at each crash, I remove Pythonista from tasks list and restart...

JonB

Whoops, I think I mistyped before the symbol for one time code should be

UITextContentTypeOneTimeCode

In the in_dll. I had missed the Text bit

cvp

@JonB with UITextContentTypeOneTimeCode, no more symbol not found but same crash...

JonB

Ok, now when you call setTextContentType_(UITextContentTypeOneTimeCode, restype=c_void_p, argtypes=[c_void_p])

I had swapped restype and argtypes, it's possible both were needed

cvp

@JonB just to be sure, my "last" code is

import ui
from objc_util import *

load_framework('UIKit')

UITextContentTypeOneTimeCode=c_void_p.in_dll(c, 'UITextContentTypeOneTimeCode')
#UITextContentTypeOneTimeCode=ns('UITextContentTypeOneTimeCode')

if UITextContentTypeOneTimeCode:
    UITextContentTypeOneTimeCode = ObjCInstance(UITextContentTypeOneTimeCode)

tf = ui.TextField() 
tfo=tf.objc_instance.textField()
print(tfo.setTextContentType_.encoding)

tfo.setTextContentType_(UITextContentTypeOneTimeCode, argtypes=[c_void_p], restype=None)

tf.present('sheet')
cvp

@JonB same crash ( my last code had been written just before your post about swapping, but I also tested it)

#tfo.setTextContentType_(UITextContentTypeOneTimeCode, argtypes=[c_void_p], restype=None)
tfo.setTextContentType_(UITextContentTypeOneTimeCode, restype=c_void_p, argtypes=[c_void_p])
JonB

Sorry, right. Swap restype and argtypes order in the last call, and use restype=c_void_p.

Alternatively we could try

my_method = ObjCInstanceMethod(tfo, 'setTextContentType_')
my_method.encoding='v@:@'

my_method(UITextContentTypeOneTimeCode)

cvp

@JonB same crash with

#tfo.setTextContentType_(UITextContentTypeOneTimeCode, argtypes=[c_void_p], restype=None)
#tfo.setTextContentType_(UITextContentTypeOneTimeCode, restype=c_void_p, argtypes=[c_void_p])

my_method = ObjCInstanceMethod(tfo, 'setTextContentType_')
my_method.encoding='v@:@'
my_method(UITextContentTypeOneTimeCode)
JonB

Ate you sure the traceback is the exactly the same? What is the invalid selector now?

Try using : instead of _ in the selector name... I forget how objcinstancemsthod works

cvp

@JonB with

#tfo.setTextContentType_(UITextContentTypeOneTimeCode, argtypes=[c_void_p], restype=None)
#tfo.setTextContentType_(UITextContentTypeOneTimeCode, restype=c_void_p, argtypes=[c_void_p])

#my_method = ObjCInstanceMethod(tfo, 'setTextContentType_')
my_method = ObjCInstanceMethod(tfo, 'setTextContentType:')
my_method.encoding='v@:@'
my_method(UITextContentTypeOneTimeCode)

Fault log is

Fatal Python error: Aborted

Current thread 0x000000016ff97000 (most recent call first):
  File "/var/containers/Bundle/Application/FED7F8B2-4F86-4833-BCFB-C2F8803CD0F1/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 897 in __call__
  File "/private/var/mobile/Containers/Shared/AppGroup/668A7D98-7216-47ED-917D-AA0B6173167E/Pythonista3/Documents/MesTests/test6.py", line 22 in <module>

------------------------------------------------------------------------

Objective-C exception details:

NSInvalidArgumentException: -[UITextField String"]: unrecognized selector sent to instance 0x104289c00

Stack trace:

0   CoreFoundation                      0x00000001ee36feb8 <redacted> + 252
1   libobjc.A.dylib                     0x00000001ed541a40 objc_exception_throw + 56
2   CoreFoundation                      0x00000001ee288d04 <redacted> + 0
3   UIKitCore                           0x000000021b162b38 <redacted> + 280
4   CoreFoundation                      0x00000001ee3757b8 <redacted> + 1412
5   CoreFoundation                      0x00000001ee37745c _CF_forwarding_prep_0 + 92
6   Py3Kit                              0x0000000101468044 ffi_call_SYSV + 68
7   Py3Kit                              0x0000000101463e10 ffi_call_int + 940
8   Py3Kit                              0x000000010145e8bc _ctypes_callproc + 700
9   Py3Kit                              0x0000000101458178 PyCFuncPtr_call + 524
10  Py3Kit                              0x0000000101288794 PyObject_Call + 124
11  Py3Kit                              0x0000000101351f24 _PyEval_EvalFrameDefault + 12284
12  Py3Kit                              0x0000000101355818 _PyEval_EvalCodeWithName + 3132
13  Py3Kit                              0x0000000101356160 _PyFunction_FastCallDict + 340
14  Py3Kit                              0x00000001012889bc _PyObject_FastCallDict + 304
15  Py3Kit                              0x0000000101288ae4 _PyObject_Call_Prepend + 148
16  Py3Kit                              0x0000000101288794 PyObject_Call + 124
17  Py3Kit                              0x00000001012e8c5c slot_tp_call + 180
18  Py3Kit                              0x0000000101288970 _PyObject_FastCallDict + 228
19  Py3Kit                              0x0000000101354abc call_function + 428
20  Py3Kit                              0x00000001013527b4 _PyEval_EvalFrameDefault + 14476
21  Py3Kit                              0x0000000101355818 _PyEval_EvalCodeWithName + 3132
22  Py3Kit                              0x000000010134ee9c PyEval_EvalCode + 56
23  Py3Kit                              0x000000010137e1c4 PyRun_FileExFlags + 188
24  Py3Kit                              0x000000010137d658 PyRun_SimpleFileExFlags + 252
25  Py3Kit                              0x0000000100c24174 -[PYK3Interpreter doRunWithOptions:] + 1176
26  Foundation                          0x00000001eee2239c <redacted> + 336
27  CoreFoundation                      0x00000001ee3001cc <redacted> + 24
28  CoreFoundation                      0x00000001ee30014c <redacted> + 88
29  CoreFoundation                      0x00000001ee2ffa30 <redacted> + 176
30  CoreFoundation                      0x00000001ee2fa8fc <redacted> + 1040
31  CoreFoundation                      0x00000001ee2fa1cc CFRunLoopRunSpecific + 436
32  Foundation                          0x00000001eecef404 <redacted> + 300
33  Foundation                          0x00000001eecef2b0 <redacted> + 148
34  Py3Kit                              0x0000000100c22bb0 -[PYK3Interpreter setupInterpreterThreadRunLoop] + 252
35  Foundation                          0x00000001eee221ac <redacted> + 1040
36  libsystem_pthread.dylib             0x00000001edf8b2ac <redacted> + 128
37  libsystem_pthread.dylib             0x00000001edf8b20c _pthread_start + 48
38  libsystem_pthread.dylib             0x00000001edf8ecf4 thread_start + 4

End of exception details.
JonB

ok, try

my_method = ObjCInstanceMethod(tfo, 'setTextContentType_')
my_method.sel_name='setTextContentType:'
my_method.encoding=b'v@:@'
my_method(UITextContentTypeOneTimeCode)

i forgot encoding should be bytes, not str. and lets try setting the selName manually.

that should do it.....?

cvp

@JonB Sorry for the delay, dinner time 😢
No crash but how to check if script ok: keyboard of tf seems usual...

JonB

Now THAT I don't know...

what does tfo.textContentType() return?

I think you'd have to text yourself from another phone with a text that has a code. Then you might need to have the auto correct/suggestion thing above the keyboard enabled, and it should show the code as a suggestion.

cvp

@JonB return is None.
Hoping all this spent time will help @AlbertoAEC

JonB

From stack overflow

First of all, the SMS need to have the keyword "code" or "passcode" into their message, and don't use spaces after the code. if you received the SMS and you have the button "Copy Code" then it will works

JonB

@cvp are you on ios12?

Seems like this didn't actually work...

cvp

@JonB iOS 12.1, but don't forget I am not the requester. I only tried to help, without success if without you 😢

AlbertoAEC

@cvp @JonB THANK YOU VERY MUCH!!

It works perfectly.
You can try the code using other content type like phone number.
UITextContentTypeTelephoneNumber

import ui
from objc_util import *

load_framework('UIKit')

UITextContentTypeOneTimeCode=c_void_p.in_dll(c, 'UITextContentTypeTelephoneNumber')

if UITextContentTypeOneTimeCode:
    UITextContentTypeOneTimeCode = ObjCInstance(UITextContentTypeOneTimeCode)

tf = ui.TextField()
tf.keyboard_type = ui.KEYBOARD_NUMBER_PAD
tfo=tf.objc_instance.textField()
print(tfo.setTextContentType_.encoding)

my_method = ObjCInstanceMethod(tfo, 'setTextContentType_')
my_method.sel_name='setTextContentType:'
my_method.encoding=b'v@:@'
my_method(UITextContentTypeOneTimeCode)

tf.present('sheet')

I couldn’t answer to you before because I was working.

Best regards,
Alberto

cvp

@AlbertoAEC 👍 and one proof more, if needed, that @JonB is our guru

cvp

@AlbertoAEC and you can comment the load_framework, I think

#load_framework('UIKit')
AlbertoAEC

@cvp yes, load_framework is no needed.
Thanks to both of you for your time