releases.shpreview
Apollo GraphQL/Apollo iOS

Apollo iOS

Mon
Wed
Fri
JunJulAugSepOctNovDecJanFebMarAprMay
Less
More
Releases8Avg2/moVersionsv1.25.4 to v2.1.1
Fixed
  • Fix \r\n in GraphQL descriptions generating invalid Swift comments (#965): GraphQL field descriptions containing \r\n (Windows CRLF) line endings caused codegen to emit invalid Swift — only the first line received the /// doc comment prefix and subsequent lines were emitted as uncommented text, breaking compilation. Backport of #961. Fixes #3553. Thank you to @iPhoneNoobDeveloper for the contribution.
Fixed
  • Make SubscriptionStream initializer public (#975): The SubscriptionStream initializer was inadvertently scoped to package access, preventing adopters from writing custom conformances to the public SubscriptionNetworkTransport protocol. The initializer is now public. Fixes #3637. Thank you to @ahou8 for raising the issue.
  • Fix \r\n in GraphQL descriptions generating invalid Swift comments (#961): GraphQL field descriptions containing \r\n (Windows CRLF) line endings caused codegen to emit invalid Swift — only the first line received the /// doc comment prefix and subsequent lines were emitted as uncommented text, breaking compilation. Fixes #3553. Thank you to @iPhoneNoobDeveloper for the contribution.
Fixed
  • Fix cache read failure for nested arrays of objects (#938): Reading nested arrays of objects (2D, 3D, etc.) from the normalized cache threw a JSONDecodingError.wrongType error. Reference resolution now handles array nesting at any depth. Fixes #3609. Thank you to @gurusekhar-ibm for raising the issue.
  • Fix incorrect default mock value when first enum case is deprecated (#949): When deprecatedEnumCases was set to .exclude, the mock codegen incorrectly used the first enum case as the default value in convenience initializers — even if that case was deprecated and excluded from the generated enum, causing a compile error. Fixes #3634. Thank you to @cswelin for raising the issue.
  • Fix recursive OneOf input object enum cases not marked indirect (#954): A @oneOf input object that directly references itself generated a Swift enum that failed to compile with Recursive enum is not marked 'indirect'. Self-referencing cases are now correctly marked indirect. Fixes #3633. Thank you to @ahou8 for raising the issue.
Fixed
  • Fixed concurrency crash in compileGraphQLResult on Swift 6.3/macOS 26 (#929): Serialized async let calls in compileGraphQLResult to work around a Swift concurrency runtime crash triggered when code generation is used in an AsyncParsableCommand. See PR #942. Thank you to @m4p for the contribution.
New
  • WebSocket Transport: Apollo iOS 2.0 now supports WebSocket connections using the graphql-transport-ws protocol for subscriptions, queries, and mutations. See the WebSocket Transport documentation for setup and usage details.
  • Swift 6.2 MainActor default isolation support (#925): Added a markTypesNonisolated codegen option that emits nonisolated on all generated type declarations. This prevents compilation errors when SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor is enabled. The option defaults to true when the codegen tool is compiled with Swift 6.2+.
  • ApolloURLSession delegate injection (#899): Added support for injecting a custom URLSessionTaskDelegate into ApolloURLSession, enabling delegate callback handling. Thank you to @hammy-e for the contribution.
Fixed
  • Fix concurrency issue in compileGraphQLResult (#929): Resolved a Swift compiler crash triggered by async let stack management during code generation in AsyncParsableCommand contexts. Thank you to @m4p for the contribution.
New
  • WebSocket Transport: Apollo iOS 2.0 now supports WebSocket connections using the graphql-transport-ws protocol for subscriptions, queries, and mutations. See the WebSocket Transport documentation for setup and usage details.
  • ApolloURLSession delegate injection (#899): Added support for injecting a custom URLSessionTaskDelegate into ApolloURLSession, enabling delegate callback handling. Thank you to @hammy-e for the contribution.
  • Make JSONRequest.useGetForQueries mutable (#897): The useGetForQueries property on JSONRequest is now a var, allowing interceptors to mutate the request directly instead of copying it. Thank you to @nevil for the contribution.
Fixed
  • Add preflight HTTP header for CSRF prevention (#900): Added the X-Apollo-Operation-Name header to requests to satisfy Apollo Router's CSRF prevention requirements.
Improved
  • Use dictionary for objectType(forTypename:) lookup (#918): Replaced the generated switch statement in SchemaMetadata.objectType(forTypename:) with a static dictionary lookup, improving deserialization performance by ~75% for schemas with many types (4000+). Thank you to @erneestoc for the contribution.
Improvement
  • Use dictionary instead of switch for objectType(forTypename:) lookup (#3631): The generated SchemaMetadata.objectType(forTypename:) method now uses a static dictionary for O(1) hash-based lookup instead of a switch statement that performed O(n) linear scanning. For schemas with many object types (~4300 types), this improves deserialization times by approximately 75%. See PR #926.
Fixed
  • Fix HTTP method selection (#877): The APQ retry logic was overriding the HTTP method selected for all queries. Thank you to @3redrubies for raising the issue.
  • Prevent crashes in Dictionary initialization with duplicate keys (#884): Dictionary initialization using literal elements now uses a safer internal initializer to prevent crashes when duplicate keys are used. In the event that duplicate keys are present, the value associated with the first key will override all other values. Thank you to @adysart for raising the issue.
  • Fix data race in AsyncReadWriteLock (#862): This fixes issue #3616. Thank you to @AlexPan1992 for raising the issue.
  • Set URLRequest.cachePolicy on GET requests (#859): Thank you to @samjdurante for the contribution.
Fixed
  • Fix infinite loop bug in Test Mocks (#842): Thank you to @AlexPan1992 for raising the issue.
  • Improve error description formatting for validation failure (#846): GraphQL validation errors encountered while running code generation are now formatted to be easier to read in logs. Thank you to @dfed for the contribution.
  • Fix deadlock in AsyncReadWriteLock (#851): When under heavy loads, the AsyncReadWriteLock used by the ApolloStore could cause a deadlock. This is now resolved. Thank you to @marksvend for raising the issue.
  • Fix cancellation error for single response operations (#855): When a single response operation was cancelled, a .noResults error was thrown instead of the expected CancellationError. This is now resolved. Thank you to @3redrubies for raising the issue.
  • Fix multipart parsing error (#852): When a multipart message was received with characters after the closing boundary the multipart parser would emit a cannotParseChunkData parsing error. This is now resolved. Thank you to @ecant for raising the issue.
Fixed
  • Include merged fields in selection set equality check (#3602): When a field merged from a child object in a named fragment was merged, it was not being used for equality checks. Equality checks now use the types __fulfilledFragments and collects selections from all of them, instead of just traversing downward from self.__selections. This ensures all expected data is collected from merged fragments. See PR #832. Thank you to @JOyo246 for raising the issue.
  • Percent encode semicolons when using GET (#812): Semicolons were not being correctly encoded into the query string when useGETForQueries was enabled. Thank you to @nevil for the contribution.
Fixed
  • Percent encode semicolons when using GET (#812): Semicolons were not being correctly encoded into the query string when useGETForQueries was enabled. Thank you to @nevil for the contribution.
  • Include merged fields in selection set equality check (#3602): When a field merged from a child object in a named fragment was merged, it was not being used for equality checks. Equality checks now use the types __fulfilledFragments and collects selections from all of them, instead of just traversing downward from self.__selections. This ensures all expected data is collected from merged fragments. See PR #832. Thank you to @JOyo246 for raising the issue.
  • Fixed compilation of initializers for mock objects with custom scalars (#3599): Default values for custom scalars were not compiling due to SPI usage. See PR #838. _Thank you to @akoslowski for raising the issue.
  • Fixed infinite loop in parsing invalid multipart messages (#3608): When a multipart message did not end with the correct ending delimiter, the parser would loop over the line infinitely. See PR #839. _Thank you to @frehulfd for raising the issue.

This version has no new changes since v1.25.1 and is being created to fix an issue where the previous version was tagged incorrectly.

Fixed
  • Fixed SelectionSet equality with @include/@skip fields (#840): When a single field was used in a selection set with an @include/@skip directive, an assertionFailure would crash the program. This is now fixed.
Fixed
  • Fixed SelectionSet equality with @include/@skip fields (#840): When a single field was used in a selection set with an @include/@skip directive, an assertionFailure would crash the program. This is now fixed.
Fixed
  • Narrowly Scoped SelectionSet Equality (#3579): SelectionSet equality now uses a narrowly scoped algorithm that only compares fields in the underlying data that are relevant to the SelectionSet. This fixes a bug where a fragment read back from the graph doesn't match one created in memory by ensuring that equality checks for a fragment do not consider fields that are not included in the fragment, even if they are present in the data. Previous equality checks would simply compare the underlying DataDict dictionary which was incorrect. See PR #771. Thank you to @potrebic for raising the issue.

Note: This change is fixing a long-standing bug in SelectionSet equality, however it may highlight previously hidden equality issues and appear to be a bug. If you're convinced this new equality behaviour exposes a bug please open a new issue and we can discuss it.

Fixed
  • SPM CLI Installation (#795): Fixed CLI installation via Swift Package Manager by standardizing relative path handling.

  • SPI Attributes on Internal Models (#796): Fixed code generation to exclude @_spi attributes from models with internal access modifier, preventing compilation errors.

Apollo iOS 2.0 is now available! 🎉

Apollo iOS 2.0 represents a complete reimplementation of many components of the library, redesigned from the ground up to take full advantage of Swift's modern concurrency model. This major release introduces significant breaking changes but provides substantial improvements in type safety, performance, and developer experience.

🚀 What's New
  • Swift Concurrency First: Complete reimplementation using async/await and structured concurrency
  • Streamlined APIs: Simplified client APIs with clearer separation of concerns and more precise type safety
  • Modern Swift Features: Full adoption of Swift 6 with strict concurrency enabled
  • Enhanced Request Chain: New interceptor framework with separate types for different request phases
  • Sendable Types: Most types now conform to Sendable for improved thread safety
🔧 Major API Changes
  • ApolloClient: Complete redesign using async/await instead of callback-based APIs
  • Cache Policies: Split into discrete types (cacheFirst, networkFirst, networkOnly, cacheOnly, cacheAndNetwork) with specific return signatures
  • Request Interceptors: New framework with GraphQLInterceptor, HTTPInterceptor, CacheInterceptor, and ResponseParsingInterceptor types
  • GraphQLResponse: Renamed from GraphQLResult with improved generic typing over operations
⚠️ Breaking Changes & Limitations

Minimum Deployment Targets

  • iOS 15.0+ (was iOS 12.0+)
  • macOS 12.0+ (was macOS 10.14+)
  • tvOS 15.0+ (was tvOS 12.0+)
  • watchOS 8.0+ (was watchOS 5.0+)
  • visionOS 1.0+ (new)

Removed Features

  • CocoaPods Support: No longer available. Use Swift Package Manager or XCFrameworks
  • Legacy Network Session: URLSessionClient replaced with ApolloURLSession protocol
  • RequestContext: Replaced with Swift 6 @TaskLocal values for dependency injection

Current Limitations

  • Web Socket Support: Not available in initial 2.0 release. HTTP subscriptions are supported via RequestChainNetworkTransport. Web socket support will be added in a future 2.0.x release.
  • Deprecated APIs: 1.x callback-based APIs are deprecated but still available for incremental migration
📖 Migration Guide

Apollo iOS 2.0 migration follows a two-phase approach:

Phase 1: Breaking Changes

  • Update request/response models with code-generation
  • Migrate custom Interceptors to new discrete types
  • Update custom NetworkTransport implementations
  • Update custom NormalizedCache implementations

Phase 2: Incremental Updates

  • Migrate from deprecated callback APIs to new async/await APIs
  • Update cache policies to use new discrete types
  • Replace RequestContext with @TaskLocal values

For detailed migration instructions, see the Apollo iOS 2.0 Migration Guide.

🎯 Recommended Migration Path
  1. Update dependency to Apollo iOS 2.0
  2. Re-run code generation with 2.0 engine
  3. Fix breaking changes (custom interceptors, network transports, etc.)
  4. Incrementally migrate ApolloClient usage from callbacks to async/await
  5. Test thoroughly at each step
New
  • Configure cache keys for an operation using the new @fieldPolicy directive. (#735): Added a new @fieldPolicy directive that can be used to configure cache keys for reading data from the cache prior to making a network request for an operation. Cache keys can also be configured programatically, for more information see documentation here.
Improvement
  • Add batching to sqlite selects. (#725): Adding batching to the SQLite select handling to cap the number of parameters at 500 per query.
  • Add result code to SQLiteError. (#755): Adding the raw sqlite result code as an associated value on enum cases of SQLiteError.
  • Add RootSelectionSet convenience initializer from inline fragment. (#748): Added a convenience initializer to RootSelectionSet that allows it to be initialized directly from an InlineFragment, simplifying the conversion process between fragments and root entity types.
  • Make dependentKeys in GraphQLResult public. (#758): Making dependentKeys public allows for implementing custom ApolloStoreSubscribers similar to GraphQLQueryWatcher. Without this it's extremely difficult to know when to react to cache changes for a query. _Thank you to @chrsmys for the contribution.
Fixed
  • Duplicate deferred fragment identifiers. (#700): The deferred fragment identifier was being generated using all elements in the deferred fragments path type info array. While the contents of that array are correct because of the unique selection sets, the identifier is able to be shared amongst elements with the same path and defer condition. Taking this into account the identifiers are now generated without duplicates.
  • Fix generated default mock initializer for lowercase type names. (#712): Type name in mock initializer of a type with a lowercase name was being inadvertently captialized. Thank you to @dwroth for the contribution.
  • Deferred fragment accessor with nested fragment. (#709): The selection set template would correctly produce a fragment accessor property for merged deferred fragments but the initializer was missing.
  • Change clientVersion build delimiter. (#721): This changes the version/build delimiter from a - to a +. This now matches the semver specification of that additional metadata.
New
  • Added requireNonOptionalMockFields flag to ApolloCodegenConfiguration.OutputOptions. (#669): Added new flag to codegen output options to allow having non-optional fields in the test mocks if desired. Thank you to @dwroth for the contribution.
Improvement
  • Added public initializer to DatabaseRow. (#664): Not having a public initializer on DatabasRow was hindering the ability to create custom SQLiteDatabase implementations. This solves that by adding a public initializer to DatabaseRow.Thank you to @ChrisLaganiere for the contribution.
Fixed
  • Unncessary deprecation warning in codegen options initializer. (#3563): Added @_disfavoredOverload to the deprecated initialized in ApolloCodegenConfiguration to prevent possible warnings caused by the compiler selecting a deprecated initializer versus the new/current initializer. See PR #682. Thank you to @CraigSiemens for raising the issue.
Improvement
  • Make cache public within ReadTransaction (#661): Some users have use cases for accessing a custom NormalizedCache implementation directly while performing cache transactions. A new ReadOnlyNormalizedCache protocol exposes the cache as read-only in the ReadTransaction and as writable in the ReadWriteTransaction. See PR #661.
Fixed
  • Multiple deprecation warning directives not compiling (#3559): Codegen would generate an incorrect list-style character between the Swift deprecation annotations when using multiple deprecation directives in GraphQL. See PR #658. Thank you to @guilherme-anchorage for raising the issue.
  • Non-all field merging causes selection set initializers to stop being generated for local cache mutations (#3554): Codegen will now force field merging behaviour and selection set initializer generation for local cache mutations. See PR #654.
  • Referenced fragments within a local cache mutation operation are generated as mutable (#3557): Any fragments referenced within a local cache mutation will now be generated as mutable too, including any fragments within those fragments. See PR #659.
Last Checked
5h ago
Tracking since Sep 2, 2021