--- oncalls: ['sdk'] --- # Facebook iOS SDK — Coding Rules These constraints apply to every change. Violating them will break builds or reviews. ## Diff Summaries Are Published to Public GitHub This repo is mirrored to GitHub, and ShipIt exports the **whole** commit message. The `Summary` and `Test Plan` you write in Phabricator appear verbatim in public history. Treat every word as a public release: once pushed it is cloned, forked, and indexed, and amending the diff later does not retract what was mirrored. Write the summary for an external reader. Describe *what changed and why* in terms of the public API and the code in this repo. Do not paste in anything whose audience is internal. Keep out of `Summary` and `Test Plan`: - **Internal identifiers** — task numbers (`T…`), SEV numbers, and internal-only diff references. Say "tracked internally" or restate the substance instead. - **Internal URLs** — `internalfb.com`, `fburl.com`, Phabricator, wikis, dashboards, Scuba/ODS links. An external reader cannot open them anyway. - **Unreleased plans** — launch dates, rollout percentages, upcoming products, deprecations that have not been announced. - **Gating and config names** — GateKeepers, JustKnobs, sitevars, experiment names, and their values. - **Infrastructure detail** — hostnames, service names, capacity, internal metrics, and raw log excerpts that embed any of the above. - **People** — names, unixnames, and org structure in the prose. (The `Reviewers` / `Subscribers` / `Differential Revision` trailers are generated by `jf` and are exported regardless; that is expected. Everything you type is not.) CI signal names and script paths that already live in this repo (for example `ios-sdk-unit-tests`, `ci/unit_tests.py`) are fine — they are public here. Before `jf submit`, scan the message: ```bash git log -1 --format=%B | grep -inE 'T[0-9]{6,}|internalfb|fburl|phabricator|\bGK\b|justknob|sitevar|SEV[0-9]' ``` Hits in the body need rewording; hits in the generated trailers are expected. ## Style - 2-space indentation (no tabs), 120-char line length - Trailing commas mandatory on multi-line collections - Imports sorted; `@testable` imports first - Classes must be `final` unless explicitly `open` - Modifier order: `public override` (not `override public`) - Max cyclomatic complexity: 11 ## Copyright Header (every Swift/ObjC file) ```swift /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ ``` ## Naming - Public types: clean names (`LoginManager`), ObjC name via `@objc(FBSDKLoginManager)` - Internal types: underscore prefix (`_ErrorFactory`, `_BridgeAPI`) - Protocols: `-ing`/`-Providing`/`-Creating` suffixes (`ErrorCreating`, `URLOpening`) - Factory protocols: `*FactoryProtocol` (`GraphRequestFactoryProtocol`) - SPM naming: `FBSDK` prefix = ObjC target, no prefix = Swift target (e.g., `FBSDKLoginKit` vs `FacebookLogin`) - Extensions for splitting types: `Settings+AutoLogAppEvents.swift` - Private constant namespacing: `private enum Keys { static let ... }` ## Dependency Properties Properties in `ObjectDependencies` / `TypeDependencies` must be in **alphabetical order** by name. Types must always be protocols, never concrete types. ## Public API — Dual Swift/ObjC Interfaces New public methods using Swift-only types (`Result`, enums with associated values, structs) require dual interfaces: `@nonobjc` Swift-preferred + `@available(swift, obsoleted: 0.1) @objc` ObjC-compatible, both delegating to a shared `private` implementation. See `.llms/skills/public-api-design.md` for the full pattern. ## Deployment Targets | Target | Minimum iOS | |--------|-------------| | SDK modules (`FBSDKCoreKit`, `FBSDKLoginKit`, etc.) | 15.0 | | Hackbook test app (`internal/testing/Hackbook`) | 15.0 | | CoffeeShop test app (`internal/testing/CoffeeShop`) | 15.0 | Everything inherits `15.0` from `xcodegen_project_common.yml` and `Configurations/Platform/iOS.xcconfig`; the podspecs and `Package.swift` declare the same floor to consumers. Xcode 27 does not accept a deployment target below 15.0, so do not lower these. Do NOT use APIs newer than the target's minimum without `@available` checks. ## Simulator Destinations When building for iOS Simulator from the CLI, always query available destinations first (`xcodebuild -scheme -showdestinations`) rather than hardcoding device names. Device names change with each iOS/Xcode generation (e.g., iOS 26 has `iPhone 17 Pro`, not `iPhone 16`). ## Build Settings - Warnings are errors (`GCC_TREAT_WARNINGS_AS_ERRORS = YES`) - `BUILD_LIBRARY_FOR_DISTRIBUTION = YES` — API stability required - Use xcconfig files — never add settings directly to targets - Swift 5.0, C++11, ARC enabled ## Module Dependency Boundaries ``` Basics (L0) → AEM (L1) → Core (L2) → Login / Share / Gaming (L3) Gaming also imports Share ``` | Source module | May import | |---|---| | `FBSDKCoreKit_Basics` | *(none)* | | `FBAEMKit` | `FBSDKCoreKit_Basics` | | `FBSDKCoreKit` | `FBSDKCoreKit_Basics`, `FBAEMKit` | | `FBSDKLoginKit` | `FBSDKCoreKit`, `FBSDKCoreKit_Basics` | | `FBSDKShareKit` | `FBSDKCoreKit`, `FBSDKCoreKit_Basics` | | `FBSDKGamingServicesKit` | `FBSDKCoreKit`, `FBSDKCoreKit_Basics`, `FBSDKShareKit` | Exception: `CoreKitConfigurator.swift` uses `@testable import FBAEMKit` for composition-root wiring. System frameworks are always allowed. ## New Files Use `./scripts/new-file.sh ` to scaffold source + test files. After: run `./generate-projects.sh` and verify target membership in `project.yml` (both Static and Dynamic targets; TV targets if cross-platform). Before creating a new test double, check `TestTools/TestTools/` — shared doubles like `TestSettings`, `TestGraphRequestFactory`, etc. already exist there. ## Do Not Modify Never edit these files without explicit instruction: - `Package.swift` binary checksums or remote URLs - `.swiftformat`, `.swiftlint.yml` (tooling config) - `build/` directory (generated artifacts) - `*.xcframework` files (prebuilt binaries) ## Test Verification After completing source changes, run `./scripts/test.sh `. Changes to `FBSDKCoreKit_Basics` or `FBSDKCoreKit` may break downstream — run `./scripts/test.sh` (no args) for those. Fix failures before considering the task done. | Directory | Kit | |-----------|-----| | `FBSDKCoreKit_Basics/` | `BasicKit` | | `FBAEMKit/` | `AEMKit` | | `FBSDKCoreKit/` | `CoreKit` | | `FBSDKLoginKit/` | `LoginKit` | | `FBSDKShareKit/` | `ShareKit` | | `FBSDKGamingServicesKit/` | `GamingKit` |