Skip to main content

Overview

EncoreObjC is a thin @objc overlay over the Swift EncoreKit SDK, distributed as a source pod on CocoaPods. Every method is a translation shim — all business logic lives in EncoreKit — so the Obj-C surface mirrors the Swift API 1:1 semantically. Use this page to install the bridge, wire it up in an Obj-C AppDelegate, and map each method back to the Swift docs for full semantics.

When to Use

Use EncoreObjC if

  • Pure Objective-C codebases
  • Legacy iOS apps that haven’t adopted Swift
  • Teams standardized on CocoaPods
  • Mixed codebases where .m files need direct access

Use EncoreKit (Swift) if

  • Pure Swift or SwiftUI codebases
  • Mixed codebases where Swift files drive integration
  • You want async/await and typed errors
  • You prefer Swift Package Manager
Both pods point at the same singleton. In mixed codebases, Swift files should import Encore and call the typed Swift API — only .m files need @import EncoreObjC.

Install

1

Add EncoreObjC to your Podfile

Target iOS 15.0 or later and enable use_frameworks!. Install directly from the tagged Git release:
Podfile
platform :ios, '15.0'
use_frameworks!

target 'MyApp' do
  pod 'EncoreObjC', :git => 'https://github.com/EncoreKit/objc.git', :tag => 'v0.1.0'
end
The standard trunk form — pod 'EncoreObjC', '~> 0.1' — is also available and is the recommended steady-state install once CocoaPods’ CDN shard index has refreshed for this release.
The Git-ref form resolves by cloning the public repo at a specific tag, so it works immediately after a release — independent of CocoaPods shard-index propagation (which can lag 15–60 min after pod trunk push). The '~> 0.1' trunk form is canonical once the CDN catches up and is preferred for consumers who want automatic patch bumps.
2

Install the pod

From the directory containing your Podfile:
pod install --repo-update
3

Open the workspace

From now on, open MyApp.xcworkspace (not .xcodeproj). Build to confirm the pod linked cleanly.
@import EncoreObjC;
If @import EncoreObjC; resolves in Xcode, you’re ready to configure.

Quickstart

Configure the SDK at launch, identify the current user, register a purchase handler, and present a placement. The full flow fits in one AppDelegate.m:
AppDelegate.m
#import "AppDelegate.h"
@import EncoreObjC;

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // 1. Configure
    EncoreOptions *options = [[EncoreOptions alloc] init];
    options.logLevel = EncoreLogLevelInfo;
    [[EncoreClient shared] configureWithApiKey:@"pk_live_your_key_here"
                                       options:options];

    // 2. Identify the user
    EncoreUserAttributes *attrs = [[EncoreUserAttributes alloc] init];
    attrs.email = @"user@example.com";
    attrs.subscriptionTier = @"free";
    [[EncoreClient shared] identifyWithUserId:@"user_123" attributes:attrs];

    // 3. Register the purchase handler
    [[EncoreClient shared] onPurchaseRequest:^(EncorePurchaseRequest *request,
                                               void (^done)(NSError *error)) {
        // Kick off your StoreKit / RevenueCat / Adapty purchase here.
        // Call done(nil) on success, or done(error) on failure.
        NSLog(@"Purchase requested for productId=%@", request.productId);
        done(nil);
    }];

    // 4. Handle dismissal / no-offer passthrough
    [[EncoreClient shared] onPassthrough:^(NSString *placementId) {
        NSLog(@"Passthrough for %@", placementId);
    }];

    return YES;
}

@end
Present a placement anywhere in your app:
ViewController.m
- (void)presentPaywall {
    [[[EncoreClient shared] placement:@"paywall"]
        showWithCompletion:^(EncorePresentationResult *result, NSError *error) {
            if (error) {
                NSLog(@"Show failed: %@", error.localizedDescription);
                return;
            }
            if (result.kind == EncorePresentationKindGranted) {
                NSLog(@"Granted entitlement kind=%ld", (long)result.entitlement.kind);
            } else {
                NSLog(@"Not granted. reason=%ld", (long)result.reason);
            }
        }];
}
showWithCompletion: is auto-generated from the async throws Swift method via SE-0297. The completion block always receives either a result or an error, never both.

API Mapping

