📲

【print】objc_util からRubicon-ObjC へ移行【デバッグ】

2024/03/30に公開

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)

ざっくり解説

PythonistaAppTemplate/PythonistaAppTemplate/PythonistaKit.framework/pylib/site-packages/objc_util.py at f560f93f8876d82a21d108977f90583df08d55af · omz/PythonistaAppTemplate

ObjCInstance class の__dir__ を写経。
本家(objc_util)だと super class の method も、list で一括にまとめられていたが、今回は class ごとに取得をして、dict 形式として key value で持たせている。

Discussion