---
title: "Nutrient iOS SDK 27 release notes"
canonical_url: "https://www.nutrient.io/guides/ios/releases/27/"
md_url: "https://www.nutrient.io/guides/ios/releases/27.md"
last_updated: "2026-09-07T00:00:00.000Z"
description: "Nutrient iOS SDK 27 supports iOS 27, macOS 27, visionOS 27, and Xcode 27. It adds progressive page rendering and updates on-device AI Assistant on iOS 27."
---

16 September 2026

Nutrient iOS SDK 27 is the annual release for iOS 27, macOS 27, visionOS 27, and Xcode 27. It adds progressive page rendering and updates on-device AI Assistant on iOS 27, including support for your own model.

Following our [version numbering system](https://www.nutrient.io/guides/ios/best-practices/version-numbering.md), this upgrade has one API change. Configure AI Assistant with the new API, or keep the old API with a deprecation warning.

For the full list of changes, refer to the [changelog](https://www.nutrient.io/guides/ios/changelog.md#27.0.0).

## iOS 27 and Xcode 27

Nutrient iOS SDK 27 requires Xcode 27. If your app still sets [`UIDesignRequiresCompatibility`](https://developer.apple.com/documentation/BundleResources/Information-Property-List/UIDesignRequiresCompatibility) to keep the old design, note that Xcode 27 ignores this key. Users on iOS 27 get the new design.

iOS 27 uses a hard scroll edge effect by default. Content stops below the navigation bar with a dividing line instead of the soft fade from iOS 26, and Nutrient follows the system default.![Screenshot of Nutrient iOS SDK 27 on iPad running iOS 27, showing the hard scroll edge effect below the navigation bar, the annotation toolbar, and the text selection menu.](@/assets/guides/ios/releases/27-ipad.png)

If you prefer the softer look, set the style on the document scroll view. The Catalog app includes the new [`SoftScrollEdgeEffectExample`](https://github.com/PSPDFKit/pspdfkit-ios-catalog/blob/master/Catalog/Examples/ViewCustomization/SoftScrollEdgeEffectExample.swift).

If you want to stay on Xcode 26, keep using [Nutrient iOS SDK 26.12](https://www.nutrient.io/guides/ios/releases/26-12.md). For more details, refer to the [system compatibility](https://www.nutrient.io/guides/ios/announcements/version-support.md) guide.

## Progressive rendering

Pages with detailed vector content, such as building plans and maps, can take longer to render. Earlier releases showed a blank page or blurry placeholder until the full page finished rendering.

Nutrient iOS SDK 27 renders these pages in short steps. It shows each partial result as soon as it’s ready, so content appears while rendering continues.

Progressive rendering is enabled by default and needs no code changes. Pages that already render without delay look the same as before, and zoomed-in rendering is unchanged.

This continues our long-term work on responsiveness for complex documents. Recent releases covered [opening large documents](https://www.nutrient.io/guides/ios/releases/26-4.md), [memory usage](https://www.nutrient.io/guides/ios/releases/26-10.md), and [annotation editing](https://www.nutrient.io/guides/ios/releases/26-11.md).

## On-device AI Assistant

We introduced [on-device AI Assistant](https://www.nutrient.io/guides/ios/ai-assistant/on-device.md) using Apple’s Foundation Models in [Nutrient iOS SDK 26.2](https://www.nutrient.io/guides/ios/releases/26-2.md). This release changes how AI Assistant works on iOS 27.

On iOS 27, AI Assistant with Apple’s system model becomes an agent built on the new Foundation Models APIs. It uses a [`LanguageModelSession`](https://developer.apple.com/documentation/foundationmodels/languagemodelsession) with a [dynamic profile](https://developer.apple.com/documentation/foundationmodels/languagemodelsession/dynamicprofile), whose instructions change as a turn moves from research to answering. It also uses [tool calling](https://developer.apple.com/documentation/foundationmodels/tool) so the model can search the document.

Instead of using one retrieval pass before generating, the model resolves follow-up questions against the conversation. It runs focused searches when one search isn’t enough and verifies evidence before answering.

On iOS 26, these APIs aren’t available, so AI Assistant keeps the single-retrieval approach. Long conversations are more reliable on both versions because conversation context stays available when the model session rebuilds.

### Bring your own model

On iOS 27, you can run AI Assistant with any Foundation Models model that conforms to the [`LanguageModel`](https://developer.apple.com/documentation/foundationmodels/languagemodel) protocol. Use [`AIAssistantModel.custom(_:identifier:contextWindow:)`](https://www.nutrient.io/api/ios/documentation/pspdfkit/aiassistantmodel/custom(_:identifier:contextwindow:)) instead of Apple’s system model.

This supports larger or specialized open-weight models, including models hosted through [MLX](https://github.com/ml-explore/mlx-swift). Our example project runs Qwen 3 4B through MLX and shows it in the standard AI Assistant UI.

A custom model can run on the device or call a server, depending on its implementation. AI Assistant sends document text, questions, and conversation history to the model. Review the model’s data handling before you ship.

### Configuring AI Assistant

[`PDFConfiguration`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/pdfconfiguration) now has one [`aiAssistantSource`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/pdfconfiguration/aiassistantsource) property for server and on-device setups. Use it to select a Nutrient AI Assistant server or a language model. The default is the system model, so existing setups keep the same behavior.

```swift

// Nutrient AI Assistant server:
$0.aiAssistantSource =.server(serverConfiguration)

// Apple’s system model (the default):
$0.aiAssistantSource =.languageModel(.system)

// Your own Foundation Models language model on iOS 27:
$0.aiAssistantSource =.languageModel(.custom(model, identifier: "qwen3-4b-4bit:8k", contextWindow: 8_192))

```

On-device AI Assistant is a license component for Nutrient iOS SDK. Contact [Nutrient Support](https://support.nutrient.io/hc/en-us/requests/new) if you’d like to try it.

## Migration notes

This release only deprecates AI Assistant configuration APIs. Existing code compiles with warnings and behaves the same as before, so you can migrate when you’re ready.

| Deprecated                                                              | Replacement                                                           | Recommended change                                                                                                              |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| [`AIAssistantConfiguration`](https://www.nutrient.io/api/ios/documentation/pspdfkit/aiassistantconfiguration)                | [`AIAssistantServerConfiguration`](https://www.nutrient.io/api/ios/documentation/pspdfkit/aiassistantserverconfiguration) | Rename. It’s the same type with the same initializer.                                                                           |
| [`PDFConfiguration.aiAssistantConfiguration`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/pdfconfiguration/aiassistantconfiguration) | [`PDFConfiguration.aiAssistantSource`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/pdfconfiguration/aiassistantsource)           | Wrap your server configuration in `.server(…)`. If you read the property, match on `.server` instead of unwrapping an optional. |

If you connect to a Nutrient AI Assistant server, your setup changes from this example:

```swift

let configuration = AIAssistantConfiguration(serverURL: serverURL, jwt: jwt, sessionID: sessionID)
let controller = PDFViewController(document: document) {
    $0.aiAssistantConfiguration = configuration
}

```

Use this configuration instead:

```swift

let configuration = AIAssistantServerConfiguration(serverURL: serverURL, jwt: jwt, sessionID: sessionID)
let controller = PDFViewController(document: document) {
    $0.aiAssistantSource =.server(configuration)
}

```

If you use on-device AI Assistant with the system model, you don’t need to change anything. [`AIAssistantSession(documents:configuration:)`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/aiassistantsession/init(documents:configuration:)) continues to take a server configuration. The new [`AIAssistantSession(document:configuration:)`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/aiassistantsession/init(document:configuration:)) takes an [`AIAssistantModelConfiguration`](https://www.nutrient.io/api/ios/documentation/pspdfkit/aiassistantmodelconfiguration) when you present [`AIAssistantView`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/aiassistantview) or [`AIAssistantViewController`](https://www.nutrient.io/api/ios/documentation/pspdfkitui/aiassistantviewcontroller) yourself with a language model.
---

## Related pages

- [14 12](/guides/ios/releases/14-12.md)
- [26 1](/guides/ios/releases/26-1.md)
- [26 10](/guides/ios/releases/26-10.md)
- [26 11](/guides/ios/releases/26-11.md)
- [26 12](/guides/ios/releases/26-12.md)
- [26 2](/guides/ios/releases/26-2.md)
- [26 3](/guides/ios/releases/26-3.md)
- [26 4](/guides/ios/releases/26-4.md)
- [26 5](/guides/ios/releases/26-5.md)
- [26 6](/guides/ios/releases/26-6.md)
- [26 7](/guides/ios/releases/26-7.md)
- [26 8](/guides/ios/releases/26-8.md)
- [26 9](/guides/ios/releases/26-9.md)
- [26](/guides/ios/releases/26.md)

