【问题标题】:EXC_BAD_ACCESS while passing array to new ViewController将数组传递给新的 ViewController 时的 EXC_BAD_ACCESS
【发布时间】:2015-11-19 11:43:52
【问题描述】:

我正在从 web 服务(汽车数据)加载一些 XML,创建一些汽车对象并希望在 TableViewController 中显示它们。

当用户选择了开始和目标位置后,我对 web 服务进行异步调用,显示活动指示器,一旦加载数据,我就会转到新视图。所以我有这样的事情:

 class NewReservationViewController : UIViewController {
       @IBAction func searchCarsClicked(sender: UIBarButtonItem) {

            //show load cars activity indicator
            loadingCarsActivityIndicator.startAnimating()

            //load available cars from webservice asyncronously
           DataManager.getAvailableCars([...parameter list...], carsLoadedCallback: carsLoaded)


        }

        func carsLoaded(loadedCars: [Car]) {
            //dismiss the waiting widget
            //trigger the segue and advance to the next screen

            loadingCarsActivityIndicator.stopAnimating()
            print("stopped cars loading activity indicator")
            print("cars loaded callback called")
            print("loaded \(loadedCars.count) distinct cars")

            self.cars = loadedCars
            performSegueWithIdentifier("showAvailableCars", sender: self)

        }


    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == "showAvailableCars" {

            let carTableViewController = segue.destinationViewController as! CarTableViewController
            carTableViewController.cars = self.cars
            presentViewController(carTableViewController, animated: false, completion: nil)

        }
    }
}






class DataManager {


   class func getAvailableCars([...parameter list...], carsLoadedCallback: ([Car]) -> Void){
       Webservice.getAvailability([...parameter list...], completionHandler: { (data, response, error) in


           //parse xml
           //in the end I get an Array of Car objects


           var cars: [Car] = ...

           carsLoadedCallback(cars)

        })}
   }
}

当我使用在 CarTableViewController 类中创建的一些 DummyData 填充 TableView 时,它工作正常。但是,当我尝试将汽车数组传递给我的 TableViewController 时,我得到一个 EXC_BAD_ACCESS 代码 = 2 异常。据我所知,这是某种内存异常,通常是由损坏的指针引起的。所以我猜我在我调用的静态方法中的静态 DataManager 类中创建的汽车数组被破坏了。但是我不确定这一点,因为自动引用计数应该避免这种情况。

表视图甚至会显示数据,但随后会立即因 EXC_BAD_ACCESS 异常而崩溃。我尝试在 XCode 的断点选项卡中设置一个通用断点,但是我没有收到关于应用程序崩溃原因的合理错误消息。

您对为什么会发生这种情况有任何想法吗?如何获得更好的错误信息? 提前感谢您的帮助。

【问题讨论】:

    标签: ios objective-c swift swift2 exc-bad-access


    【解决方案1】:

    首先检查这个函数:

    func carsLoaded(loadedCars: [Car])
    

    它作为回调返回 - 它正在运行什么线程?主要还是背景? 你应该调用主线程

    dispatch_async(dispatch_get_main_queue(), {
      performSegueWithIdentifier("showAvailableCars", sender: self)
    })
    

    如果没有帮助 - 提供在调试器中中断的行,以便我可以提供帮助并查看更多信息。

    UPD:没注意到,你为什么要手动呈现?

    presentViewController(carTableViewController, animated: false, completion: nil)
    

    您的 segue 会自动显示视图控制器,您可以在情节提要中更改其样式(模式、推送)。

    【讨论】:

    • 不幸的是,当我这样做时,应用程序仍然崩溃。我的问题是我没有收到合理的错误消息。我只看到 AppDelegate 和带有 EXC_BAD_ACCESS 的红色错误消息。所以我看不到它在调试器中的中断位置。
    • 为这些行设置断点:loadingCarsActivityIndicator.stopAnimating()self.cars = loadedCarsperformSegueWithIdentifier("showAvailableCars", sender: self)override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)。它停在哪里?哪里没有?
    • 它在每个断点处停止。然而,我注意到了一些奇怪的事情。如果我尝试使用 dispatch_async 停止主线程上的活动指示器,即使在语句执行后它仍然会继续。
    • 这是什么? `presentViewController(carTableViewController, animated: false, completion: nil)` 删除这一行。您的 segue 显示了一个视图控制器,然后您再手动执行一次。
    【解决方案2】:

    我可以看到两个潜在的问题。首先是你从一个可能不在主线程上的方法触发你的 segue,你需要确保这是在主线程上完成的。另一个问题是,在你准备 segue 时,你打开新的 ViewController 而不检查它,所以试试这个:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
        if segue.identifier == "showAvailableCars" {
    
            if let carTableViewController = segue.destinationViewController as? CarTableViewController {
                carTableViewController.cars = self.cars
                presentViewController(carTableViewController, animated: false, completion: nil)
            }
        }
    }
    

    【讨论】:

    • 是的,在这种情况下我绝对应该使用 if let 。该应用程序仍然崩溃。但是,如果我在我的主线程上进行 Webservice 调用,应用程序不会冻结吗?那么这将是一个同步调用。您如何看待我的一般方法?有没有更干净且不易出错的解决方案,我不会遇到线程问题?
    • 不需要在主线程做API调用,需要在主线程调用performSegue
    【解决方案3】:

    正如您所说,表格视图显示数据然后立即崩溃,我认为问题出在您的 CarTableViewController 中。您可以检查的一件事是,当您的单元格被渲染时,如果您尝试从 Car 对象访问一些为空的信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-04
      • 1970-01-01
      • 2018-03-21
      • 1970-01-01
      • 2015-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多