Skip to content

[image_picker_ios] PR 5/5 Switch Pigeon to Swift and finish the Objective-C to Swift migration. - #13493

Merged
auto-submit[bot] merged 5 commits into
flutter:mainfrom
victogomez-cs:pr5/image-picker-ios-swift-pigeon
Nov 5, 2026
Merged

auto-submit[bot] merged 5 commits into
flutter:mainfrom
victogomez-cs:pr5/image-picker-ios-swift-pigeon

Conversation

@victogomez-cs

@victogomez-cs victogomez-cs commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Switches image_picker_ios Pigeon output from Objective-C to Swift and removes the remaining Objective-C packaging:

  • pigeons/messages.dart now generates messages.g.swift instead of messages.g.h and messages.g.m.
  • ImagePickerPlugin and the PHPicker save operation use the generated Swift API, including PigeonError instead of FlutterError.
  • Deletes the image_picker_ios_objc Swift Package Manager target, the image_picker_ios.h umbrella header, and the custom module map.
  • The CocoaPods pod is Swift-only and no longer sets s.module_map.

The iOS example app and UI tests stay Objective-C until the next PR.

Bumps image_picker_ios to 0.8.13+15.

PR 5/5 of the Obj-C → Swift migration, following #13394. Part of flutter/flutter#119107

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Oct 29, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the iOS image picker plugin's Pigeon integration from Objective-C to Swift, removing the Objective-C dependency and updating the plugin and its tests to use the new Swift-native types and PigeonError. Feedback on the changes suggests renaming a test helper method to match a renamed production method, and utilizing Swift's implicit bridging to cast optional Double values directly to NSNumber? instead of using .map.

/// Saves run on a background queue and the result is delivered later on the
/// main queue, so `confirmation` would return before the callback runs.
/// `#expect` on that queue is not recorded on this test.
private func processPickerItems(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The helper method processPickerItems should be renamed to processPickerResults to remain consistent with the renamed production method processPickerResults in ImagePickerPlugin and the updated doc comment above.\n\nNote: If you apply this suggestion, please make sure to also rename any other call sites of this helper method within this test file to avoid compilation errors.

Suggested change
private func processPickerItems(
private func processPickerResults(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the helper to processPickerResults, including its three call sites, so it matches ImagePickerPlugin.processPickerResults

Comment on lines +490 to +491
let maxWidth = currentCallContext?.maxSize?.width.map { NSNumber(value: $0) }
let maxHeight = currentCallContext?.maxSize?.height.map { NSNumber(value: $0) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of using .map { NSNumber(value: $0) }, you can leverage Swift's implicit bridging to NSNumber by casting the optional Double directly using as NSNumber?. This is more concise and idiomatic.

    let maxWidth = currentCallContext?.maxSize?.width as NSNumber?\n    let maxHeight = currentCallContext?.maxSize?.height as NSNumber?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. width and height are now cast with as NSNumber? here

Comment on lines +567 to +568
let maxWidth = callContext?.maxSize?.width.map { NSNumber(value: $0) }
let maxHeight = callContext?.maxSize?.height.map { NSNumber(value: $0) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of using .map { NSNumber(value: $0) }, you can leverage Swift's implicit bridging to NSNumber by casting the optional Double directly using as NSNumber?. This is more concise and idiomatic.

      let maxWidth = callContext?.maxSize?.width as NSNumber?\n      let maxHeight = callContext?.maxSize?.height as NSNumber?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. The camera path uses the same as NSNumber? cast

@victogomez-cs victogomez-cs added the triage-ios Should be looked at in iOS triage label Oct 29, 2026

@stuartmorgan stuartmorgan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have a full iOS team review still, but some drive-by comments as someone familiar with Swift Pigeon conversions.

return
}
completion(paths?.first, error)
if let error {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it safe to use the abbreviated syntax now? The podspec is still listing the Swift version as 5.0, and this is 5.7+ syntax. Maybe it's moot under the current Xcode version requirements though?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. s.swift_version = '5.0' selects the Swift 5 language mode. if let error is Swift 5.7, and this package requires Flutter 3.47, whose iOS toolchain is well past that

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I double checked https://xcodereleases.com/ - Swift 5.7 is in Xcode 14 so we are safe

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of these entries are doing anything any more; they should be replaced with @SwiftFunction annotations where needed, and remove where no longer useful.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed all five @ObjCSelectors. The generated Swift names already match the plugin (pickImage(source:maxSize:imageQuality:requestFullMetadata:completion:) and the other four), so none of them need an @SwiftFunction. Regenerating Pigeon did not change the generated Dart or Swift

}

func desiredImageQuality(_ imageQuality: NSNumber?) -> NSNumber {
func desiredImageQuality(_ imageQuality: Int64?) -> NSNumber {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't all of the usage of NSNumber that still exists in this file (and the internal utilities they call to) a legacy of the Pigeon APIs using NSNumbers to express nullability? I would expect that everything in the entire plugin could stop using NSNumber as part of this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done for the plugin's own values. desiredImageQuality now returns Double, and max width, max height, and quality are Double? through the save operation and the image utilities. The remaining NSNumbers are ImageIO dictionary values (GIF delay, GIF loop count, and EXIF), not the old Pigeon nullability wrappers

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The remaining NSNumbers are ImageIO dictionary values (GIF delay, GIF loop count, and EXIF), not the old Pigeon nullability wrappers

Option since it's not entirely in scope, but doesn't reading the dictionary values with as? Double? or as? Int? trigged the auto-bridging and avoid the need to manually call doubleValue/intValue later (and the need to reference NSNumber directly in Swift code at all)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. as? Double and as? Int bridge the ImageIO NSNumbers, so the GIF delay, loop count, and EXIF dimension no longer go through NSNumber, doubleValue, or intValue. I used as? Double and as? Int rather than as? Double?

@jmagman
jmagman requested review from hellohuanlin and removed request for okorohelijah and vashworth November 4, 2026 17:59
maxDurationSeconds: nil
) { result in
guard case .failure(let error as PigeonError) = result else {
Issue.record("Expected invalid_result")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These message could be useful when tests fail. Can you make them more verbose?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Each Issue.record in this file now includes the actual result

return
}
completion(paths?.first, error)
if let error {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I double checked https://xcodereleases.com/ - Swift 5.7 is in Xcode 14 so we are safe

…for clarity in test cases and update related references.
…e size and quality.

Swift Pigeon ignores the old selectors, and NSNumber was only wrapping nullable width, height, and quality.
…IF and GIF properties.

Additionally, modifies ImagePickerImageUtil to handle GIF delay times as Double.
… include result details for better debugging.
@victogomez-cs
victogomez-cs force-pushed the pr5/image-picker-ios-swift-pigeon branch from 9fb26b6 to 403e59a Compare November 4, 2026 19:24
@victogomez-cs victogomez-cs added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 5, 2026
@auto-submit
auto-submit Bot merged commit 46c69b3 into flutter:main Nov 5, 2026
13 checks passed
@victogomez-cs
victogomez-cs deleted the pr5/image-picker-ios-swift-pigeon branch November 5, 2026 16:48
flutter-zl pushed a commit to NemesisDevX/flutter that referenced this pull request Nov 6, 2026
flutter/packages@0478162...63881f9

2026-11-06 [email protected] [material_ui] Paint Dialog.fullscreen
background color behind the keyboard (flutter/packages#13244)
2026-11-05 [email protected] [material_ui] Add tabBar/tab
roles and expanded state semantics (flutter/packages#13176)
2026-11-05 [email protected]
[material_ui] Disable the DropdownButtonFormField decoration when the
field is disabled (flutter/packages#13473)
2026-11-05 [email protected] [material_ui] Fix Switch throwing when first
painted mid-animation (flutter/packages#13496)
2026-11-05 [email protected] [various] Add
engineIdentifier to fake plugin registrars (flutter/packages#13574)
2026-11-05 [email protected] [google_sign_in]
Allow GoogleSignIn-iOS 10 (flutter/packages#13306)
2026-11-05 [email protected] [material_ui] Hit
test the floating label of InputDecorator at its painted position
(flutter/packages#13326)
2026-11-05 [email protected] [material_ui] Fix InputDecorator
intrinsic height when isDense or isC… (flutter/packages#13522)
2026-11-05 [email protected] [material_ui] Paint Scaffold
persistent bottom sheet background color behind the keyboard
(flutter/packages#13242)
2026-11-05 [email protected] [image_picker_ios] PR 5/5 Switch
Pigeon to Swift and finish the Objective-C to Swift migration.
(flutter/packages#13493)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
auto-submit Bot pushed a commit that referenced this pull request Nov 10, 2026
…13570)

Converts the `image_picker_ios` iOS example app and UI tests from Objective-C to Swift:

* `AppDelegate` is now Swift. `@main` replaces `main.m`, and `AppDelegate.h` becomes `Runner-Bridging-Header.h`.
* `ImagePickerFromGalleryUITests` and `ImagePickerFromLimitedGalleryUITests` are now Swift.
* The example still seeds the photo library from `jpgImageTall.jpg`, and logs when that fixture is missing.
* Drops the `@available(iOS 14, *)` checks in the UI tests. The example already requires iOS 15.

The plugin implementation is unchanged from #13493.

Bumps image_picker_ios to **0.8.13+16**.

Follow-up to the Obj-C → Swift migration, following #13493. Part of flutter/flutter#119107

## Pre-Review Checklist

**Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

[^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD p: image_picker platform-ios triage-ios Should be looked at in iOS triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants