应用程序在重新打开后崩溃

时间:2016-01-24 21:58:46

标签: ios uitableview nsuserdefaults nskeyedarchiver nskeyedunarchiver

基本上每当我关闭并重新打开应用程序时,它会在我打开“历史记录”选项卡时崩溃。我很确定它是因为我如何使用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)
        }


    }

我想我刚才意识到应用关闭后我的数组会重新启动。这就是为什么桌子崩溃了,它越界了..

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

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)
    }

}

1 个答案:

答案 0 :(得分:1)

它清楚地说:

'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将返回0并且cellForRowAtIndexPath将不会被触发。

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