Skip to content

Changed Info.plist lookup#1542

Open
olekeke999 wants to merge 2 commits into
Baseflow:mainfrom
olekeke999:SPM-infoplist-lookup
Open

Changed Info.plist lookup#1542
olekeke999 wants to merge 2 commits into
Baseflow:mainfrom
olekeke999:SPM-infoplist-lookup

Conversation

@olekeke999
Copy link
Copy Markdown

@olekeke999 olekeke999 commented Jun 5, 2026

I have flutter 3.44 with global SPM enabled. I noticed on my project that all permissions pernamentlyDenied. I've read similar issues and understood that it's related to lookup of Info.plist permissions.
I tried to use permissions_handler_apple/example ios project, migrated it to SPM and permissions were pernamentlyDenided as well, only if I used launchctl "launchctl setenv PERMISSION_CAMERA 1" it worked.
So I did code changes to improve Info.plist lookup and it helped on both permissions_handler_apple/example and as dependency overwrite in my monorepo project.

  • Package.swift Info.plist lookup fix
  • migrated iOS permissions_handler_apple/example from Pods to SPM

Pre-launch Checklist

  • [+] I made sure the project builds.
  • [+] I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • [+] I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy, or this PR is does not need version changes.
  • [+] I updated CHANGELOG.md to add a description of the change.
  • [-] I updated/added relevant documentation (doc comments with ///).
  • [+] I rebased onto main.
  • [-] I added new tests to check the change I am making, or this PR does not need tests.
  • [-] I made sure all existing and new tests are passing.
  • [-] I ran dart format . and committed any changes.
  • [-] I ran flutter analyze and fixed any errors.

@mvanbeusekom
Copy link
Copy Markdown
Member

Hi @TheoGermain, would you mind helping out and doing a review on this PR? Since you added the initial code I feel your input on this could be very valuable.

@TheoGermain
Copy link
Copy Markdown
Contributor

Hey, thanks for digging into this and providing a reproduction with the example project. The root cause you identified is correct.

With global SPM enabled in Flutter 3.44+, the #file path during manifest evaluation no longer points into the project tree. It ends up somewhere in DerivedData or the global SPM cache, so walking up from there never reaches Runner/Info.plist. The fact that launchctl setenv PERMISSION_CAMERA 1 bypasses the issue confirms exactly this: the env var path works fine, the plist lookup just never finds the file.

Adding FileManager.default.currentDirectoryPath as a second search root is the right instinct, since the working directory during manifest evaluation often stays anchored to the project. That part of the fix makes sense to me.

A few things I would want to look at before merging though.

The recursive subdirectory scan in appendInfoPlistCandidates worries me for monorepo setups. If someone has multiple apps under one root (a common Flutter monorepo pattern), that scan could pick up the wrong Info.plist and silently enable the wrong set of permissions at compile time.

What I would suggest instead is keeping the walk-up approach but using pubspec.yaml as a reliable Flutter project-root anchor. At each level, check whether pubspec.yaml exists alongside ios/Runner/Info.plist. Every Flutter app has exactly one pubspec.yaml at its root, and a melos workspace root may also have one but will never have ios/Runner/Info.plist next to it. This makes the match unambiguous even in monorepos.

Something along these lines:

func findInfoPlist() -> [String: Any] {
    let fm = FileManager.default
    let searchRoots: [URL] = [
        URL(fileURLWithPath: #file).deletingLastPathComponent(),
        URL(fileURLWithPath: fm.currentDirectoryPath),
    ]

    var visited = Set<String>()

    for root in searchRoots {
        var dir = root
        for _ in 0..<12 {
            let key = dir.resolvingSymlinksInPath().path
            guard visited.insert(key).inserted else { break }

            let plistURL = dir.appendingPathComponent("ios/Runner/Info.plist")
            if fm.fileExists(atPath: dir.appendingPathComponent("pubspec.yaml").path),
               let plist = NSDictionary(contentsOf: plistURL) as? [String: Any] {
                return plist
            }

            dir = dir.deletingLastPathComponent()
        }
    }
    return [:]
}

This covers both the standard SPM case and global SPM, deduplicates paths so the two roots do not overlap, and avoids any recursive directory scanning.

The FlutterFramework dependency added to the package target is also something I would want to understand better. The current package does not declare that dependency and resolves fine in normal SPM mode, so I am not sure what it brings here and I would want to make sure it does not break setups where that package is not available at that relative path.

Finally, the example migration from CocoaPods to SPM is a great validation step, but it is a fairly significant change on its own. It might be cleaner to split it into a separate PR so the core plist lookup fix can be reviewed and merged independently.

Would you be open to a narrower version of the patch focused on the findInfoPlist change? Happy to iterate on it with you.

@olekeke999
Copy link
Copy Markdown
Author

olekeke999 commented Jun 5, 2026

@TheoGermain , thank you for detailed response.
will take a look and return with update.

The FlutterFramework dependency added

this is new requirement from Flutter 3.41. - https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-plugin-authors#:~:text=New%20in%20Flutter%203.41!%20Add%20the%20FlutterFramework
without it, there is red warning during app building.

@TheoGermain
Copy link
Copy Markdown
Contributor

Good to know about FlutterFramework, I missed that change in 3.41. Thanks for the pointer. Looking forward to the updated patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants