我正在做一个项目,收集实时位置数据并将其存储在数据库中(使用谷歌firebase).我对Swift比较陌生,但已经编写了大约2年的代码.我创建了一个基本的主页用户界面和 map 视图用户界面,使用导航链接在页面之间移动.MapViewModel类是用于从用户收集位置数据的类.我试图用.onAppear调用MapViewModel类的一个方法.虽然当我运行该程序时,该函数没有被调用,"inside"也没有打印在终端上.我是否遗漏了一些关于onAppear和导航链接如何工作的信息?请告诉我当视图切换到MapView时调用函数的最佳解决方案.

import SwiftUI
import MapKit

struct HomePage: View {
    @State private var viewModel = MapViewModel()
    var body: some View {
        NavigationView {
            ZStack {
                LinearGradient(
                    gradient: Gradient(colors: [.blue, Color(red:0.18, green: 0.79, blue: 0.91, opacity: 1.0)]),
                    startPoint: .topLeading,
                    endPoint: .bottomTrailing)
                .edgesIgnoringSafeArea(.all)
                NavigationLink {
                    MapView()
                }
                label: {
                    ZStack {
                        Circle()
                            .trim(from: 0.5)
                            .frame(width: 450, height: 450)
                            .foregroundColor(Color(red: 1.0, green: 0.89, blue: 0.36, opacity: 1.0))
                        
                        Text("Navigate")
                            .foregroundColor(.white)
                            .font(.system(size:32, weight: .bold, design: .default))
                            .padding(.bottom, 280)
                    }
                    .position(x: 195, y: 900)
                    .ignoresSafeArea(.all)
                }
            }
        }
    }
}

struct MapView: View {
    @State private var viewModel = MapViewModel()
    var body: some View {
        Map(coordinateRegion: $viewModel.region, showsUserLocation: true)
            .ignoresSafeArea()
            .accentColor(Color(.systemPink))
            .onAppear {
                print("inside")
                viewModel.checkIfLocationServiceIsEnabled()
            }
    }
}

final class MapViewModel : NSObject, ObservableObject, CLLocationManagerDelegate {
    
    @Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 33, longitude: -120), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
     
    var locationManager: CLLocationManager?
    
    func checkIfLocationServiceIsEnabled() {
        if CLLocationManager.locationServicesEnabled() {
            locationManager = CLLocationManager()
            locationManager!.startUpdatingLocation()
            locationManager!.delegate = self
        }
        else {
            print("Print error message")
        }
    }
    
    func checkLocationAuthorization() {
        guard let locationManager = locationManager else { return }
        switch locationManager.authorizationStatus {
        case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
        case .restricted:
            print("Location restricted")
        case .denied:
            print("You have denied location permission, go to settings")
        case .authorizedAlways, .authorizedWhenInUse:
            print("Inside")
            if locationManager.location?.coordinate != nil {
                region = MKCoordinateRegion(center: locationManager.location!.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
            }
            else {
                print("Location not found")
            }
            
        @unknown default:
            break
        }
    }
    
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        checkLocationAuthorization()
    }
    
    func locationManager(_ manager: CLLocationManager,  didUpdateLocations locations: [CLLocation]) {
        let lastLocation = locations.last!
        print(lastLocation)
                   
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        HomePage()
    }
}

推荐答案

HomePage视图中使用@StateObject var viewModel = MapViewModel().在NavigationView中加.environmentObject(viewModel),在MapView中加@EnvironmentObject var viewModel: MapViewModel.对我来说很有用.

这是我用于测试的代码,对我来说很有用.

import Foundation
import SwiftUI
import MapKit

struct ContentView: View {
    var body: some View {
        HomePage()
    }
}

struct HomePage: View {
    @StateObject var viewModel = MapViewModel() // <-- here
    
    var body: some View {
        NavigationView {
            ZStack {
                LinearGradient(
                    gradient: Gradient(colors: [.blue, Color(red:0.18, green: 0.79, blue: 0.91, opacity: 1.0)]),
                    startPoint: .topLeading,
                    endPoint: .bottomTrailing)
                .edgesIgnoringSafeArea(.all)
                NavigationLink {
                    MapView()
                }
                label: {
                    ZStack {
                        Circle()
                            .trim(from: 0.5)
                            .frame(width: 450, height: 450)
                            .foregroundColor(Color(red: 1.0, green: 0.89, blue: 0.36, opacity: 1.0))
                        
                        Text("Navigate")
                            .foregroundColor(.white)
                            .font(.system(size:32, weight: .bold, design: .default))
                            .padding(.bottom, 280)
                    }
                    .position(x: 195, y: 900)
                    .ignoresSafeArea(.all)
                }
            }
        }.environmentObject(viewModel) // <-- here
    }
}

struct MapView: View {
    @EnvironmentObject var viewModel: MapViewModel // <-- here
    
    var body: some View {
            Map(coordinateRegion: $viewModel.region, showsUserLocation: true)
                .ignoresSafeArea()
                .accentColor(Color(.systemPink))
        .onAppear {
            print("\n----> in onAppear \n")
            viewModel.checkIfLocationServiceIsEnabled()
        }
    }
}

final class MapViewModel : NSObject, ObservableObject, CLLocationManagerDelegate {
    
    @Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 33, longitude: -120), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
    
    func checkIfLocationServiceIsEnabled() {
        print("\n----> in checkIfLocationServiceIsEnabled")
    }
}

如果这不适用于您的系统,请try 以下操作:

struct MapView: View {
    @EnvironmentObject var viewModel: MapViewModel
    
    var body: some View {
        VStack {  // <-- here
            Map(coordinateRegion: $viewModel.region, showsUserLocation: true)
                .ignoresSafeArea()
                .accentColor(Color(.systemPink))
        }
        .onAppear {
            print("\n----> in onAppear \n")
            viewModel.checkIfLocationServiceIsEnabled()
        }
    }
}

Ios相关问答推荐

SwiftUI文本编辑器内部滚动填充,无需文本裁剪

AlGolia InstantSearch Swift Package Manager引发编译错误

清除/删除 NavigationController 中的多个 ViewController

更改订单时如何保存商品的位置?

Flutter动画放大图

核心媒体基础知识,了解 CMSampleBuffer、CMBlockBuffer 和 CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer

iOS应用程序崩溃,必需条件为false:isformatsamplerateandchannelcountvalid(format)

如何擦除 Swift 中的 Core Graphics Context 绘图?

UIView 倒置旋转时的zoom 问题

SwiftUI 中的描边图像边框

FileHandle 不会在 iOS 中释放内存

iOS 10 错误:UICollectionView 接收到具有不存在索引路径的单元格的布局属性

interfaceOrientation在 iOS 8 中已弃用,如何更改此方法 Objective C

针对 Xcode 中的 iPad 选项

UIButton 事件.有什么不同?

如何在 iOS 中判断暗模式?

如何识别导航堆栈中的前一个视图控制器

Xcode 5 和 iOS 7:架构和有效架构

iPhone UITableView.如何开启音乐 App 之类的单字母字母列表?

Xcode 6 进程启动失败:try 启动应用程序超时