Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(imagepicker): use PHPickerViewController on iOS
Replace the QBImagePickerController pod with the system photo picker
(iOS 14+). The public API is unchanged: create(), authorize(), present()
and the ImagePickerSelection shape all behave as before, and cancel still
rejects with Error('Canceled').

- No CocoaPods dependency any more; the picker runs out of process.
- authorize() is now optional. With library access, picks resolve to
  their PHAsset as before; without it, the picker's file copy is used.
- Ordered multi-select honours maximumNumberOfSelection.
- The iOS-only UI options (prompt, column counts, etc.) are marked
  deprecated since the system picker owns its own UI.
  • Loading branch information
sitefinitysteve committed Sep 11, 2026
commit 8dd42188656f0432588b45bc8aba48eb59f527cc
32 changes: 25 additions & 7 deletions packages/imagepicker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

Imagepicker plugin supporting both single and multiple selection.

- Plugin supports **iOS8+** and uses [QBImagePicker](https://github.com/questbeat/QBImagePicker) cocoapod.
- Plugin supports **iOS 14+** and uses the system [PHPickerViewController](https://developer.apple.com/documentation/photokit/phpickerviewcontroller) (the modern Photos picker with search and albums). No CocoaPods dependency is required.
- For **Android** it uses [Intents](https://developer.android.com/reference/android/content/Intent) to open the stock images or file pickers. For Android 6 (API 23) and above, the permissions to read file storage should be explicitly required.

## Installation
Expand All @@ -28,6 +28,11 @@ Install the plugin by running the following command in the root directory of you
```cli
npm install @nativescript/imagepicker
```
**Note: Version 5.1 changes on iOS:**
* The picker is now the system `PHPickerViewController`. It runs out of process, so it can be presented without photo-library permission; calling `authorize()` first is still recommended so that selections resolve to their `PHAsset` (see [iOS required permissions](#ios-required-permissions)).
* `minimumNumberOfSelection`, `showsNumberOfSelectedAssets`, `prompt`, `numberOfColumnsInPortrait` and `numberOfColumnsInLandscape` are accepted but have no effect, because the system picker owns its own UI.
* Requires iOS 14 or later.

**Note: Version 3.1 contains breaking changes:**
* New behavior on iOS when the user selects `Limit AccessLim..` detailed in [iOS Limited permission](#ios-limited-permission).

Expand Down Expand Up @@ -82,7 +87,9 @@ For phones running < Android 13, this `use_photo_picker` option has no effect.

### iOS required permissions

Using the plugin on iOS requires the `NSPhotoLibraryUsageDescription` permission. Modify the `app/App_Resources/iOS/Info.plist` file to add it as follows:
The system picker itself needs no permission. `authorize()` requests photo-library access so that picked items resolve to their `PHAsset` (giving you `asset`, `filesize`, `duration` and `thumbnail` straight from the library). If access is not granted, `present()` still works: the picker hands over a copy of each selected file, which the plugin stores in the app's temporary folder and exposes through `path` and `asset`.

Calling `authorize()` requires the `NSPhotoLibraryUsageDescription` permission. Modify the `app/App_Resources/iOS/Info.plist` file to add it as follows:

```xml
<key>NSPhotoLibraryUsageDescription</key>
Expand All @@ -96,6 +103,8 @@ Apple introduced the `PHAuthorizationStatusLimited` permission status with iOS 1

In this case `authorise()` will return an `AuthorizationResult` where `authorized` will be `true` and the `details` will contain `'limited'`.

With limited access the system picker still lets the user browse their whole library. Items inside the limited selection resolve to their `PHAsset`; any other item falls back to a copy of the file, exactly as when access was not granted. A single `present()` call can therefore return a mix of both.

Every time the app is launched anew, and the authorize method is called, if the current permission is `limited` the user will be prompted to update the image selection.

To prevent this prompt, add the following values to your `App_Resources/iOS/Info.plist`:
Expand Down Expand Up @@ -159,6 +168,15 @@ imagePickerObj
});
```

On iOS you may also skip `authorize()` altogether: `present()` shows the system picker without any permission and every selection comes back as a file copy (with `asset`, `path`, `filename`, `filesize`, `type`, `duration` and `thumbnail` still populated).

<!--tabs: TS -->
```ts
if (isIOS) {
const selection = await imagePickerObj.present(); // rejects with Error('Canceled') if dismissed
}
```

### Demo
You can play with the plugin on StackBlitz at any of the following links:

Expand Down Expand Up @@ -187,12 +205,12 @@ An object passed to the `create` method to specify the characteristics of a medi
| Option | Type | Default |Description
|:---------------------------|:-------- |:---------|:-------
| `mode` | `string` | `multiple` | The mode of the imagepicker. Possible values are `single` for single selection and `multiple` for multiple selection. |
| `minimumNumberOfSelection` | `number` | `0` | _Optional_: (`iOS-only`) The minumum number of selected assets. |
| `minimumNumberOfSelection` | `number` | `0` | _Optional_: (`iOS-only`) Deprecated: ignored by the system picker. |
| `maximumNumberOfSelection` | `number` | `0` | _Optional_: (`iOS-only`, `Android-Photo Picker-Only`) The maximum number of selected assets. |
| `showsNumberOfSelectedAssets` | `boolean` | `true` | _Optional_: (`iOS-only`) Display the number of selected assets. |
| `prompt` | `string` | `undefined` | _Optional_: (`iOS-only`) Display prompt text when selecting assets. |
| `numberOfColumnsInPortrait` | `number` | `4` | _Optional_: (`iOS-only`) Sets the number of columns in Portrait orientation |
| `numberOfColumnsInLandscape` | `number` | `7` | _Optional_: (`iOS-only`) Sets the number of columns in Landscape orientation. |
| `showsNumberOfSelectedAssets` | `boolean` | `true` | _Optional_: (`iOS-only`) Deprecated: ignored by the system picker. |
| `prompt` | `string` | `undefined` | _Optional_: (`iOS-only`) Deprecated: ignored by the system picker. |
| `numberOfColumnsInPortrait` | `number` | `4` | _Optional_: (`iOS-only`) Deprecated: ignored by the system picker. |
| `numberOfColumnsInLandscape` | `number` | `7` | _Optional_: (`iOS-only`) Deprecated: ignored by the system picker. |
| `mediaType` | [ImagePickerMediaType](#imagepickermediatype) | `Any` |_Optional_: The type of media asset to pick whether to pick Image/Video/Any type of assets. |
| `copyToAppFolder` | `string` | `undefined` | _Optional_: If passed, a new folder will be created in your applications folder and the asset will be copied there. |
| `renameFileTo` | `string` | `undefined` | _Optional_: If passed, the copied file will be named what you choose. If you select multiple, -index will be appended. |
Expand Down
15 changes: 10 additions & 5 deletions packages/imagepicker/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ export interface Options {
mode?: string;

/**
* Set the minumum number of selected assets in iOS
* Set the minumum number of selected assets in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
minimumNumberOfSelection?: number;

Expand All @@ -69,22 +70,26 @@ export interface Options {
maximumNumberOfSelection?: number;

/**
* Display the number of selected assets in iOS
* Display the number of selected assets in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
showsNumberOfSelectedAssets?: boolean;

/**
* Display prompt text when selecting assets in iOS
* Display prompt text when selecting assets in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
prompt?: string;

/**
* Set the number of columns in Portrait in iOS
* Set the number of columns in Portrait in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
numberOfColumnsInPortrait?: number;

/**
* Set the number of columns in Landscape in iOS
* Set the number of columns in Landscape in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
numberOfColumnsInLandscape?: number;

Expand Down
15 changes: 10 additions & 5 deletions packages/imagepicker/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ interface Options {
mode?: string;

/**
* Set the minumum number of selected assets in iOS
* Set the minumum number of selected assets in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
minimumNumberOfSelection?: number;

Expand All @@ -84,22 +85,26 @@ interface Options {
maximumNumberOfSelection?: number;

/**
* Display the number of selected assets in iOS
* Display the number of selected assets in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
showsNumberOfSelectedAssets?: boolean;

/**
* Display prompt text when selecting assets in iOS
* Display prompt text when selecting assets in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
prompt?: string;

/**
* Set the number of columns in Portrait in iOS
* Set the number of columns in Portrait in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
numberOfColumnsInPortrait?: number;

/**
* Set the number of columns in Landscape in iOS
* Set the number of columns in Landscape in iOS.
* @deprecated Ignored since 5.1: the system PHPickerViewController owns its own UI.
*/
numberOfColumnsInLandscape?: number;

Expand Down
Loading