gpt4 book ai didi

ios - 位置管理器委托(delegate)调用更新 TableView 问题

转载 作者:行者123 更新时间:2023-11-29 11:40:32 25 4
gpt4 key购买 nike

我有一个 tableView,其中填充了一个 fetchedResultsController。一切正常。就目前而言,tableView 根据需要从 managedObjectContext 加载数据。问题是它的数据太多了,所以我创建了一个 CLLocationManager 类,它带有一个协议(protocol),当 tableView 有一个位置并且 tableView Controller 将谓词添加到fetchedResultsController 以减少可能性的数量。

我遇到的问题是关于应用程序的初始加载。似乎在 tableView 完成加载之前调用了 LocationManager 委托(delegate)。

我在首次启动时一直收到此错误,但在后续启动时没有:

[error] error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (0), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null)

CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (0), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null)

import CoreLocation

protocol LocationManagerDelegate: class {
func updateTableView()
}

class LocationManager: NSObject {
static let sharedInstance = LocationManager()
public var currentLocation: CLLocation? {
get {
return locationManager.location
}
}
private var locationManager = CLLocationManager()
private override init() {
super.init()
locationManager.delegate = self
self.getCurrentLocation()
}
public weak var delegate: LocationManagerDelegate?

public func updateLocation() {
getCurrentLocation()
}

private func getCurrentLocation() {
// Also tried without the DispatchQueue
DispatchQueue.global(qos: .userInitiated).async {
// DispatchQueue.global(qos: .userInitiated).sync {
self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
}
}
}

extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
delegate?.updateTableView()
// still crashes
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.delegate?.updateTableView()
}
}
}

我一直在 AppDelegate.swift 中启动 locationManager 以加快加载时间。

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
LocationManager.sharedInstance.updateLocation()
return true
}

认为这是罪魁祸首,我将它移动到 viewDidLoad 的末尾,但没有成功。该应用程序在初始启动后加载正常并且 locationManager 的委托(delegate),但我无法解决初始启动时的错误。

这是我的 NSFetchedResultsControllerDelegate 实现:

// MARK: - NSFetchedResultsControllerDelegate methods
extension MyViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch (type) {
case .insert:
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .automatic)
}
break;
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .automatic)
}
break;
case .update:
if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) {
configureCell(cell, at: indexPath)
}
break;
case .move:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .automatic)
}

if let newIndexPath = newIndexPath {
tableView.insertRows(at: [newIndexPath], with: .automatic)
}
break;
}
}

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
print("controller didChange sectionInfo")
}
}

extension MyViewController: LocationManagerDelegate {
func updateTableView() {
filterBasedOnDistance(miles: Double(slider.value))
}
}

以下是 updateTableView() 调用的方法:

  private func degreeRangeInMiles(degrees: Double, miles: Double) -> Range<Double> {
let metersPerDegree: Double = 111_000
let degreesInMeters = degrees * metersPerDegree

let metersPerMileDouble = 1_609.344
let milesDifferential = miles * metersPerMileDouble

let upperBound = (degreesInMeters + milesDifferential) / metersPerDegree
let lowerBound = (degreesInMeters - milesDifferential) / metersPerDegree

return Range(lowerBound..<upperBound)
}

func filterBasedOnDistance(miles: Double) {
guard locationManager.currentLocation != nil else { return }

let latitude = locationManager.currentLocation?.coordinate.latitude
let longitude = locationManager.currentLocation?.coordinate.longitude

let latitudeRange = degreeRangeInMiles(degrees: latitude!, miles: miles)
let longitudeRange = degreeRangeInMiles(degrees: longitude!, miles: miles)

let distancePredicate = NSPredicate(format: "latitude BETWEEN { \(latitudeRange.lowerBound),\(latitudeRange.upperBound) } AND longitude BETWEEN {\(longitudeRange.lowerBound),\(longitudeRange.upperBound)}")

fetchedResultsController.fetchRequest.predicate = distancePredicate

do {
try fetchedResultsController.performFetch()
} catch {
print(error.localizedDescription)
}
tableView.reloadData()
}

我想弄清楚我的错误在哪里,我该如何解决?感谢阅读!

更新

我尝试在我的 LocationManager 类上添加一个面向公众的 get-only 属性以确定设备的授权状态:

  public var locationServicesAuthorized: Bool {
get {
return CLLocationManager.locationServicesEnabled()
}
}

我更新了我的委托(delegate)方法调用如下:

extension MyViewController: LocationManagerDelegate {
func updateTableView() {
guard locationManager.locationServicesAuthorized else { return }
filterBasedOnDistance(miles: Double(slider.value))
}
}

同样的结果。我得到的错误是部分数量无效,即使我已经实现了 beginUpdatesendUpdates。 🙄🔫

最佳答案

pbasdf的建议下,我实现了didChange sectionInfo NSFetchedResultsController 委托(delegate)方法。 Apple's boilerplate on their site在 Objective-C 中,但这里是翻译后的 Swift 版本:

  func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {

switch type {
case .insert:
tableView.insertSections([sectionIndex], with: .fade)
break
case .delete:
tableView.deleteSections([sectionIndex], with: .fade)
default:
break
}
}

关于ios - 位置管理器委托(delegate)调用更新 TableView 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46893616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com