iOS技术问询:如何通过代码获取用户所在的App Store地区(非Locale方式)
获取合规的App Store用户地区方案
我之前刚好处理过类似的需求,给你分享两个Apple官方认可的实现方式,完全符合合规要求,比单纯用Locale更精准可靠:
方案一:iOS 13+ 直接用SKPaymentQueue的storefront属性(推荐)
从iOS 13开始,Apple在StoreKit里提供了SKPaymentQueue.default().storefront属性,它直接返回用户当前关联的App Store地区信息——如果用户登录了App Store账户,返回的是账户绑定的地区;未登录则返回设备IP对应的地区,这正是我们需要的精准结果。
代码示例:
import StoreKit func fetchAppStoreCountryCode(completion: @escaping (String?) -> Void) { if #available(iOS 13.0, *) { let countryCode = SKPaymentQueue.default().storefront?.countryCode completion(countryCode) } else { // 调用iOS 13以下的兼容方案 fetchLegacyAppStoreCountryCode(completion: completion) } }
方案二:iOS 13以下兼容方案 - SKStoreProductRequest
对于iOS 13及更早版本,我们可以通过请求当前App的产品信息来获取storeFrontId,这个ID里包含了地区代码(格式类似143441-GB,拆分后GB就是国家代码)。
代码示例:
import StoreKit func fetchLegacyAppStoreCountryCode(completion: @escaping (String?) -> Void) { guard let appBundleId = Bundle.main.bundleIdentifier else { completion(nil) return } let productRequest = SKStoreProductRequest(productIdentifier: appBundleId) productRequest.delegate = LegacyStoreFrontDelegate(completion: completion) productRequest.start() } // 单独的Delegate类,避免污染ViewController class LegacyStoreFrontDelegate: NSObject, SKStoreProductRequestDelegate { private let completion: (String?) -> Void init(completion: @escaping (String?) -> Void) { self.completion = completion super.init() } func productRequest(_ request: SKStoreProductRequest, didReceive response: SKProductsResponse) { defer { request.finish() } guard let storeFrontId = response.storeFrontId else { completion(nil) return } let components = storeFrontId.components(separatedBy: "-") guard components.count == 2 else { completion(nil) return } completion(components[1]) } func request(_ request: SKRequest, didFailWithError error: Error) { defer { request.finish() } print("获取App Store地区失败:\(error.localizedDescription)") completion(nil) } }
后续处理
拿到国家代码后,你可以把它映射成对应的地区分组:
- 美国:
US - 欧洲地区:
GB(英国)、FR(法国)、ES(西班牙)等
比如:
func isEuropeanUser(countryCode: String?) -> Bool { let europeanCountryCodes = ["GB", "FR", "ES", "DE", "IT"] // 按需扩展欧洲国家代码 return countryCode.flatMap { europeanCountryCodes.contains($0) } ?? false } func isUSUser(countryCode: String?) -> Bool { return countryCode == "US" }
注意事项
- 这两种方法都不需要额外的权限,只需导入
StoreKit框架即可。 - 相比
Locale.countryCode,这些方法直接从App Store服务获取数据,不受用户手动修改系统语言/区域设置的影响,更符合合规和业务需求。
内容的提问来源于stack exchange,提问作者Melanie Journe
相关产品推荐
相关产品推荐

