📲
【print】objc_util からrubicon-objc へ移行【デバッグ】
objc_util で独自に作って活用していたもの
objc_util のprint デバッグ。Pythonista3 の黒魔術 #Python - Qiita
objc_utilオブジェクトの持っているメソッドを確認する時に活用していたが、objc_util依存なので、rubiconに書き換えた。
rubiconでは、objc_utilそっくりにはいかないので、(写経しつつ)機能を追加してみた。
実装全容
pdbr.py
import ctypes
import json
from pprint import pprint
from rubicon.objc import ObjCInstance, ObjCClass, NSObject
from rubicon.objc.runtime import libobjc
__all__ = [
'state',
]
def _get_className_methods(rubicon_object):
if rubicon_object == None:
return None
objct_class = libobjc.object_getClass(rubicon_object)
py_className_methods = {}
is_flag = False
while objct_class is not None:
py_methods = []
num_methods = ctypes.c_uint(0)
method_list_ptr = libobjc.class_copyMethodList(objct_class,
ctypes.byref(num_methods))
for i in range(num_methods.value):
selector = libobjc.method_getName(method_list_ptr[i])
sel_name = libobjc.sel_getName(selector).decode('ascii')
py_method_name = sel_name.replace(':', '_')
if '.' not in py_method_name:
py_methods.append(py_method_name)
libobjc.free(method_list_ptr)
py_className_methods[str(ObjCInstance(objct_class.value))] = sorted(
set(py_methods))
objct_class = libobjc.class_getSuperclass(objct_class)
if is_flag:
break
if objct_class.value == NSObject.ptr.value:
is_flag = True
return dict(reversed(list(py_className_methods.items())))
def state(rubicon_obj):
_dic = _get_className_methods(rubicon_obj)
if _dic:
data = json.dumps(_dic, indent=2)
print(data)
pprint(list(_dic.keys()))
pprint(rubicon_obj)
else:
print(rubicon_obj)
ざっくり解説
ObjCInstance
classの__dir__
を写経。
本家(objc_util)だとsuper classのmethodも、list
で一括にまとめられていたが、今回はclassごとに取得をして、dict
形式としてkey valueで持たせている。
updateメモ
- 生やしていた引数を削除
- デフォルトで、
NSObject
を先頭に
- デフォルトで、
-
NSObject
のmethod取得が事前決め打ちだったものを、実際に読み込んで格納 - classごとのmethodに分けたが、全体としてどのようなclassを持っているか把握し辛かったので、class名を配列で吐くようにした
-
None
の場合、無限ループになるので、if
で逃している(よく無い)
Discussion