Every Obj-C method forwards directly to the Swift SDK. Use the Swift SDK Reference for method-level semantics; the table below is your translation key.
SwiftObjective-C
Encore.shared[EncoreClient shared]
configure(apiKey:options:)-configureWithApiKey:options:
identify(userId:attributes:)-identifyWithUserId:attributes:
setUserAttributes(_:)-setUserAttributes:
reset()-reset
placement(_:).show() (async throws)-placement:[builder showWithCompletion:]
placement(_:).show() (fire-and-forget)-placement:[builder showAndForget]
isActive(_:in:) (async)-isActive:scope:completion:
revokeEntitlements() (async throws)-revokeEntitlementsWithCompletion:
onPurchaseRequest { … }-onPurchaseRequest: (block receives EncorePurchaseRequest * + void (^done)(NSError *))
onPassthrough { … }-onPassthrough:
EncoreError (enum)NSError — see Error Handling

Error Handling

All Obj-C completion handlers receive an optional NSError *. Errors originating from EncoreKit use the domain published on EncoreErrorInfo and numeric codes defined by EncoreErrorCode:
[[EncoreClient shared] revokeEntitlementsWithCompletion:^(NSError *error) {
    if (!error) { return; }

    if ([error.domain isEqualToString:EncoreErrorInfo.domain]) {
        switch (error.code) {
            case EncoreErrorCodeIntegrationNotConfigured:
                NSLog(@"SDK not configured — call configureWithApiKey: first");
                break;
            case EncoreErrorCodeProtocolAPI: {
                NSNumber *status = error.userInfo[EncoreErrorInfo.statusKey];
                NSString *message = error.userInfo[EncoreErrorInfo.messageKey];
                NSLog(@"API error %@: %@", status, message);
                break;
            }
            default:
                NSLog(@"Encore error: %@", error.localizedDescription);
        }
    }
}];
Available codes: EncoreErrorCodeTransportNetwork, EncoreErrorCodeTransportPersistence, EncoreErrorCodeProtocolHTTP, EncoreErrorCodeProtocolAPI, EncoreErrorCodeProtocolDecoding, EncoreErrorCodeIntegrationNotConfigured, EncoreErrorCodeIntegrationInvalidApiKey, EncoreErrorCodeIntegrationInvalidURL, EncoreErrorCodeDomain. The userInfo dictionary may include EncoreErrorInfo.statusKey, EncoreErrorInfo.apiCodeKey, and EncoreErrorInfo.messageKey depending on the error.

Known Constraints

The Obj-C overlay is intentionally a subset of the Swift surface. The following gaps exist in EncoreObjC 0.1:
  • isActivePublisher (Combine) is not bridged. Poll -isActive:scope:completion: instead if you need live entitlement state.
  • onPurchaseComplete is not bridged in v0.1. Its argument is StoreKit.Transaction, which is a Swift struct and not representable in Obj-C. Use onPurchaseRequest and sync state from your purchase code directly.
  • EncoreOptions.unlockMode is accepted but ignored. It’s parked until EncoreKit promotes UnlockMode to public API. Setting it has no effect today.
  • Purchase handler completion takes only NSError *. The Swift handler’s Bool return is not surfaced in v0.1 — success/failure is signalled by passing nil or a non-nil error to done(...).

Mixed Codebases

If your app has both Swift and Obj-C files, use each language’s native SDK from its own files — they share a single underlying singleton.
UserSession.swift
import Encore

// Swift files use the typed Swift API.
Encore.shared.identify(userId: "user_123", attributes: attrs)
LegacyBridge.m
@import EncoreObjC;

// Obj-C files use the bridge.
[[EncoreClient shared] identifyWithUserId:@"user_123" attributes:attrs];
Configure the SDK once from whichever file owns app launch — subsequent calls from either language hit the same instance.

Next Steps

Full API semantics — parameter defaults, threading, edge cases — live in the Swift SDK Reference. Use the API Mapping table above to translate each Swift signature to its Obj-C selector:

configure(apiKey:)

Configuration options and initialization order

identify(userId:)

User identification and attribute behavior

placement(_:).show()

Placement presentation flow and results

onPurchaseRequest

Wiring StoreKit, RevenueCat, Adapty, or custom purchase logic
Swift reference docs apply to the Obj-C bridge with the mapping above. If a method isn’t listed in the API Mapping table, it’s not bridged in v0.1 — see Known Constraints.