# TryYourSize iOS SDK reference --- # iOS reference (TryYourSize for Swift) > The native Size guide button (SwiftUI and UIKit), the shopper's recommended size, and the TryYourSize window in a sheet. Source: https://docs.tryyoursize.com/reference/ios/ *SDK* · `TryYourSize (Swift)` · v0.1.0 iOS 16+, Swift 5.9+, SwiftUI and UIKit. A client per publishable key, the native **Size guide** button, the shopper's recommended size (sizes only), and our window in a sheet. Register your app for the key in Studio as `ios-app://` (test mode today; live mode for apps is coming soon). ## Install **Swift Package Manager** ```swift // File → Add Package Dependencies → the TryYourSize package, product "TryYourSize". // Package.swift: .product(name: "TryYourSize", package: "TryYourSize") ``` **CocoaPods** ```ruby pod 'TryYourSize' ``` ## Initialize **Swift** ```swift let tys = try TryYourSize(publishableKey: "pk_test_…") // a secret key throws ``` **Kotlin** ```kotlin val tys = TryYourSize(context, "pk_test_…") // a secret key throws ``` **React Native** ```tsx await configure("pk_test_…"); // once, at startup ``` **Flutter** ```dart final tys = await TryYourSize.create('pk_test_…'); ``` Error codes: [Mobile SDK errors](https://docs.tryyoursize.com/mobile/errors.md). ## Client | | | |---|---| | [`init`](https://docs.tryyoursize.com/reference/ios/init.md) | Creates the client for your publishable key. | | [`Configuration`](https://docs.tryyoursize.com/reference/ios/configuration.md) | Options of the client. | | [`recommendation(for:)`](https://docs.tryyoursize.com/reference/ios/recommendation.md) | The shopper's recommended size for a product, in your size labels. | | [`onRecommendation`](https://docs.tryyoursize.com/reference/ios/on-recommendation.md) | Calls handler now (once known) and on every change: signing in, a new body, a simulation finishing. | | [`on (events)`](https://docs.tryyoursize.com/reference/ios/on.md) | Window events: ready, open, close, size, loadError. | | [`present`](https://docs.tryyoursize.com/reference/ios/present.md) | Opens the measuring / try-on window for a product, as a sheet over presenter (default: the app's top-most view controller). | | [`appearance`](https://docs.tryyoursize.com/reference/ios/appearance-property.md) | Live restyle (e.g. | | [`appOrigin`](https://docs.tryyoursize.com/reference/ios/app-origin.md) | ios-app://: what the store registers as an allowed origin. | ## Size guide button | | | |---|---| | [`SizeGuide`](https://docs.tryyoursize.com/reference/ios/size-guide.md) | The "Size guide" button: "Size guide" → "Calculating your size…" → "Your size: M". | | [`SizeGuideButton`](https://docs.tryyoursize.com/reference/ios/size-guide-button.md) | The same button as a UIView. | ## Types | | | |---|---| | [`Recommendation`](https://docs.tryyoursize.com/reference/ios/recommendation-type.md) | The shopper's recommended size for one product, in the store's own size labels. | | [`Appearance`](https://docs.tryyoursize.com/reference/ios/appearance.md) | Colours, font and corner radius for the button and the window. | | [`TryYourSizeError`](https://docs.tryyoursize.com/reference/ios/errors.md) | Every error the SDK raises: a stable code, a message and a doc link (like the web SDK). | --- # appOrigin > ios-app://: what the store registers as an allowed origin. Source: https://docs.tryyoursize.com/reference/ios/app-origin/ *Property* · `TryYourSize (Swift)` `ios-app://`: what the store registers as an allowed origin. ```swift public let appOrigin: String ``` ## Example **Swift** ```swift print(tys.appOrigin) // "ios-app://com.brand.shop": add it in Studio ``` --- # appearance > Live restyle (e.g. Source: https://docs.tryyoursize.com/reference/ios/appearance-property/ *Property* · `TryYourSize (Swift)` Live restyle (e.g. when your app switches theme); an open window updates at once. ```swift public var appearance: Appearance ``` ## Example **Swift** ```swift tys.appearance.colorPrimary = TYSColor(hex: "#3b2f26") // an open window restyles at once ``` **Kotlin** ```kotlin tys.appearance = tys.appearance.copy(colorPrimary = 0xFF3B2F26.toInt()) ``` **React Native** ```tsx setAppearance({ variables: { colorPrimary: "#3b2f26" } }); ``` **Flutter** ```dart await tys.setAppearance(const Appearance(colorPrimary: Color(0xFF3B2F26))); ``` ## See also - [Appearance](https://docs.tryyoursize.com/reference/ios/appearance.md) --- # Appearance > Colours, font and corner radius for the button and the window. Source: https://docs.tryyoursize.com/reference/ios/appearance/ *Type* · `TryYourSize (Swift)` Colours, font and corner radius for the button and the window. With `.inherit` (default) the button takes your SwiftUI font and text colour and the window your app's colours, dark mode included. ## Properties - **`theme`** (`Theme`, required) - **`colorPrimary`** (`TYSColor?`, required): Buttons and the tape line on the body; the "connected" dot on the size guide. - **`colorBackground`** (`TYSColor?`, required) - **`colorText`** (`TYSColor?`, required) - **`fontFamily`** (`String?`, required): A CSS font-family for the window (e.g. "Inter, -apple-system, sans-serif"). The native button uses the SwiftUI font of where it is placed. - **`borderRadius`** (`Double?`, required): Corner radius in points (0–32) for cards, inputs and buttons. - **`fonts`** (`[URL]`, required): Stylesheets with @font-face rules for the window (Google Fonts only). ## Example **Swift** ```swift let tys = try TryYourSize(publishableKey: "pk_test_…", configuration: .init( appearance: Appearance(borderRadius: 10), locale: "es")) ``` **Kotlin** ```kotlin val tys = TryYourSize(context, "pk_test_…", TryYourSize.Configuration( appearance = Appearance(borderRadius = 10f), locale = "es", )) ``` **React Native** ```tsx await configure("pk_test_…", { appearance: { variables: { borderRadius: 10 } }, locale: "es" }); ``` **Flutter** ```dart final tys = await TryYourSize.create('pk_test_…', appearance: const Appearance(borderRadius: 10), locale: 'es'); ``` --- # TryYourSize.Configuration > Options of the client. Source: https://docs.tryyoursize.com/reference/ios/configuration/ *Type* · `TryYourSize (Swift)` Options of the client. ## Properties - **`appearance`** (`Appearance`, required): Colours, font and corner radius for the button and the window. - **`locale`** (`String?`, required): BCP 47 language for the button and the window; nil: the app's preferred language. - **`bundleIdentifier`** (`String?`, required): The app's identity registered for the store; nil: `Bundle.main.bundleIdentifier`. - **`embedOrigin`** (`URL`, required): Our window's origin (change only for staging or local development). - **`inspectable`** (`Bool`, required): Lets Safari's Web Inspector attach to the window (iOS 16.4+). Debug builds only. ## Example **Swift** ```swift let tys = try TryYourSize(publishableKey: "pk_test_…", configuration: .init( appearance: Appearance(borderRadius: 10), locale: "es")) ``` **Kotlin** ```kotlin val tys = TryYourSize(context, "pk_test_…", TryYourSize.Configuration( appearance = Appearance(borderRadius = 10f), locale = "es", )) ``` **React Native** ```tsx await configure("pk_test_…", { appearance: { variables: { borderRadius: 10 } }, locale: "es" }); ``` **Flutter** ```dart final tys = await TryYourSize.create('pk_test_…', appearance: const Appearance(borderRadius: 10), locale: 'es'); ``` --- # TryYourSizeError > Every error the SDK raises: a stable code, a message and a doc link (like the web SDK). Source: https://docs.tryyoursize.com/reference/ios/errors/ *Type* · `TryYourSize (Swift)` Every error the SDK raises: a stable `code`, a message and a doc link (like the web SDK). Each error has a stable `code`, a `message` and a `docURL`. Explanations: [Mobile SDK errors](https://docs.tryyoursize.com/mobile/errors.md). ## Codes - **`.secretKeyInApp`** (`"secret_key_in_app"`, optional): A secret (`sk_`) or restricted (`rk_`) key was passed. Those belong on your server. - **`.invalidKey`** (`"invalid_key"`, optional): Not a publishable key (`pk_test_…` / `pk_live_…`). - **`.invalidAppIdentifier`** (`"invalid_app_identifier"`, optional): The bundle identifier can't be used as an app origin. - **`.invalidOption`** (`"invalid_option"`, optional) - **`.windowUnreachable`** (`"window_unreachable"`, optional): Our window did not answer (offline, or blocked). - **`.appNotAllowed`** (`"app_not_allowed"`, optional): This app (`ios-app://`) is not registered for the key's store. - **`.signInCancelled`** (`"sign_in_cancelled"`, optional) - **`.signInUnavailable`** (`"sign_in_unavailable"`, optional): System-browser sign-in is not available yet. ## Example **Swift** ```swift do { tys = try TryYourSize(publishableKey: key) } catch let error as TryYourSizeError where error.code == .secretKeyInApp { assertionFailure("Use the pk_ key in the app") } ``` --- # TryYourSize(publishableKey:configuration:) > Creates the client for your publishable key. Source: https://docs.tryyoursize.com/reference/ios/init/ *Constructor* · `TryYourSize (Swift)` Creates the client for your publishable key. Keep one per app. ```swift public init(publishableKey: String, configuration: Configuration = Configuration()) throws ``` ## Parameters - **`publishableKey`** (`String`, required): Your publishable key (`pk_test_…` / `pk_live_…`). - **`configuration`** (`Configuration`, optional, default `Configuration()`): Appearance, language and the app identity. See `Configuration`(/reference/ios/configuration/). ## Errors `TryYourSizeError` with code `secret_key_in_app`, `invalid_key`, `invalid_app_identifier` or `invalid_option`. ## Example **Swift** ```swift let tys = try TryYourSize(publishableKey: "pk_test_…", configuration: .init( appearance: Appearance(borderRadius: 10), locale: "es")) ``` **Kotlin** ```kotlin val tys = TryYourSize(context, "pk_test_…", TryYourSize.Configuration( appearance = Appearance(borderRadius = 10f), locale = "es", )) ``` **React Native** ```tsx await configure("pk_test_…", { appearance: { variables: { borderRadius: 10 } }, locale: "es" }); ``` **Flutter** ```dart final tys = await TryYourSize.create('pk_test_…', appearance: const Appearance(borderRadius: 10), locale: 'es'); ``` --- # onRecommendation(for:onError:_:) > Calls handler now (once known) and on every change: signing in, a new body, a simulation finishing. Source: https://docs.tryyoursize.com/reference/ios/on-recommendation/ *Method* · `TryYourSize (Swift)` Calls `handler` now (once known) and on every change: signing in, a new body, a simulation finishing. Keep the subscription; `cancel()` it when done. ```swift @discardableResult public func onRecommendation(for product: String, onError: ((TryYourSizeError) -> Void)? = nil, _ handler: @escaping (Recommendation) -> Void) -> TYSSubscription ``` ## Parameters - **`for`** (`String`, required): Your product ID or SKU. - **`onError`** (`((TryYourSizeError) -> Void)?`, optional, default `nil`): Called when our window cannot be reached or the app is not registered. - **`handler`** (`@escaping (Recommendation) -> Void`, required): Called now (once known) and on every change. ## Returns A subscription: keep it, and `cancel()` it when you are done. ## Example **Swift** ```swift let sub = tys.onRecommendation(for: "SKU-123") { rec in if rec.status == .ready, !touched { selectedSize = rec.size } } // keep `sub`; sub.cancel() when the screen goes away ``` **Kotlin** ```kotlin val sub = tys.onRecommendation("SKU-123") { rec -> if (rec.status == Recommendation.Status.READY && !touched) selected = rec.size } // sub.cancel() in onDestroy ``` **React Native** ```tsx useEffect(() => { const sub = addRecommendationListener("SKU-123", (rec) => { if (rec.status === "ready" && !touched) setSize(rec.size); }); return () => sub.remove(); }, []); ``` **Flutter** ```dart final sub = tys.onRecommendation('SKU-123').listen((rec) { if (rec.status == RecommendationStatus.ready && !touched) setState(() => size = rec.size); }); // sub.cancel() in dispose() ``` --- # on(_:) > Window events: ready, open, close, size, loadError. Source: https://docs.tryyoursize.com/reference/ios/on/ *Method* · `TryYourSize (Swift)` Window events: ready, open, close, size, loadError. ```swift @discardableResult public func on(_ handler: @escaping (Event) -> Void) -> TYSSubscription ``` ## Parameters - **`handler`** (`@escaping (Event) -> Void`, required): Called with each window event. ## Events - **`.ready(product: String)`** (optional): The window is shown and connected. - **`.open(product: String)`** (optional) - **`.close(product: String)`** (optional) - **`.size(SizeSelection)`** (optional): The shopper chose a size: preselect it. - **`.loadError(TryYourSizeError)`** (optional): Our window could not be reached, or this app is not registered for the key. ## Returns A subscription; `cancel()` stops the events. ## Example **Swift** ```swift let sub = tys.on { event in switch event { case .size(let selection): selectedSize = selection.size // "Use this size" case .loadError(let error): print(error.code) default: break } } ``` **Kotlin** ```kotlin val sub = tys.on { event -> when (event) { is TryYourSize.Event.Size -> selected = event.selection.size is TryYourSize.Event.LoadError -> Log.w("tys", event.error.code.wire) else -> Unit } } ``` **React Native** ```tsx const sub = addEventListener((e) => { if (e.type === "size") setSize(e.selection.size); if (e.type === "loaderror") console.warn(e.code); }); ``` **Flutter** ```dart tys.events.listen((e) { if (e is SizeSelected) setState(() => size = e.selection.size); if (e is LoadError) debugPrint(e.error.code); }); ``` --- # present(product:step:from:) > Opens the measuring / try-on window for a product, as a sheet over presenter (default: the app's top-most view controller). Source: https://docs.tryyoursize.com/reference/ios/present/ *Method* · `TryYourSize (Swift)` Opens the measuring / try-on window for a product, as a sheet over `presenter` (default: the app's top-most view controller). Swiping the sheet down asks the window first: with unsaved measurements, the shopper confirms. ```swift public func present(product: String, step: OpenStep? = nil, from presenter: UIViewController? = nil) ``` ## Parameters - **`product`** (`String`, required): Your product ID or SKU. - **`step`** (`OpenStep?`, optional, default `nil`): `.create`, `.improve` or `.view` (default: where the shopper is). - **`from`** (`UIViewController?`, optional, default `nil`): The presenting view controller (default: the top-most one). ## Example **Swift** ```swift tys.present(product: "SKU-123") // or step: .view, from: viewController ``` **Kotlin** ```kotlin tys.present(activity, "SKU-123") // or step = OpenStep.VIEW ``` **React Native** ```tsx present("SKU-123"); // or present("SKU-123", "view") ``` **Flutter** ```dart await tys.present('SKU-123'); // or step: OpenStep.view ``` --- # Recommendation > The shopper's recommended size for one product, in the store's own size labels. Source: https://docs.tryyoursize.com/reference/ios/recommendation-type/ *Type* · `TryYourSize (Swift)` The shopper's recommended size for one product, in the store's own size labels. ## Properties - **`product`** (`String`, required) - **`status`** (`Status`, required) - **`size`** (`String?`, required): The recommended size in the store's label (its size map), or nil. - **`studioSize`** (`String?`, required): The same size as entered in TryYourSize Studio, or nil. - **`wearableSizes`** (`[String]?`, required): Sizes that can be worn on this body, in the store's labels (when simulated). ## Example **Swift** ```swift let rec = try await tys.recommendation(for: "SKU-123") if rec.status == .ready, let size = rec.size { selectedSize = size } ``` **Kotlin** ```kotlin lifecycleScope.launch { val rec = tys.recommendation("SKU-123") if (rec.status == Recommendation.Status.READY) selected = rec.size } ``` **React Native** ```tsx const rec = await getRecommendation("SKU-123"); if (rec.status === "ready") setSize(rec.size); ``` **Flutter** ```dart final rec = await tys.recommendation('SKU-123'); if (rec.status == RecommendationStatus.ready) setState(() => size = rec.size); ``` ## Notes `status`: `.ready` (`size` is set), `.computing`, `.noSize` (`"none"` on the web: no size can be worn), `.signedOut`, `.unavailable`. --- # recommendation(for:) > The shopper's recommended size for a product, in your size labels. Source: https://docs.tryyoursize.com/reference/ios/recommendation/ *Method* · `TryYourSize (Swift)` The shopper's recommended size for a product, in your size labels. Never starts a simulation; never carries measurements or body data. ```swift public func recommendation(for product: String) async throws -> Recommendation ``` ## Parameters - **`for`** (`String`, required): Your product ID or SKU. ## Returns The shopper's recommended size. See [Recommendation](https://docs.tryyoursize.com/reference/ios/recommendation-type.md). ## Example **Swift** ```swift let rec = try await tys.recommendation(for: "SKU-123") if rec.status == .ready, let size = rec.size { selectedSize = size } ``` **Kotlin** ```kotlin lifecycleScope.launch { val rec = tys.recommendation("SKU-123") if (rec.status == Recommendation.Status.READY) selected = rec.size } ``` **React Native** ```tsx const rec = await getRecommendation("SKU-123"); if (rec.status === "ready") setSize(rec.size); ``` **Flutter** ```dart final rec = await tys.recommendation('SKU-123'); if (rec.status == RecommendationStatus.ready) setState(() => size = rec.size); ``` --- # SizeGuideButton (UIKit) > The same button as a UIView. Source: https://docs.tryyoursize.com/reference/ios/size-guide-button/ *Component* · `TryYourSize (Swift)` The same button as a `UIView`. Auto Layout sizes it from its content. `product`, `variant`, `label` and `onRecommendation` can be changed later. ```swift public init(client: TryYourSize, product: String, variant: SizeGuide.Variant = .link, label: String? = nil) ``` ## Parameters - **`client`** (`TryYourSize`, required): Your client. - **`product`** (`String`, required): Your product ID or SKU. - **`variant`** (`SizeGuide.Variant`, optional, default `.link`) - **`label`** (`String?`, optional, default `nil`) ## Example **Swift** ```swift // UIKit let guide = SizeGuideButton(client: tys, product: "SKU-123", variant: .button) guide.onRecommendation = { rec in /* … */ } stack.addArrangedSubview(guide) ``` **Kotlin** ```kotlin // Views val guide = SizeGuideView(context).apply { client = tys product = "SKU-123" variant = SizeGuideVariant.BUTTON onRecommendation = { rec -> /* … */ } } ``` --- # SizeGuide (SwiftUI) > The "Size guide" button: "Size guide" → "Calculating your size…" → "Your size: M". Source: https://docs.tryyoursize.com/reference/ios/size-guide/ *Component* · `TryYourSize (Swift)` The "Size guide" button: "Size guide" → "Calculating your size…" → "Your size: M". A tap opens the window. It takes the SwiftUI font and colour of where you put it. ```swift public init(client: TryYourSize, product: String, variant: Variant = .link, label: String? = nil, onRecommendation: ((Recommendation) -> Void)? = nil) ``` ## Parameters - **`client`** (`TryYourSize`, required): Your client. - **`product`** (`String`, required): Your product ID or SKU. - **`variant`** (`Variant`, optional, default `.link`): `.link` (link-sized text with the mark, 44 pt hit area) or `.button` (a small bordered button). - **`label`** (`String?`, optional, default `nil`): your own words instead of "Size guide". - **`onRecommendation`** (`((Recommendation) -> Void)?`, optional, default `nil`): the shopper's recommended size, on appear and on every change (sizes only). ## Example **Swift** ```swift // SwiftUI, where your "Size guide" link was SizeGuide(client: tys, product: "SKU-123") { rec in if rec.status == .ready, !touched { selectedSize = rec.size } } ``` **Kotlin** ```kotlin // Compose, where your "Size guide" link was SizeGuide(tys, "SKU-123", textStyle = MaterialTheme.typography.bodyMedium) { rec -> if (rec.status == Recommendation.Status.READY && !touched) selected = rec.size } ``` **React Native** ```tsx rec.status === "ready" && !touched && setSize(rec.size)} /> ``` **Flutter** ```dart const SizeGuide(product: 'SKU-123') // listen to tys.onRecommendation to preselect ```