Problem:
I’m encountering a Swift compiler error when trying to run a Flutter project on an iOS device (or simulator) the project depends on the PhoneNumberKit library in my Flutter iOS project.
Statement:
I am using phone_form_field to validate phone numbers in my Flutter project. However, when I try to build the project with ios, I get the following Swift compiler errors: (Android works just fine)
• Error: Module 'PhoneNumberKit' has no member named 'defaultRegionCode'
• Error: Cannot call value of non-function type 'module<PhoneNumberKit>'
• Error: Cannot infer contextual base in reference to member 'international'
Disclaimer: the project used to work fine , don’t have a clue why it stopped compiling on ios.
The errors seem related to the project trying to use PhoneNumberKit in the Swift class. Here’s a simplified version of the Swift code I am using:
import Foundation
import PhoneNumberKit
import Checkout
class PhoneNumberValidator: Validator {
var countryCode: String = PhoneNumberKit.defaultRegionCode()
private let validator = PhoneValidator()
private let phoneKit = PhoneNumberKit()
private let validCharacterSet: CharacterSet = {
var validInputs = "-+() "
(0...9).forEach { validInputs.append("($0)") }
return CharacterSet(charactersIn: validInputs)
}()
init() {}
func shouldAccept(text: String) -> Bool {
CharacterSet(charactersIn: text).isSubset(of: validCharacterSet) &&
text.count < Checkout.Constants.Phone.phoneMaxLength
}
func isValid(text: String) -> Bool {
do {
let formattedNumber = try phoneKit.parse(text,
withRegion: countryCode,
ignoreType: true)
let phone = Phone(number: String(formattedNumber.numberString),
country: Country(iso3166Alpha2: formattedNumber.regionID ?? ""))
return validator.validate(phone) == .success
} catch {
return false
}
}
func formatForDisplay(text: String) -> String {
do {
let formattedNumber = try phoneKit.parse(text,
withRegion: countryCode)
return phoneKit.format(formattedNumber, toType: .international)
} catch {
return text
}
}
}
// MARK: Singleton behaviour
extension PhoneNumberValidator {
static var shared: PhoneNumberValidator {
if let instance {
return instance
}
let newValidator = PhoneNumberValidator()
instance = newValidator
return newValidator
}
static private var instance: PhoneNumberValidator?
/// Will deallocate the singleton source
static func removeSingleton() {
Self.instance = nil
}
}
Here’s an image of the errors inside Xcode
Here’s my current depnendecies in pubpspec.yaml
name: app
description: "DESCRIPTION"
publish_to: 'none'
version: 7.7.9+7036
environment:
sdk: '>=3.4.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
app_tracking_transparency: ^2.0.6
awesome_notifications: ^0.9.3+1
badges: ^3.1.2
cupertino_icons: ^1.0.8
cached_network_image: ^3.4.0
carousel_slider: ^5.0.0
crypto: ^3.0.5
device_info_plus: ^10.1.2
dio: ^5.6.0
flutter_easyloading: ^3.0.5
font_awesome_flutter: ^10.7.0
firebase_auth: ^5.1.4
firebase_analytics: ^11.2.1
flutter_checkout_payment:
git:
url: https://github.com/lucasuracosta/flutter_checkout_payment.git
ref: master # branch name
firebase_core: ^3.3.0
flutter_credit_card: ^4.0.1
firebase_dynamic_links: ^6.0.4
#TODO remmber to check tabby version before updating this pacakge to newer versions
flutter_inappwebview: ^5.8.0 #downgraded because of tabby package constraints ^1.5.0
flutter_local_notifications: ^17.2.2
firebase_messaging: ^15.0.4
flutter_phoenix: ^1.1.1
flutter_rating_bar: ^4.0.1
flutter_secure_storage: ^9.2.2
flutter_widget_from_html: ^0.15.1
pay: ^2.0.0
get: ^4.6.6
get_storage: ^2.1.1
google_sign_in: ^6.2.1
http: ^1.2.2
path_provider: ^2.1.4
permission_handler: ^11.3.1
persistent_bottom_nav_bar_v2: ^5.3.0
retry: ^3.1.2
selection_menu: ^2.0.2
shared_preferences: ^2.3.2
shimmer: ^3.0.0
sign_in_with_apple: ^6.1.1
url_launcher: ^6.3.0
webview_flutter: ^4.8.0
icons_launcher: ^3.0.0-beta.3
tabby_flutter_inapp_sdk: ^1.5.0
phone_form_field: ^9.2.5
sentry_flutter: ^8.7.0
in_app_review: ^2.0.9
is_first_run_plus: ^1.1.0
jiffy: ^6.3.1
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^4.0.0
sentry_dart_plugin: ^2.1.0
I suspected the issue might have came from Phone form field package but i tried it on a new project and the project ran without any errors.
Tried Solutions:
1. Updated All Dependencies: I ensured all dependencies, including PhoneNumberKit, Checkout, and others, are updated to their latest versions.
2. Reinstalled Pods: Ran pod deintegrate, followed by pod install --repo-update to ensure all CocoaPods dependencies are installed correctly.
3. Verified Project Configuration: Checked the Podfile, Build Settings, and other configurations to ensure they are set up correctly for the latest iOS and Xcode versions.
Additional Information:
• Development Environment:
• Xcode Version: 15.4
• macOS Version: Sonoma 14.6.1
• Flutter Version: 3.24.1
• PhoneNumberKit Version: 4.0.0 (Havne't changed it at all)
• What I’m Avoiding:
• I prefer not to modify internal code or downgrade to older versions of dependencies unless absolutely necessary.
Question:
How can I resolve the Swift compiler errors when using PhoneNumberKit in my Flutter iOS project? Are there any known issues or workarounds for using PhoneNumberKit with the latest versions of iOS and Xcode? Any help would be appreciated!
2
Answers
I just found the solution posted three hours ago before posting my question
The solution was posted on this Question answered by user haroon-abutabar
For reference, here's the answer:
Podfile.lock
in Podfile:
and then run:
Would welcome any change to the answer to elaborate more on why this package caused the issue.
I am here just to add a little context of how it happened.
First, solution with pinning version in
Podfile
is right, in my opinion. Maybe it’s worth to pin it to~> 3.8.0
or something cause every version before4.0.0
works.Second, why version
4.0.0
breaks the build? The reason is this PR landed in4.0.0
. In this PR,PhoneNumberKit
renamed toPhoneNumberUtility
to avoid "shadowing" and corresponding warnings. Must say that is it right thing to do and it will happens sooner or later in any case.Essentially, client-code should update usages of this framework and all will be good.
Third, problem here is that error is not in your code, but in iOS-side of
flutter_checkout_payment
package. It uses Frames framework, which is part ofCheckout.com
SDK. And thisFrames
framework depends onPhoneNumberKit
andFrames
is main consumer ofPhoneNumberKit
.Problem in
Frames
configuration is here: dependency onPhoneNumberKit
is not version-constrained.PhoneNumberKit
updates and still satisfies Frame’s dependency because there are no constraints. But API changed and code can not use new4.0.0
versionFinally, I again think that pinning version in
Podfile
is OK. But, best way to fix it will be to reach out toCheckout.com
somehow and ask to updateFrames