Приложение вылетает после повторного открытия

В основном каждый раз, когда я закрываю и снова открываю приложение, оно вылетает, когда я открываю вкладку «История». Я почти уверен, что это из-за того, как я использую 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)
    }

}

person Triscuit Delicious    schedule 24.01.2016    source источник
comment
Опубликуйте трассировку стека из вывода   -  person pnavk    schedule 25.01.2016
comment
Завершение работы приложения из-за необработанного исключения «NSRangeException», причина: «*** -[__NSArrayI objectAtIndex:]: индекс 1 за пределами [0 .. 0]» *** Стек вызовов первого броска: (0x181cd5900 0x181343f80 0x181bbbac4 0x1000feb5c 0x1000fdbd6 1240011x8 0x1300112 0x1000637a4 0x186d1931c 0x186d19484 0x186d087e8 0x186d1dfb0 0x186ab308c 0x1869c3778 0x1843d2b2c 0x1843cd738 0x1843cd5f8 0x1843ccc94 0x1843cc9dc 0x1869b9c78 0x181c8c588 0x181c8a32c 0x181c8a75c 0x181bb9680 0x1830c8088 0x186a30d90 0x1000617c4 0x18175a8b8) libc++abi.dylib: terminating with uncaught exception of type NSException   -  person Triscuit Delicious    schedule 25.01.2016
comment
массив countof 6 24 января 2016, 14:33 массив countof 1   -  person Triscuit Delicious    schedule 25.01.2016
comment
массив становится 0 после выключения приложения   -  person Triscuit Delicious    schedule 25.01.2016
comment
Почему вы обновляете массив newHistory в методе cellForRowAtIndexPath?   -  person shpasta    schedule 25.01.2016
comment
потому что иначе я не могу ничего добавить в ячейку. Что вы имеете ввиду обновить? Я просто разархивирую все из истории   -  person Triscuit Delicious    schedule 25.01.2016
comment
Я изменил это, но я все еще получаю неправильные результаты, мой tableView по какой-то причине не обновляется   -  person Triscuit Delicious    schedule 25.01.2016
comment
Я заметил, что мой tableView обновляется только после того, как я снова открываю приложение.   -  person Triscuit Delicious    schedule 25.01.2016


Ответы (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, попробуйте добавить две точки останова внутри numberOfRowsInSection и cellForRowAtIndexPath, чтобы вы могли знать, что идет не так. Обычно, если данных нет, numberOfRowsInSection возвращает 0, а cellForRowAtIndexPath не срабатывает.

Вы также можете указать точку исключения в навигаторе Xcode BreakPoint, чтобы вы могли прерываться при любых исключениях. Это простые навыки отладки, которые вам необходимо освоить.

person Wingzero    schedule 25.01.2016
comment
вот в чем проблема, после перезапуска приложения все данные теряются... не могу понять почему - person Triscuit Delicious; 25.01.2016
comment
Вы не сохраняете данные на диск? Вы должны все, когда вы запускаете приложение, повторно извлекать данные, а затем обновлять свою ячейку. - person Wingzero; 25.01.2016
comment
обновил мой вопрос, я видел, что вы сохранили и попытались перезагрузить, но дело в том, какая функция пытается прочитать пустой массив. Вы должны добавить исключение bp или вручную добавить свой bp для отладки, это должно быть очень легко решить - person Wingzero; 25.01.2016
comment
я разобрался спасибо!! :) моя единственная проблема в том, что теперь, когда я проверяю историю, она всегда показывает мне 1 запись позади, если я не переключаю вкладки дважды, не добавляя новую запись, в основном из того, что я понимаю, tableView не обновляется или не хватает строк? я не знаю :( - person Triscuit Delicious; 25.01.2016
comment
@TriscuitDelicious Не совсем понимаю, но табличное представление не будет обновлять ваш массив, если вы не сказали ему это сделать. Обычно, когда вы обновляете свой массив, вы вызываете tableView.reloadData для обновления представления таблицы. - person Wingzero; 25.01.2016
comment
Откуда мне звонить? Я добавил его во многих местах, и ничего не происходит. Если я добавлю его в tableView, все, что я получаю, это белые пятна вместо моих записей. - person Triscuit Delicious; 25.01.2016