📲
【print】objc_util からRubicon-ObjC へ移行【デバッグ】
objc_util で独自に作って活用していたもの
objc_util の print デバッグ。Pythonista3 の黒魔術 #Python - Qiita
objc_util オブジェクトの持っているメソッドを確認する時に活用していたが、objc_util 依存なので、Rubicon-ObjC に書き換えた。
Rubicon-ObjC では、objc_util そっくりにはいかないので、(写経しつつ)機能を追加してみた。
実装全容
pdbr.py
import ctypes
import json
from pprint import pprint
from pyrubicon.objc import ObjCInstance, ObjCClass, NSObject
from pyrubicon.objc.runtime import libobjc
__all__ = [
'state',
]
def _get_className_methods(rubicon_object):
if rubicon_object is 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, is_merge_methods: bool = False):
_dic = _get_className_methods(rubicon_obj)
if _dic:
pprint(sorted(set().union(
*list(_dic.values())))) if is_merge_methods else print(
json.dumps(_dic, indent=2))
pprint(list(_dic.keys()))
pprint(rubicon_obj)
else:
print(rubicon_obj)
使い方
# Class の継承順に分け要素を列挙
pdbr.state(オブジェクト)
# 継承関係なく、要素を列挙
pdbr.state(オブジェクト, True)
ざっくり解説
ObjCInstance
class の__dir__
を写経。
本家(objc_util)だと super class の method も、list
で一括にまとめられていたが、今回は class ごとに取得をして、dict
形式として key value で持たせている。
Discussion