Repository navigation
Conversation
…ive-C facades Meta now builds the Facebook iOS SDK binaries with Xcode releases newer than the ones available on CI runners, and a Swift facade can only import the SDK's Swift interfaces with the exact Swift compiler Meta used. - Port the Login and Share facades from Swift to Objective-C. They call the SDK through its Objective-C headers (including the generated -Swift.h headers), keep the same C entry points and keep the same behaviour. - Replace the SwiftPM dependency with release archives pinned by URL and SHA-256 in DependencyLocks/iOS/lockstate.txt (still SDK 18.0.2). The hashes equal the upstream Package.swift remoteChecksum values. - Build each facade with clang + libtool per slice, then wrap it in the same kfb/kfbshare xcframeworks as before. - Port the Share source invariants to the Objective-C implementation. - Cache the pinned archives in CI instead of the SwiftPM scratch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NativeFacebookShare binds its entry points with static __Internal imports, so the .NET iOS build passes them to the native linker as required symbols for every app. A Login-only build (the default selection) therefore failed to link with "Undefined symbols: _kfb_facebook_share_*" since 1.1.0. When Share is not selected, inject kfbsharestub.xcframework instead of kfbshare.xcframework. It defines the same three entry points on top of Foundation only: configuring logs an error, sharing completes with Failed/share_feature_not_selected and URL handling returns false. Share selections are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Pin the 19.0.0 dynamic xcframework archives. Their SHA-256 values equal the upstream Package.swift remoteChecksum values at tag v19.0.0. - SDK 19 builds its device slice as ios-arm64_arm64e. Resolve the device slice from the packaged xcframework so the privacy-manifest resources keep pointing at existing files. - Document the new iOS 15.0 minimum of the SDK. Meta built 19.0.0 with Xcode 27.1 / Swift 6.4. The Objective-C facades compile and link with Xcode 26.x, which a Swift facade cannot do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add kfbappevents.xcframework, an Objective-C facade over FBSDKAppEvents, FBSDKSettings and FBSDKApplicationDelegate exported as kfb_appevents_* C symbols: - SDK lifecycle: initialize, finished-launching hook, URL and user-activity forwarding (AEM / deep links), SDK version. - Settings: auto-log app events, advertiser ID collection, advertiser tracking (iOS 15-16 only), SKAdNetwork reporting, SDK 19 metadata collection and product-improvement switches, data processing options (LDU) and app-events debug logging. - Logging: activateApp, logEvent (optional valueToSum), logPurchase, flush and flush behaviour. Parameters travel as a JSON object of string or number values. - Identity: anonymous ID, user ID and advanced-matching user data. It only depends on FBSDKCoreKit, which every feature selection already links, so the package injects it for every selection: the managed App Events entry points will be static __Internal imports and must always resolve. The facade never changes a setting on its own. Values set through it are recorded and applied again after SDK initialization so the SDK persists them even when they were set before initialization. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Expose the App Events facade as Kapusch.Facebook.iOS.FacebookAppEvents, bound with static __Internal LibraryImport entry points: - InitializeSdk / FinishedLaunching, HandleOpenUrl and ContinueUserActivity forwarding for AEM and deep links, SdkVersion. - Set/Is pairs for automatic logging, advertiser ID collection, advertiser tracking (iOS 15-16), SKAdNetwork reporting, metadata collection and product improvement; SetDataProcessingOptions and SetDebugLoggingEnabled. - ActivateApp, LogEvent (parameters + optional valueToSum), LogPurchase, typed LogStartTrial / LogSubscribe / LogCompleteRegistration helpers, Flush and flush behaviour. - GetAnonymousId, Set/Clear/GetUserId and advanced-matching user data. Parameters accept strings, numbers and booleans (sent as "1"/"0") and are serialized with Utf8JsonWriter (trim and AOT safe). Add constants for every event name, parameter name, parameter value and user-data type declared by the bundled SDK headers, plus the Android-public activate/deactivate and _valueToSum names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Parse AppEvents in KapuschFacebookFeatures. App Events only needs FBSDKCoreKit, which every selection links, so its facade is always linked; selecting AppEvents alone produces a CoreKit-only build without LoginKit or ShareKit. The default selection stays Login. - Warn about unknown (or wrongly cased) feature names, which were silently ignored before. - Cover the AppEvents, Login;Share;AppEvents and default selections in the feature-selection test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NativeFacebookShare.ConfigureAndInitialize forces automatic app events logging off and advertiser ID collection / advertiser tracking to trackingAllowed. Once the app manages these settings through FacebookAppEvents (for example after a consent decision), Share must not silently override them. - The App Events facade records explicit values in the Objective-C class KFBAppEventsSettingsRegistry. Share and Login look it up through the Objective-C runtime, so there is no link-time dependency. - Share only applies its historical defaults to settings the app did not set explicitly. Apps that never call FacebookAppEvents keep the exact previous behaviour. - After Share or Login initializes the SDK, the recorded values are applied again so the SDK persists them (no-op when nothing was set). - Guard the behaviour in the Share source invariants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- scripts/validate-package.py replaces the inline layout check in CI and publish. On top of the layout (now including kfbsharestub and kfbappevents) it checks that both slices of each wrapper export every entry point of its header, that FacebookAppEvents binds every kfb_appevents_* symbol with a static __Internal import, that the managed constants cover every App Events name of the bundled SDK headers and that each constant value exists in the bundled FBSDKCoreKit binary. - scripts/verify-public.py fails on consuming-app names or real Facebook app IDs, URL schemes and client tokens in tracked files. - Move FacebookDataProcessingOptions next to the other App Events types: it is a caller-supplied value, not an SDK constant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Integration.md: AppEvents feature selection; Info.plist switches with SDK defaults (FacebookAutoLogAppEventsEnabled, FacebookAdvertiserIDCollectionEnabled, FBSDKAutoLogMetaDataEnabled, FBSDKAutoLogProductImprovementEnabled, FacebookSKAdNetworkReportEnabled) and the missing iOS AutoInit counterpart; a consent recipe (switches off in Info.plist, initialize after consent, manual ActivateApp, withdrawal steps); AEM URL / Universal Link forwarding; the double-counting rule for server-side purchase events; single SKAdNetwork owner; diagnostics and platform gaps. - README, NuGet readme, SourceMode and third-party notices: App Events, new xcframeworks, pinned archives and the CoreKit tracking manifest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Select Login;AppEvents in the sample (overridable with KapuschFacebookFeatures) so it links the App Events facade explicitly. - Ship the App Events switches off in Info.template.plist and add buttons for the consent recipe of Docs/Integration.md: grant consent (initialize, enable advertiser ID collection and debug logging, manual activation), log StartTrial and a custom event, flush and withdraw consent. Log activations from OnActivated after consent and forward Universal Links. - Without a FacebookAppID in the local, gitignored Info.plist the App Events buttons only print a message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NativeFacebookLogin resolved kfb_facebook_* with a run-time lookup in the
main program. Nothing referenced those symbols at link time, so the native
linker dead-stripped them: Initialize and HandleOpenUrl silently did
nothing and SignInAsync could not reach the SDK. A Login;Share build of
master showed only the three Share symbols in the app executable.
- Bind the four Login entry points with [LibraryImport("__Internal")], like
Share and App Events. The public API and its best-effort semantics are
unchanged.
- When Login is not selected, link kfbloginstub.xcframework (Foundation
only), which defines the same entry points: SignInAsync completes with
Failed/login_feature_not_selected.
- Validate the static imports and package the placeholder.
Verified with nm on simulator builds for Login;AppEvents, AppEvents and
Share: all 40 kfb_* entry points are present in the executable.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1.2.0 bundles Facebook iOS SDK 19.0.0 and adds App Events. It is first published as 1.2.0-rc.1 from a v1.2.0-rc.1 tag on master. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kapusch
force-pushed
the
feat/app-events
branch
from
October 26, 2026 22:59
dfbc560 to
d7a6641
Compare
Owner
Author
|
Superseded by #7. The history is rebuilt from master so no commit carries the encoded pattern of this branch's scripts/verify-public.py (the scanner now reads private terms at run time). The bundled Facebook iOS SDK stays 18.0.2, and #7 adds the independent review and its fixes. The branch is left in place. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Kapusch.Facebook.iOS1.2.0 (first published as1.2.0-rc.1):FacebookAppEvents) plus constants for every standard event name, parameter name, parameter value and user-data type.AppEventsfeature selection: a CoreKit-only build, without LoginKit or ShareKit. The default selection staysLogin.The commits are split so each one can be reviewed or bisected on its own. The Objective-C port is validated on 18.0.2 first, then the SDK bump follows in its own commit.
Why Objective-C facades instead of Swift
Meta built 19.0.0 with Xcode 27.1 / Swift 6.4. A Swift facade has to import the SDK's
.swiftinterface, which only compiles with that exact compiler. With Xcode 26.3 (Swift 6.2.4), the toolchain CI now pins on macos-15 (#5) and the local one, it fails:this SDK is not supported by the compiler (the SDK is built with 'Apple Swift version 6.4 …'). Staying on Swift would have limited us to SDK ≤ 18.0.3: 18.1.1 is already built with Swift 6.3.3.The SDK also ships Objective-C headers, including the generated
*-Swift.h. Any recent clang compiles against them, so the facades are now Objective-C:kfb_*C entry points and the same Login/Share behaviour;A probe showed that Swift cannot use the Clang-only module either: classes declared with
SWIFT_CLASS_NAMEDbecome "unavailable", so a Swift facade really is ruled out.Because Meta's SwiftPM wrapper targets are Swift too, the build no longer goes through SwiftPM. It downloads Meta's release
*-Dynamic_XCFramework.ziparchives, pinned by URL and SHA-256 inDependencyLocks/iOS/lockstate.txt, the same technique as the Android wrapper. The hashes are the same as the upstreamPackage.swiftremoteChecksumvalues. It then builds withclang+libtoolper slice. The 18.0.2 package built this way has the same file list as the published 1.1.0, apart from the archive names inside the xcframeworks.App Events API (
Kapusch.Facebook.iOS.FacebookAppEvents)Lifecycle:
InitializeSdk()runsdidFinishLaunchingwith no launch options, on the main thread.FinishedLaunching(app, launchOptions)passes the launch options, so a cold-start URL reaches AEM.HandleOpenUrlandContinueUserActivityforward URLs and Universal Links (AEM, deep links).SdkVersion.Settings:
Set…Enabled/Is…Enabledpairs for:Also
SetDataProcessingOptions(string[], country, state)andSetDebugLoggingEnabled.Logging:
ActivateApp;LogEvent(name, parameters?, valueToSum?);LogPurchase(decimal, currency, parameters?);LogStartTrial,LogSubscribeandLogCompleteRegistration(value, currency,fb_order_id, extra parameters);Flush,SetFlushBehavior/FlushBehavior.Identity:
GetAnonymousId;SetUserId/ClearUserId/GetUserId;SetUserData(FacebookAppEventsUserData)/ClearUserData, for advanced matching (the SDK hashes the values);SetUserDataValue/ClearUserDataValue, for example forexternal_id.Constants:
FacebookAppEventNames,FacebookAppEventParameterNames,FacebookAppEventParameterValues,FacebookAppEventUserDataTypesandFacebookDataProcessingOptions.Not available on iOS (documented):
setAutoInitEnabledhas no counterpart: on iOS the SDK starts only when the app initializes it.SetFlushBehaviorexists, but there is no iOS equivalent of Android'ssetIsDebugEnabled.SetDebugLoggingEnabledtoggles the SDK's app-events, developer-error and informational logging behaviours instead, and restores the previous behaviours when turned off.Non-obvious choices
FBSDKCoreKit, which every selection already ships.__Internalimports, so the .NET iOS build asks the native linker for them in every app.AppEventstherefore means "no LoginKit, no ShareKit" (CoreKit, AEMKit and Basics only).Utf8JsonWriter, which is safe under trimming and AOT."1"/"0"like the SDK'sFBSDKAppEventParameterValueYes/No.ArgumentException.Info.pliston later launches. A value set before initialization only lives in memory inside the SDK. The facade records the values set through it and applies them again right after initialization, whichever wrapper initializes. That way "set before init" and "set after init" behave the same.ConfigureAndInitializestill forces auto-log off and advertiser ID collection / tracking totrackingAllowed(identical defaults).FacebookAppEvents.NSClassFromString), so no wrapper depends on another at link time.KapuschFacebookFeaturesvalues now produce a build warning. Before, they were silently ignored.Bugs fixed on the way (they also affect 1.1.0)
Login was never linked.
NativeFacebookLoginused a run-time lookup (NativeLibrary.GetExport). Nothing referenced the symbols at link time, so the linker dead-stripped them:nmon aLogin;Sharebuild ofmastershows only the three Share symbols;InitializeandHandleOpenUrlsilently did nothing.It now uses
[LibraryImport("__Internal")], like Share. The public API and its best-effort semantics are unchanged.Login-only builds (the default) failed to link, with
Undefined symbols: _kfb_facebook_share_*. Share's static imports are required symbols for every app. Reproduced onmasterwith the sample.Fix: when a feature is not selected, a Foundation-only placeholder is linked (
kfbsharestub/kfbloginstub). It defines the same entry points and fails withshare_feature_not_selected/login_feature_not_selected.Other changes
ios-arm64_arm64e. The targets resolve the device slice from the package, so thePrivacyInfo.xcprivacyBundleResourceitems keep pointing at files that exist.scripts/validate-package.py:kfb_appevents_*symbol bound by a static import;GetExport;FBSDKCoreKitbinary (negative-tested).scripts/verify-public.py: genericity scan for consuming-app names and real Facebook IDs or tokens.AppEvents.Docs/Integration.md§4 covers:Info.plistkeys with their SDK defaults:FacebookAutoLogAppEventsEnabled,FacebookAdvertiserIDCollectionEnabled,FBSDKAutoLogMetaDataEnabled,FBSDKAutoLogProductImprovementEnabled,FacebookSKAdNetworkReportEnabled;Info.plist, initialize after consent, manualActivateApp, withdrawal steps;FacebookAutoLogAppEventsEnabled=false+ActivateApp(), and/or set "Log In-App Events Automatically = No". SDK 18+ scans StoreKit 2 transactions, renewals included;Login;AppEvents;Validation
bash src/…/Native/iOS/build.shbuilds all 5 wrapper xcframeworks with-Wall -Werroragainst SDK 19.0.0 on Xcode 26.3. It was also built on 18.0.2 at the port commit, and a cold download restore was tested.bash tests/validate-feature-selection.sh,python3 scripts/verify-public.pyandpython3 scripts/validate-package.pyall pass.dotnet pack→Kapusch.Facebook.iOS.1.2.0.nupkg.Login,Share,AppEvents,Login;Share,Login;AppEventsandLogin;Share;AppEvents;ios-arm64Release forLogin;ShareandAppEvents(AOT).AppEventsbundles only CoreKit, AEMKit and Basics.kfb_*entry points are present in the executables.19.0.0initialized;advertiserId=TruedespitetrackingAllowed:false;tracking=Falsefrom the Share default);StartTrial,Subscribe,fb_mobile_complete_registration,fb_mobile_purchaseand a custom event recorded with the expected_valueToSum,fb_currency,fb_order_idand boolean"1"(seen in the SDK debug log);PR CI passed on the pinned macos-15 / Xcode 26.3 runner (
build_pack_ios, including both validators). The branch is rebased on #5.Not verified here: delivery to a real Events Manager app and the Login UI flow (it needs a real Meta app).
Release
After merge: tag
v1.2.0-rc.1on the merge commit ofmaster(seeDocs/Release.md).🤖 Generated with Claude Code