重新打开后应用程序崩溃

App crashes after reopening

基本上每次我关闭并重新打开应用程序时,当我打开“历史记录”选项卡时它都会崩溃。我很确定这是因为我使用 NSUserDefaults 的方式。谁能指导我完成?

我注意到有时它会在重新打开后打开“历史记录”选项卡,但如果我向 Nsuserdefaults 添加一个新条目,它会崩溃,在我重新打开它后它会正常工作,并会显示以前的条目,否则它会删除所有内容并仅保留新条目。

    //
    //  SecondViewController.swift
    //  Angelina
    //
    //  Created by Artiom Sobol on 1/3/16.
    //  Copyright © 2016 Artiom Sobol. All rights reserved.
    //

    import UIKit

    class History: UIViewController, UITableViewDataSource, UITableViewDelegate
    {
        // test variable
        var test: MyHistory!
        // array to store unarchived history
        var newHistory = [MyHistory]()

        //outlet for tableview

        let defaults = NSUserDefaults.standardUserDefaults()

        @IBOutlet var tableView: UITableView!

        override func viewDidLoad()
        {

            //change the background
            self.view.backgroundColor = UIColor(patternImage: UIImage(named: "newBackground.jpg")!)
            super.viewDidLoad()


            if let savedPeople = defaults.objectForKey("MyHistory") as? NSData {
                newHistory = NSKeyedUnarchiver.unarchiveObjectWithData(savedPeople) as! [MyHistory]
            }
            tableView.delegate = self
            tableView.dataSource = self
        }

        override func viewDidAppear(animated: Bool) {
            super.viewDidAppear(animated)
            tableView.reloadData()
        }


        func tableView(tableView: UITableView,numberOfRowsInSection section: Int) -> Int
        {
            return self.newHistory.count
        }

        func numberOfSectionsInTableView(tableView: UITableView) -> Int
        {
            return 1
        }

        func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
        {

            let cell = tableView.dequeueReusableCellWithIdentifier("historyCell", forIndexPath: indexPath) as! historyCell
            let person = newHistory[indexPath.item]
          //  let defaults2 = NSUserDefaults.standardUserDefaults()

            print("This is count", newHistory.count)

          //  if let savedPeople = defaults.objectForKey("MyHistory") as? NSData {
        //        newHistory = //NSKeyedUnarchiver.unarchiveObjectWithData(savedPeople) as! [MyHistory]
//            }



           // cell.durationLabel.text = String(person.durationNumber)
            let (hour,minutes,seconds) = secondsToHoursMinutesSeconds(person.durationNumber)

            if(seconds < 10 && minutes < 10)
            {
                cell.durationLabel.text = "0\(hour):0\(minutes):0\(seconds)"
            }
            else if(seconds > 9 && minutes < 10)
            {
                cell.durationLabel.text = "0\(hour):0\(minutes):\(seconds)"
            }
            else if(seconds > 9 && minutes > 9)
            {
                cell.durationLabel.text = "0\(hour):\(minutes):\(seconds)"
            }
            else if(seconds < 10 && minutes > 9)
            {
                cell.durationLabel.text = "0\(hour):\(minutes):0\(seconds)"
            }


            cell.kicksLabel.text = String(person.kicksNumber)

            return cell
        }


        func secondsToHoursMinutesSeconds (seconds : Int) -> (Int, Int, Int)
        {
            return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
        }


    }

我想我刚刚意识到我的阵列在应用程序关闭后重新启动。这就是 table 崩溃的原因,因为它超出了范围..

这是我保存数组的另一个文件。

import UIKit
class Kicks: UIViewController
{
  var count = 0 as Int
    var countKicks = 0 as Int
    var kickReached = false as Bool
    var pressedOnce = true as Bool
    var timer = NSTimer()
    var test: MyHistory!
    var dateString = " "

    @IBOutlet var timerLabel: UITextField!
    @IBOutlet var kicksLabel: UITextField!

    @IBOutlet var dateDisplay: UITextField!

    @IBOutlet var kickbutton: UIButton!

    var myHistoryArray: [MyHistory] = []
    var currentMyHistory: MyHistory!

