Skip to content

Add “Object Explorer” Runtime Inspector Feature #154

Description

@maatheusgois-dd

Description

Summary
DebugSwift currently offers a rich set of debugging utilities (crash reports, network logs, view overlays, performance monitors, etc.) that make inspecting and interacting with an app much easier ([github.com]1, [github.com]2). However, it lacks a dedicated, in-app “Object Explorer” that lets developers browse any live Swift/Objective-C object’s properties, methods, ivars, and associated state at runtime ([github.com]3, [github.com]4). Adding this feature would greatly augment DebugSwift’s toolkit by giving real-time introspection similar to [FLEX](https://github.com/FLEXTool/FLEX) but tailored for Swift projects ([github.com]3, [github.com]5).

Motivation and Benefits

  1. Deep Runtime Introspection

    • Developers often need to inspect the internal state of complex view controllers, model objects, and system frameworks while debugging. An integrated “Object Explorer” would allow live inspection of any instance, including its class name, memory address, property values, and method signatures ([github.com]3, [github.com]4).
    • This capability, already proven valuable in FLEX (which offers “View all ivars, properties, and methods on any Objective-C object” at runtime), would be hugely beneficial to Swift developers by bridging the gap between compile-time APIs and runtime state ([github.com]3, [github.com]5).
  2. Enhanced Debugging Workflows

    • With an Object Explorer, developers can navigate into nested objects (e.g. the view hierarchy of a UIViewController) and modify values on the fly—similar to FLEX’s “edit property” or “invoke method” flows ([github.com]3, [github.com]6).
    • This reduces reliance on print statements or breakpoints to examine runtime data, streamlining workflows for diagnosing UI layout issues, state inconsistencies, or unexpected values in Swift code.
  3. Consistent UI/UX

    • By following DebugSwift’s existing UI patterns (table views, modal controllers, toast alerts), the Object Explorer can feel like a natural extension of the toolkit, maintaining a consistent look and behavior ([github.com]1, [cocoapods.org]7).

Proposed Feature Overview

  1. Object Explorer Entry Point

    • Add a new tab or menu item labeled “Object Explorer” inside the DebugSwift overlay UI (e.g. alongside “Console,” “Network Logs,” “User Defaults”) ([github.com]1, [github.com]2).

    • When tapped, present a search bar allowing the user to input either:

      • A Swift/Objective-C class name (to list all live instances, if it’s a class).
      • A specific object pointer/address (for direct inspection).
      • An expression or variable name (if the app exposes a registry of objects).
  2. Top-Level Explorer Screen

    • Implement a UITableViewController (e.g. DSObjectExplorerViewController) that displays the target object’s “sections,” such as:

      • Identity: Class name, memory address, whether it’s a class object vs. instance.
      • Properties: All Swift var/let and Objective-C @property values (using Mirror API for Swift and class_copyPropertyList for Obj-C).
      • Ivars (only for bridged Objective-C classes): List ivars via class_copyIvarList.
      • Methods: List selectors (via class_copyMethodList) or Swift method names (via Mirror combined with the Swift runtime API).
      • Hierarchy: Superclass chain, subclasses (using runtime scans).
      • Associated Objects: Any associated objects (via objc_getAssociatedObject).
      • View Hierarchy: If the object is a UIView or UIViewController, show its subviews or child view controllers.
  3. Navigation & Editable Detail Screens

    • When a row is selected:

      • If it’s a property/ivar whose type is inspectable (e.g. String, Int, NSObject *, UIView *), push a new explorer for the tapped value.
      • If it’s a numeric or string property that’s writable, present an inline editor (text field, slider, etc.) to change the value and apply it immediately.
      • If it’s a method, open a modal allowing the user to input arguments (for simple types) and invoke the method, with return values printed in a console or alert.
  4. Implementation Sketch

    • Reflection/Introspection Layer

    • View Controller & UI Layer

      • Create DSObjectExplorerSection protocol mirroring FLEXObjectExplorerSection (with methods: isAvailable(for:), numberOfRows(), title(), configure(cell:forRow:), and didSelect(row:in:)) ([github.com]3, [github.com]4).

      • Implement concrete sections:

        1. DSIdentitySection (class name + address).
        2. DSPropertySection (Swift + Obj-C properties).
        3. DSIvarSection (Obj-C ivars only).
        4. DSMethodSection (selectors and simple Swift methods).
        5. DSAssociatedObjectsSection.
        6. DSViewHierarchySection.
    • Bridging Swift & Obj-C

      • Since DebugSwift already depends on Objective-C and Swift code coexisting, you can import <objc/runtime.h> alongside Swift’s reflection utilities.
      • For pure Swift classes without @objc annotations, use Mirror only; for classes marked @objcMembers or inheriting from NSObject, you can also use Objective-C runtime APIs.
  5. Registration & Defaults

How to Get Started

  1. Fork & Branch

  2. Create Protocol & Base Classes

    • Define DSObjectExplorerSection.swift (or .m/.h if you prefer Objective-C) to outline the section API.
    • Add DSObjectExplorerViewController.swift as a subclass of UITableViewController, initializing with any Any object and calling a buildSections() method.
  3. Implement Core Sections

    • Identity: Implement DSIdentitySection. Use type(of: obj) for the class name (Swift) or NSStringFromClass(object_getClass(obj)) if it’s an Objective-C object ([github.com]3, [github.com]4).
    • Property & Ivar: For Swift, use Mirror(reflecting:). For Obj-C, use class_copyPropertyList and class_copyIvarList.
    • Method: Use class_copyMethodList for Obj-C. For Swift, enumerate Mirror’s .children and filter for function types by testing Mirror.Child’s value with type(of:) is Function ([github.com]3, [github.com]3).
  4. Navigation & Editors

    • In didSelectRow(at:), determine the selected item’s type. If it’s a nested object (e.g. a UIView within a UIViewController), instantiate a new explorer for that nested instance.
    • For primitive types (String, Int, Bool), present an UIAlertController with a text field to allow editing and then set the new value using Key-Value Coding (setValue(_:forKey:) for Obj-C) or by reconstructing the object in Swift (if it’s a var) ([github.com]3, [github.com]5).
  5. Testing & Examples

    • Test with simple objects (e.g. a UILabel instance) to ensure properties like text, font, frame are displayed and editable.
    • Test with custom Swift classes that have nested objects (e.g. a ViewModel struct with properties) to verify that Mirror introspection works.
    • Validate that invoking methods with no parameters (e.g. calling view.layoutIfNeeded()) shows expected behavior.

Implementation References

Example Issue Body

**Feature Request: Add “Object Explorer” Runtime Inspector**

**Background:**  
DebugSwift offers extensive debugging utilities (console logs, network logs, resource explorers, etc.) but lacks a dedicated in-app object inspector. In contrast, [FLEX](https://github.com/FLEXTool/FLEX) provides a powerful Object Explorer that lets developers browse any live Objective-C object’s ivars, properties, methods, and more (see [FLEXObjectExplorerFactory.m](https://github.com/FLEXTool/FLEX/blob/master/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m)) :contentReference[oaicite:21]{index=21}.

**Proposal:**  
Introduce a new “Object Explorer” tab in the DebugSwift overlay. This feature should:  
1. **List Live Instances** for a given class name or allow entering a specific object pointer/address for inspection.  
2. **Display Sections** for:
   - **Identity**: class name, memory address, isClassInstance.  
   - **Properties**: Swift and Obj-C properties using `Mirror` and `class_copyPropertyList`.  
   - **Ivars** (Obj-C only) via `class_copyIvarList`.  
   - **Methods**: selectors (Obj-C via `class_copyMethodList`) and Swift methods (via `Mirror`).  
   - **Associated Objects** using `objc_getAssociatedObject`.  
   - **View Hierarchy** for `UIView`/`UIViewController` types.  

3. **Enable Editing** of writable properties (text fields, sliders, etc.) and **Method Invocation** (no-parameter methods at minimum).  
4. **Follow DebugSwift’s UI Conventions**: Use `UITableViewController` with grouped sections, inline editors via `UIAlertController`, and navigation pushed onto the DebugSwift container’s navigation stack.

**Implementation Steps:**  
1. Create `DSObjectExplorerSection` protocol (similar to `FLEXObjectExplorerSection`).  
2. Implement `DSObjectExplorerViewController` (`UITableViewController`) that builds sections in `buildSections()`.  
3. Add concrete sections (`DSIdentitySection.swift`, `DSPropertySection.swift`, etc.) by leveraging Swift’s `Mirror` and Objective-C runtime functions (see FLEX’s [FLEXIvarSection.m](https://github.com/FLEXTool/FLEX/blob/master/Classes/ObjectExplorers/Sections/FLEXIvarSection.m)) :contentReference[oaicite:22]{index=22}.  
4. Register default “shortcuts” for UIKit classes—e.g., toggle `UIView.backgroundColor`—using a `DSShortcutsSection` modeled after [FLEXShortcutsSection.m](https://github.com/FLEXTool/FLEX/blob/master/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.m) :contentReference[oaicite:23]{index=23}.  
5. Test thoroughly on both Swift-only classes (using `Mirror`) and mixed Obj-C/Swift classes (using a combination of runtime and reflection).

**References:**  
- FLEX repo: [FLEXObjectExplorerFactory](https://github.com/FLEXTool/FLEX/blob/master/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m) :contentReference[oaicite:24]{index=24}  
- FLEX tutorial: “See the properties and ivars on any object” section in README (FLEX) :contentReference[oaicite:25]{index=25}  
- Swift Mirror docs: [Apple Developer – Mirror](https://developer.apple.com/documentation/swift/mirror) :contentReference[oaicite:26]{index=26}  

**Expected Outcome:**  
After implementation, DebugSwift users can open the “Object Explorer” tab, enter a class name (e.g. `UIViewController`) or paste an object address, and interactively navigate through that object’s entire runtime surface (properties, ivars, methods, associated objects, view hierarchy). This will significantly speed up debugging workflows and bring DebugSwift’s capabilities closer to what FLEX offers for Objective-C apps.

Citations

  1. DebugSwift’s existing feature set (App Settings, Console, Performance monitors) ([github.com]1, [github.com]2)
  2. FLEX’s runtime object inspection capabilities (listing ivars, properties, methods) ([github.com]3, [github.com]5)
  3. FLEX’s code for FLEXObjectExplorerFactory.m demonstrating how to push an object explorer for any object ([github.com]5, [github.com]4)
  4. FLEX’s implementation of FLEXIvarSection.m using class_copyIvarList ([github.com]3, [github.com]3)
  5. FLEX’s use of class_copyMethodList in FLEXMethodSection ([github.com]3, [github.com]3)
  6. FLEX’s FLEXShortcutsSection.m demonstrating registration of class-specific actions ([github.com]3, [github.com]8)
  7. Swift’s Mirror reflection API for enumerating Swift object properties (Apple Developer – Mirror) ([github.com]3, [github.com]3)
  8. DebugSwift’s README describing its existing debugging tools (Console, Network Logs, Keychain, User Defaults) ([github.com]1, [github.com]2)
  9. DebugSwift’s CocoaPods integration instructions (to verify how dependencies and modules are organized) ([cocoapods.org]7, [github.com]1)
  10. FLEX’s FLEXAssociatedObjectsSection.m showing how to list associated objects at runtime ([github.com]3, [github.com]3)

Metadata

Metadata

Labels

Advanced 🏆Complex tasks that require deep technical knowledge and expertise in iOS development.

Projects

Status
Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions