Skip to content

ref: migrate Cocoa bindings to SentryObjC surface (partial #5444) - #5450

Draft
jamescrosswell wants to merge 3 commits into
mainfrom
5444-rebind-sentryobjc
Draft

ref: migrate Cocoa bindings to SentryObjC surface (partial #5444)#5450
jamescrosswell wants to merge 3 commits into
mainfrom
5444-rebind-sentryobjc

Conversation

@jamescrosswell

@jamescrosswell jamescrosswell commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Caution

I think we need to see what shape the new CocoaSDK APIs will take before we can finalise this PR... until we have a solution for ISentrySerializable in the new APIs, we can't retire the old APIs anyway... so don't really get any benefit from merging until then.

Summary

Partial work on #5444 — the mechanical rebind of Sentry.Bindings.Cocoa from the classic Sentry* Objective-C classes (in Sentry.framework) to the new SentryObjC* classes. This is the "mechanical rebind" scoped in the issue's Rebinding section; the two "to be decided" items (scope→event enrichment and the exported SentrySerializable protocol) are intentionally left as classic holdouts, so this does not close the issue and Sentry.xcframework is still shipped.

Tip

This looks like a massive commit (and it is) but the bulk of the changes are in the ApiDefinitions.cs file, which is 100% generated code - so not something we need to review in detail (it's validated by the proper building and functioning of the code).

image

What changed

  • scripts/generate-cocoa-bindings.ps1 — binds the SentryObjC.h umbrella header only. It supersedes the classic Sentry.h / Sentry-Swift.h surface as well as the individually-listed SentryObjC* internal headers, and exposes the full public surface (options, SDK entry point, event model, scope, enums) plus the structured hybrid API (SentryObjCSDK.internal, incl. debug images). Framework-style <SentryObjC/…> includes are patched to local quotes for sharpie.
  • scripts/patch-cocoa-bindings.cs — keep-list and per-type rules retargeted to the SentryObjC* names. SentryObjCSDK now keeps the public entry points the .NET SDK calls (startWithOptions / configureScope / crash / crashedLastRun) alongside the internal accessor; SentryObjCInternalApi additionally keeps debug. The SentryObjC enums are no longer dropped.
  • Regenerated ApiDefinitions.cs / StructsAndEnums.cs.
  • PrivateApiDefinitions.cs — replaced the old private-scope partial with a small, self-contained classic Sentry.framework remnant (SentrySDK.configureScope, SentryScope.applyToEvent, SentryEvent.context, and the SentrySerializable protocol) for the two holdouts. These classes still ship in Sentry.framework (linked alongside SentryObjC), so the hand-written bindings resolve at runtime.
  • Consumers under src/Sentry/Platforms/Cocoa/ migrated to SentryObjC*. Most of the churn is absorbed by the aliases in Sentry.Cocoa.props; CFunctions now loads debug images from SentryObjCSDK.internal.debug.images; CocoaEventProcessor routes the enrichment holdout through a new SentryCocoaLegacySdk alias.
  • Sentry.Bindings.Cocoa.csproj — the SupportDelegates.g.cs internalizing workaround now only runs when bgen actually emits that file. The SentryObjC surface uses inline Func/Action callbacks (no named delegates), whose trampolines bgen emits as internal delegates in Trampolines.g.cs, so there is nothing to patch.

Validation

src/Sentry.Bindings.Cocoa and src/Sentry both build for net9.0-ios and net9.0-maccatalyst locally (Xcode 26.6, cocoa 9.23.0).

Note: the generated *.cs are produced by Objective Sharpie; regenerating on a different Xcode/iOS SDK can produce cosmetic diffs (the dirty-check in CI is SDK-sensitive).

Related: #5444

🤖 Generated with Claude Code

#skip-changelog

Rebind the generated Sentry.Bindings.Cocoa surface from the classic Sentry*
Objective-C classes to the new SentryObjC* classes (options, SDK entry point,
event model, scope, enums, and debug images via [SentryObjCSDK internal].debug).

- generate-cocoa-bindings.ps1 now binds the SentryObjC umbrella header only.
- patch-cocoa-bindings.cs keeps the SentryObjC* surface the .NET SDK consumes and
  the public SDK entry points (startWithOptions/configureScope/crash) plus the
  hybrid `internal` accessor.
- Consumers under src/Sentry/Platforms/Cocoa migrated to the SentryObjC* types;
  debug images now come from the structured internal.debug API.
- PrivateApiDefinitions.cs keeps a minimal classic Sentry.framework remnant for the
  two holdouts that SentryObjC* does not yet expose: scope.applyToEvent enrichment
  (CocoaEventProcessor) and the SentrySerializable protocol used by envelope
  serialization. These are the "to be decided" parts of #5444 and are left as-is.

This is a partial step: Sentry.xcframework is still shipped, so it does not close
the issue.

#skip-changelog

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jamescrosswell jamescrosswell added the skip-changelog Suppress automatic changelog generation via Craft label Jul 27, 2026
@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.69%. Comparing base (b52eac9) to head (5625d2c).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5450      +/-   ##
==========================================
+ Coverage   74.62%   74.69%   +0.07%     
==========================================
  Files         512      512              
  Lines       18672    18722      +50     
  Branches     3657     3660       +3     
==========================================
+ Hits        13934    13985      +51     
  Misses       3865     3865              
+ Partials      873      872       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bitsandfoxes

Copy link
Copy Markdown
Contributor

bless your kind heart for tackling this

jamescrosswell and others added 2 commits July 28, 2026 10:21
CocoaExtensionsTests and the iOS-conditional SentrySdkTests block referenced the
classic Sentry* binding types (SentryEvent, SentryException, SentryBreadcrumb,
SentryUser, SentryLevel), which were renamed to SentryObjC* in the rebind. Point
them at the SentryObjC* equivalents so the iOS test project compiles.

#skip-changelog

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The classic SentryEvent exposed serialize() (via SentrySerializable), which
ToSentryEvent used to round-trip a native event into a managed one through JSON.
SentryObjCEvent exposes no serialize(), so that path returned null - which made
the native beforeSend/event-processor pipeline bail (event dropped, callbacks
skipped) and NRE'd the tests that assert on the converted event.

Reconstruct the managed SentryEvent directly from the SentryObjCEvent properties
instead, mapping the same subset CopyToCocoaSentryEvent writes back plus the
exception from the native NSError. Adds ToSentryMessage and a name-correct
ToSentryLevelOrNull (SentryObjCLevel has a leading None member, so a direct cast
would be off by one).

Verified locally against the iOS device test suite (2698 tests, 0 failed),
including the four previously-failing CocoaExtensionsTests / SentrySdkTests cases.

#skip-changelog

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment on lines +119 to +122
<!-- Workaround for https://github.com/xamarin/xamarin-macios/issues/15299.
Only runs when bgen actually emits SupportDelegates.g.cs (i.e. when the binding declares
named delegate types). The SentryObjC surface uses only inline Func/Action callbacks, whose
trampolines bgen emits as internal delegates in Trampolines.g.cs, so no patching is needed. -->

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<!-- Workaround for https://github.com/xamarin/xamarin-macios/issues/15299.
Only runs when bgen actually emits SupportDelegates.g.cs (i.e. when the binding declares
named delegate types). The SentryObjC surface uses only inline Func/Action callbacks, whose
trampolines bgen emits as internal delegates in Trampolines.g.cs, so no patching is needed. -->
<!-- Workaround for https://github.com/xamarin/xamarin-macios/issues/15299. -->

return null;
// Unlike the classic SentryEvent, SentryObjCEvent exposes no serialize() to round-trip through
// JSON, so we reconstruct the managed event from its properties. We map the same subset that
// CopyToCocoaSentryEvent writes back, plus the exception derived from the native NSError.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there's some symmetry to this (matching CopyToCocoaSentryEvent) so we could go down that route. It would be nicer/easier if we could rely on serialisation to convert events from Cocoa to .NET and back again (we have to maintain the serialisation code to be able to send this stuff to Sentry anyway - so we get .NET <-> Cocoa conversion for free if we do this).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changelog Suppress automatic changelog generation via Craft

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants