Baseflow / Baseflow/flutter-geolocator
BYPASS_PERMISSION_LOCATION_ALWAYS cannot be set under Swift Package Manager (ITMS-90683 returns)
- Dominant language
- Dart
- Stars
- 1.3k
- Forks
- 803
- Avg merge
- 8h 16m
- Merged PRs (30d)
- 1
Description
#1241 was closed by #1403, which added `BYPASS_PERMISSION_LOCATION_ALWAYS`. That
switch is set from the `Podfile`'s `post_install` hook, so it only exists for
CocoaPods builds. Flutter now supports Swift Package Manager for iOS, and under
SPM there is no `Podfile` — and no supported way to set the macro. The coverage
`#1403` established is therefore lost for every project that has migrated.
**A consuming project cannot inject preprocessor macros into a package target.**
`GCC_PREPROCESSOR_DEFINITIONS` on the app target applies to that target only; it
does not propagate into a Swift package's targets. The package manifest is the
only place those settings can come from.
`geolocator_apple` 2.3.14's `Package.swift` has neither a `.define` nor any
environment lookup:
```swift
targets: [
.target(
name: "geolocator_apple",
dependencies: [],
resources: [.process("PrivacyInfo.xcprivacy")],
publicHeadersPath: "include/geolocator_apple",
cSettings: [.headerSearchPath("include/geolocator_apple")]
)
]
```
So `#if !BYPASS_PERMISSION_LOCATION_ALWAYS` in `Handlers/PermissionHandler.m` is
always true under SPM, and `requestAlwaysAuthorization` is compiled into every
app that uses this plugin.
**Consequence: ITMS-90683 is back for every SPM app, even one that only ever
uses when-in-use.** Verified on a release archive built with `flutter build ipa`
(Flutter 3.44.2, geolocator 14.0.3 / geolocator_apple 2.3.14). The app declares
only `NSLocationWhenInUseUsageDescription` and never requests
always-authorization from Dart. From the uploaded archive:
```
$ strings Payload/Runner.app/Runner | grep containsLocationAlwaysDescription
containsLocationAlwaysDescription
$ strings Payload/Runner.app/Runner | grep -x requestAlwaysAuthorization
requestAlwaysAuthorization
```
`containsLocationAlwaysDescription` is declared inside the
`#if !BYPASS_PERMISSION_LOCATION_ALWAYS` block, so its presence is the direct
evidence that the bypass was not set. App Store Connect returned ITMS-90683 on
upload of that build.
Worth noting how dead this code is for such apps: on iOS the always branch is an
`else if` behind the when-in-use check —
```objc
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != nil) {
[locationManager requestWhenInUseAuthorization];
}
#if !BYPASS_PERMISSION_LOCATION_ALWAYS
else if ([self containsLocationAlwaysDescription]) {
[locationManager requestAlwaysAuthorization];
}
#endif
```
— so for any app that declares the when-in-use key, the always call can never
execute. It is unreachable at runtime and still costs the warning at upload.
### Reproduction
1. `flutter config --enable-swift-package-manager`
2. Any app with `geolocator`, declaring only
`NSLocationWhenInUseUsageDescription`
3. `flutter build ipa`, then `xcrun altool --upload-app`
→ ITMS-90683 (missing `NSLocationAlwaysAndWhenInUseUsageDescription`)
There is no `Podfile` in this setup, so the `post_install` hook from #1403 never
runs.
### Prior art in the sibling package
`permission_handler_apple` 9.6.1 solves exactly this for SPM: its `Package.swift`
locates the app's `Info.plist` (via `INFOPLIST_FILE` from the Xcode project and
`.xcconfig` files) and derives each `PERMISSION_*` macro from the presence of the
matching `NS*UsageDescription` key, with an environment variable as an override.
Measured on the same archive, only the permissions the app declares are compiled
in — `CNContactStore`, `AVCaptureDevice`, `PHPhotoLibrary`, `CBCentralManager`,
`SFSpeechRecognizer`, `ATTrackingManager` and `EKEventStore` are all absent from
the binary.
### Suggestion
Either of these would close the gap:
1. Derive the switch in `Package.swift` the way `permission_handler_apple` does —
compile the always branch only when `NSLocationAlwaysUsageDescription` or
`NSLocationAlwaysAndWhenInUseUsageDescription` is actually present. That
matches the existing runtime condition exactly, so no app changes behaviour.
2. Failing that, read an environment variable in the manifest, or expose it as a
package trait, so the choice is at least expressible.
Happy to open a PR for option 1 if that direction is welcome.
Contributor guide
Research direction
Start with geolocator_apple's Package.swift and Handlers/PermissionHandler.m, then compare the SPM setup with permission_handler_apple's Package.swift. Reproduce with Flutter's SPM configuration and an app declaring only NSLocationWhenInUseUsageDescription. Done means the release archive no longer contains the unreachable always-authorization path or triggers ITMS-90683 for that app.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart, flutter, objective-c, swift
- Domain
- build-system, mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100