    override func viewDidLoad()
    {
        super.viewDidLoad()
        self.printTimestamp()
        // Do any additional setup after loading the view, typically from a nib.
        self.view.backgroundColor = UIColor(patternImage: UIImage(named: "background13.png")!)
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

      @IBAction func kickButton()
    {

        //currentMyHistory.kicksNumber = 5
        kickbutton.setImage(UIImage(named: "gold-button-heart-icon.png"), forState: UIControlState.Normal)


        if(pressedOnce == true)
        {
            pressedOnce = false
            timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("counter"), userInfo: nil, repeats: true)
        }
        else if(kickReached == true)
        {

            //  let date = NSDate()
            //  let calendar = NSCalendar.currentCalendar()
            // let timer_total = calendar.components([ .Hour, .Minute, .Second], fromDate: date)

        }
        else if(pressedOnce == false)
        {
            countKicks++
            kicksLabel.text = "\(countKicks)"
            if(countKicks == 10)
            {
                self.printTimestamp()
                kickReached = true
                timer.invalidate()
                kickbutton.setImage(UIImage(named: "pink-button-heart-icon.png"), forState: UIControlState.Normal)
                congratsAlert()

                currentMyHistory = MyHistory(kicksNumber: countKicks, durationNumber: count)

                myHistoryArray.append(currentMyHistory)


                test = myHistoryArray[0]

                print("countof array ",  myHistoryArray.count)

                printTimestamp() // Prints "Sep 9, 2014, 4:30 AM"

                //save data
                let savedData = NSKeyedArchiver.archivedDataWithRootObject(myHistoryArray)
                let defaults = NSUserDefaults.standardUserDefaults()
                defaults.setObject(savedData, forKey: "MyHistory")
                clear()

            }
        }

    }

    func printTimestamp() {
        let timestamp = NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .MediumStyle, timeStyle: .ShortStyle)
        print(timestamp)
        dateDisplay.text = "\(timestamp)"
    }



    // save countKicks, count, and stamp i
    func congratsAlert()
    {
        let alert = UIAlertController(title: "Congratulation", message: "Yay!!! Angelina kicked 10 times in less than 2 hours.",preferredStyle: .Alert)

        let okAction = UIAlertAction(title: "Ok",style: .Default,handler:{(action:UIAlertAction) -> Void in})
        alert.addAction(okAction)

        presentViewController(alert,animated: true,completion: nil)
    }

    func clear()
    {
        count = 0
        countKicks = 0
        kickReached = false
        pressedOnce = true
        timerLabel.text = "00:00:0\(count)"
        kicksLabel.text = "\(countKicks)"
    }

    func counter()
    {
        ++count
        let (hour,minutes,seconds) = secondsToHoursMinutesSeconds(count)

        if(seconds < 10 && minutes < 10)
        {
            timerLabel.text = "0\(hour):0\(minutes):0\(seconds)"
        }
        else if(seconds > 9 && minutes < 10)
        {
            timerLabel.text = "0\(hour):0\(minutes):\(seconds)"
        }
        else if(seconds > 9 && minutes > 9)
        {
            timerLabel.text = "0\(hour):\(minutes):\(seconds)"
        }
        else if(seconds < 10 && minutes > 9)
        {
            timerLabel.text = "0\(hour):\(minutes):0\(seconds)"
        }
    }

    func secondsToHoursMinutesSeconds (seconds : Int) -> (Int, Int, Int)
    {
        return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
    }

}

写的很清楚:

'NSRangeException',原因:'*** -[__NSArrayI objectAtIndex:]:索引 1 超出范围 [0 .. 0]'

仔细检查您的数组对象,例如 newHistory 在您的应用程序启动时包含所有元素

好像

    func tableView(tableView: UITableView,numberOfRowsInSection section: Int) -> Int
    {
        return self.newHistory.count
    }

self.newHistory.count不为0会触发cellForRowAtIndexPath,试试在numberOfRowsInSectioncellForRowAtIndexPath里面加两个断点,这样就知道哪里出错了。通常,如果没有数据,numberOfRowsInSection会return0,cellForRowAtIndexPath不会被触发。

您还可以在 Xcode 断点导航器中设置异常点,这样您就可以在任何异常处中断。这是您需要掌握的简单调试技巧。