核心位置为ObservableObject的SwiftUI崩溃 [英] SwiftUI with Core Location as ObservableObject crashes

查看:62
本文介绍了核心位置为ObservableObject的SwiftUI崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Core Location获取CLRegionState来更新SwiftUI应用程序中的元素。我正在使用XCode 11 beta 6,并且在我的设备上安装了iOS 13 beta 7。

I am trying to use Core Location to get the CLRegionState to update elements in a SwiftUI app. I am using XCode 11 beta 6 and have iOS 13 beta 7 on my device.

我可以看到两个问题:


  1. 应用程序崩溃并显示错误线程1:第147行出现EXC_BAD_ACCESS(... ScrollView {...)

  1. The app crashes and the error Thread 1: EXC_BAD_ACCESS appears on line 147 (...ScrollView {... )

CLRegionState永远不会被调用或不会更新。

The CLRegionState is never called or does not update.

我基于此Paul Hudson关于SwiftUI信标检测器的教程(我也无法使它工作)的一部分,并对其进行了修改以使用CLRegionState而不是信标接近度。

I am basing this off of Paul Hudson's tutorial on SwiftUI Beacon Detector (which I have not been able to make work either), and modifying it to use CLRegionState instead of beacon proximity .

这里是代码:

import SwiftUI
import CoreLocation
import Combine

class MYLocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {


    var locationManager: CLLocationManager?
    var willChange = PassthroughSubject<Void, Never>()
    var lastRegionState = CLRegionState.unknown


    override init() {
        super.init()
        locationManager = CLLocationManager()
        locationManager?.delegate = self
        locationManager?.requestWhenInUseAuthorization()
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        checkLocationAuthorization()
    }

    func update(state: CLRegionState) {
        lastRegionState = state
        willChange.send(())
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
        print("Your location is \(location)")
        update(state: .unknown)
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
    }

    func startScanning() {

        // temporary coordinates
        var workCoordinates: CLLocationCoordinate2D {
            return CLLocationCoordinate2D(
                latitude: 43.486525,
                longitude: -11.912542)
        }

        var homeCoordinates = CLLocationCoordinate2D(
            latitude: 43.499541,
            longitude: -11.875079)

        let workRegion: CLCircularRegion = CLCircularRegion(center: workCoordinates, radius: 100, identifier: "Work")

        let homeRegion: CLCircularRegion = CLCircularRegion(center: homeCoordinates, radius: 100, identifier: "Home")

        locationManager!.startMonitoring(for: workRegion)
        locationManager!.startMonitoring(for: homeRegion)
        locationManager!.requestState(for: workRegion)
        locationManager!.requestState(for: homeRegion)
    }

    func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
        switch state {
        case .inside:
            switch region.identifier {
            case "Work":
                print("You are at work")
            case "Home":
                print("You are at home")
            default:
                print("unknown")
            }
        default:
            break
        }
    }

    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {

        switch region.identifier {
        case "Work":
            print("Work**********")
        //self.taskTypeSegCtrl.selectedSegmentIndex = 0
        case "Home":
            print("Home*********8")
        //self.taskTypeSegCtrl.selectedSegmentIndex = 1
        default:
            break
        }
    }

    func checkLocationAuthorization() {
        switch CLLocationManager.authorizationStatus() {
        case .authorizedWhenInUse:
            startScanning()
            break
        case .authorizedAlways:
            startScanning()
            break
        case .denied:
            // show an alert instructing them howto turn on permissions
            break
        case .notDetermined:

            print("Location authorization is not determined.")
            locationManager!.requestAlwaysAuthorization()
            break
        case .restricted:
            break
        @unknown default:
            fatalError()
        }
    }
}


struct ContentView: View {
    @Environment(\.managedObjectContext) var managedObjectContext

    @FetchRequest(entity: Task.entity(),
                  sortDescriptors: [NSSortDescriptor(
                    keyPath: \Task.name, ascending: true)])
    var tasks: FetchedResults<Task>

    var locationManager = CLLocationManager()

    @ObservedObject var location: MYLocationManager = MYLocationManager()

    @State private var taskName = ""
    @State private var taskType = 0
    @State private var selectedTask = ""
    @State private var numberOfTaps = 0
    @State private var regionState = CLRegionState.unknown

    var body: some View {

        ScrollView {
            VStack {
                TextField("Enter a task name", text: $taskName)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                Picker(selection: $taskType, label: Text("Task type")) {
                    Text("Work").tag(1)
                    Text("Home").tag(2)
                }.pickerStyle(SegmentedPickerStyle())

                Text(selectedTask)

                Button(action: {
                    let task = Task(context: self.managedObjectContext)
                    task.name = self.taskName
                    task.type = Int16(self.taskType)
                    do {
                        try self.managedObjectContext.save()
                    } catch {
                        // handle the Core Data error
                    }
                    self.taskName = ""
                }) {
                    Text("Save Task")
                }.padding()

                Button(action: {
                    if self.numberOfTaps < self.tasks.count {
                        let task = self.tasks[self.numberOfTaps].name
                        self.selectedTask = task ?? "No task..."
                        self.numberOfTaps = self.numberOfTaps + 1
                    } else {
                        self.selectedTask = "No more tasks!  Have a wonderful day."
                    }
                }) {
                    Text("Next Task")
                }

                List {
                    ForEach(tasks, id: \.self) {
                        task in
                        VStack(alignment: .leading, spacing: 6) {
                            Text(task.name ?? "Unknown")
                                .font(.headline)
                            Text("Task type \(task.type)")
                                .font(.caption)
                        }
                    }.onDelete(perform: removeTask)

                }
            }   .frame(width: 300, height: 400, alignment: .top)
                .padding()
                .border(Color.black)

            if regionState == .inside {
                Text("inside")
            } else if regionState == .outside {
                Text("outside")
            } else {
                Text("unknown")
            }


            Spacer()
        }
    }


    func removeTask(at offsets: IndexSet) {
        for index in offsets {
            let task = tasks[index]
            managedObjectContext.delete(task)
            do {
                try managedObjectContext.save()
            } catch {
                // handle the Core Data error
            }
        }
    }

    func showTask(at offsets: IndexSet) {
        for index in offsets {
            let task = tasks[index]
            selectedTask = task.name ?? "No task..."
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

实施Fabian所做的更改后,以下是控制台日志的内容:

After implementing the changes made by Fabian, here is the content of the console log:

已授予:true
2019-08-22 14 :30:07.051062-0600 AppName [4452:2089841] locationManager(_管理器:CLLocationManager,didChangeAuthorization状态:CLAuthorizationStatus)
2019-08-22 14:30:07.052803-0600 New1Thing [4452:2089841] startScanning
2019-08-22 14:30:07.054319-0600 New1Thing [4452:2089841]当前位置:< + .49945068,-* .87504490> +/- 65.00m(速度-1.00 mps / course -1.00)@ 18/22/19,2:30:07 PM ****白天时间

Granted: true 2019-08-22 14:30:07.051062-0600 AppName[4452:2089841] locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) 2019-08-22 14:30:07.052803-0600 New1Thing[4452:2089841] startScanning 2019-08-22 14:30:07.054319-0600 New1Thing[4452:2089841] Current location: <+.49945068,-*.87504490> +/- 65.00m (speed -1.00 mps / course -1.00) @ 8/22/19, 2:30:07 PM **** Daylight Time

推荐答案

第一关闭,我要感谢Fabian和graycampbell的帮助。

First off I want to thank Fabian and graycampbell for their help.

其次,据我所知,@ ObservableObject仍然有效在使用XCode 11 beta 6的iOS 13 beta 8中无法正常工作。

Secondly, as for as I can tell @ObservableObject still does not work in iOS 13 beta 8 using XCode 11 beta 6.

这对我有用:
1.我更改了

Here is what worked for me: 1. I changed

@ObservedObject var location: MYLocationManager = MYLocationManager()

至:

@EnvironmentObject var location: MYLocationManager

2。在SceneDelegate中,我添加了:

2. In the SceneDelegate I added:

let myLocationManager = MYLocationManager()

and:

 window.rootViewController = UIHostingController(rootView: CoreLocationView_NeedsEnv()
            .environmentObject(myLocationManager)

不再崩溃!

PS我正在使用Fabian的更新代码。再次感谢!

P.S. I am using Fabian's updated code. Thanks again!

这篇关于核心位置为ObservableObject的SwiftUI崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