You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI首次加载时LocationManager日志有值但模态视图无内容问题

问题分析:首次加载模态视图不显示国家名称的原因

首次加载应用时,控制台打印LocationManager的日志Current country code: US,但模态视图显示空文本:Looks like you're in !;手动修改模拟器位置为加拿大后,日志打印Current country code: CA,模态视图能正常显示Looks like you're in Canada!。


参考文件与代码

Countries.json

[
     {
        "display_name": "United States of America",
        "searchable_names": [
            "united states of america",
            "us",
            "usa"
        ],
        "image": "united-states-of-america",
        "id": 204,
        "iso": "US"
    },
    {
        "display_name": "Canada",
        "searchable_names": [
            "Canada",
            "ca"
        ],
        "image": "canada",
        "id": 205,
        "iso": "CA"
    }
]

核心代码

struct ContentView: View {
    @State private var isPresented = false
    @Binding var countries: [Country];
    @State var modalCountry: Country?
    @StateObject var locationManager = LocationManager()

    var body: some View {
        VStack {
            // 视图内容
        }
        .onChange(of: locationManager.countryCode) { country in
            self.isPresented = true                              
         }
        .sheet(isPresented: $isPresented) {
            ModalView(countryModal: self.modalCountry)
        }
    }
}

struct ModalView: View {
    @State var countryModal: Country?
    @Environment(\.presentationMode) var presentationMode
    
    var body: some View {
        VStack {
            Text("Looks like you're in \(countryModal?.display_name ?? "") !")
                .bold()
            Button("Show Me") {}
            Button("Dismiss") {
                presentationMode.wrappedValue.dismiss()
            }
        }
        .padding()
    }
}

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
    let locationManager = CLLocationManager()
    @Published var countryCode: Country?
    
    override init() {
        super.init()
        locationManager.delegate = self
        locationManager.distanceFilter = 500
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let currentLocation = locations.last else { return  }
        let geocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(currentLocation) { (placemarks, error) in
            guard let placemark = placemarks?.first, let countryCode = placemark.isoCountryCode else { return }
            print("Current country code: \(countryCode)")
            self.countryCode = countries.first(where: { $0.iso == countryCode }) ?? nil
        }
    }
}

原因分析

1. modalCountry未与locationManager.countryCode同步

ContentView的onChange监听locationManager.countryCode变化时,仅执行了isPresented = true来弹出模态视图,但没有将最新的countryCode值赋值给modalCountry。首次加载时modalCountry初始值为nil,模态视图接收的参数为空,因此显示空白文本。

2. LocationManager无法访问countries数组,导致首次countryCode赋值失效

LocationManager的didUpdateLocations方法中,直接调用countries.first(where:...),但countries是ContentView的绑定属性,LocationManager并未持有该数组的引用——这会导致编译错误,实际运行中无法找到US对应的Country对象,使得self.countryCode仍为nil。


修复方案

同步modalCountry与locationManager.countryCode

修改ContentView的onChange回调,更新modalCountry的值:

.onChange(of: locationManager.countryCode) { newCountry in
    self.modalCountry = newCountry
    self.isPresented = true
}

给LocationManager传入countries数组

修改LocationManager的初始化逻辑,接收countries参数:

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
    let locationManager = CLLocationManager()
    @Published var countryCode: Country?
    private let countries: [Country]
    
    init(countries: [Country]) {
        self.countries = countries
        super.init()
        // 原有初始化逻辑不变
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // 原有逻辑不变
        self.countryCode = countries.first(where: { $0.iso == countryCode }) ?? nil
    }
}

在ContentView中初始化时传入数组:

@StateObject var locationManager: LocationManager

init(countries: Binding<[Country]>) {
    self._countries = countries
    self._locationManager = StateObject(wrappedValue: LocationManager(countries: countries.wrappedValue))
}

修正ModalView的参数定义

ModalView的countryModal无需用@State,改为普通常量即可:

struct ModalView: View {
    let countryModal: Country?
    @Environment(\.presentationMode) var presentationMode
    
    // 原有视图逻辑不变
}

内容的提问来源于stack exchange,提问作者mrJuei3l

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 08:12:56