重新打开后应用程序崩溃
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
,试试在numberOfRowsInSection
和cellForRowAtIndexPath
里面加两个断点,这样就知道哪里出错了。通常,如果没有数据,numberOfRowsInSection
会return0,cellForRowAtIndexPath
不会被触发。
您还可以在 Xcode 断点导航器中设置异常点,这样您就可以在任何异常处中断。这是您需要掌握的简单调试技巧。
基本上每次我关闭并重新打开应用程序时,当我打开“历史记录”选项卡时它都会崩溃。我很确定这是因为我使用 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
,试试在numberOfRowsInSection
和cellForRowAtIndexPath
里面加两个断点,这样就知道哪里出错了。通常,如果没有数据,numberOfRowsInSection
会return0,cellForRowAtIndexPath
不会被触发。
您还可以在 Xcode 断点导航器中设置异常点,这样您就可以在任何异常处中断。这是您需要掌握的简单调试技巧。