Skip to content

Inability to Implement UNUserNotificationCenterDelegate due to Silent Failure with ctypes-based IMPs #653

@onasipim

Description

@onasipim

Describe the bug

Problem Description

Implementing the UNUserNotificationCenterDelegate in pure Python using rubicon-objc appears to be impossible due to a silent failure where the delegate methods are never invoked by iOS. This occurs even when the delegate class is correctly configured with valid method signatures, protocol conformance, and returns True for respondsToSelector_.

Investigation and Findings

My goal was to create a pure Python delegate for handling iOS notifications. I discovered that the UNUserNotificationCenterDelegate methods require completion handlers with extended block type encodings (e.g., @?"v@?Q"), which are not supported by the standard objc_block decorator.
To address this, I developed a patch for rubicon-objc that successfully adds support for these extended signatures. Runtime diagnostics confirm that my patch correctly registers the delegate methods with the exact type encodings required by the UserNotifications framework:

Selector: userNotificationCenter:willPresentNotification:withCompletionHandler:
  - Method Encoding: v@:@@@?"v@?Q"
Selector: userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
  - Method Encoding: v@:@@@?"v@?"

Despite this verifiable success in setting up the delegate, the methods are never called by iOS. No errors or warnings are produced.

Core Limitation and Hypothesis

This leads me to believe that the issue is not with the method signature itself, but with the Method Implementation Pointer (IMP) that rubicon-objc generates from the Python callback via ctypes.
I hypothesize that the modern UserNotifications framework performs a validation check on the IMP and is rejecting the kind of function pointer that ctypes provides. Simpler, older delegate patterns (like those for camera or location) work correctly, suggesting this is a requirement specific to newer, security-sensitive iOS frameworks.

Conclusion and Question

It appears there is a fundamental limitation in using ctypes-based IMPs for certain modern iOS delegate patterns. While a native Objective-C shim is a viable workaround, it defeats the purpose of a pure Python implementation.
Is this a known limitation of rubicon-objc? Is there any potential path forward to make ctypes-generated IMPs compatible with frameworks like UserNotifications, or is this an architectural boundary that cannot be crossed without changes to the core bridging mechanism?

Steps to reproduce

Expected behavior

Screenshots

No response

Environment

  • Python version: 3.13
  • Software versions:
    • Briefcase: 0.3.25
    • Toga: 0.5.2

Logs


Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting detailsMore details are needed before the issue can be triaged.bugA crash or error in behavior.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions