ViewControllers之间的segue问题
Posted
技术标签:
【中文标题】ViewControllers之间的segue问题【英文标题】:Trouble with segue between ViewControllers 【发布时间】:2015-08-20 19:11:20 【问题描述】:这是我的代码:
import UIKit
import CoreData
class ViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
var logo = UIImage(named: "no_pain_no_gain-_.jpg")
logoImage.image = logo
viewExercisesButton.frame = CGRectMake(-30,250,125,125)
viewExercisesButton.addTarget(self, action: "viewExercisesButtonTouch:", forControlEvents: UIControlEvents.TouchDown)
viewExercisesButton.setImage(imageViewExercises, forState: .Normal)
viewExercisesButton.imageEdgeInsets = UIEdgeInsetsMake(30,30,30,30)
self.view.addSubview(viewExercisesButton)
var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var fetchedResultsController: NSFetchedResultsController?
var daysArray1 = [TrainingDay]()
@IBOutlet var logoImage: UIImageView!
var viewExercisesButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
var imageViewExercises = UIImage(named: "plusbutton.png")
func viewExercisesButtonTouch(sender: UIButton!)
performSegueWithIdentifier("goToDays", sender: self)
println("future event will be added, button working fine - view")
第一个去:
import UIKit
import CoreData
class ViewExercisesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate
override func viewDidLoad()
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchTrainingDetails(), managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController?.delegate = self
fetchedResultsController?.performFetch(nil)
self.viewExerciseTableView.reloadData()
sundayButton.frame = CGRectMake(-30,50,125,125)
sundayButton.addTarget(self, action: "sundayButtonTouch:", forControlEvents: UIControlEvents.TouchDown)
sundayButton.setImage(imageSunday, forState: .Normal)
sundayButton.imageEdgeInsets = UIEdgeInsetsMake(30,30,30,30)
self.view.addSubview(sundayButton)
mondayButton.frame = CGRectMake(120,50,125,125)
mondayButton.addTarget(self, action: "mondayButtonTouch:", forControlEvents: UIControlEvents.TouchDown)
mondayButton.setImage(imageMonday, forState: .Normal)
mondayButton.imageEdgeInsets = UIEdgeInsetsMake(30,30,30,30)
self.view.addSubview(mondayButton)
tuesdayButton.frame = CGRectMake(270,50,125,125)
tuesdayButton.addTarget(self, action: "tuesdayButtonTouch:", forControlEvents: UIControlEvents.TouchDown)
tuesdayButton.setImage(imageTuesday, forState: .Normal)
tuesdayButton.imageEdgeInsets = UIEdgeInsetsMake(30,30,30,30)
self.view.addSubview(tuesdayButton)
wednesdayButton.frame = CGRectMake(-30,150,125,125)
wednesdayButton.addTarget(self, action: "wednesdayButtonTouch:", forControlEvents: UIControlEvents.TouchDown)
wednesdayButton.setImage(imageWednesday, forState: .Normal)
wednesdayButton.imageEdgeInsets = UIEdgeInsetsMake(30,30,30,30)
self.view.addSubview(wednesdayButton)
thursdayButton.frame = CGRectMake(70,150,125,125)
thursdayButton.addTarget(self, action: "thursdayButtonTouch:", forControlEvents: UIControlEvents.TouchDown)
thursdayButton.setImage(imageThursday, forState: .Normal)
thursdayButton.imageEdgeInsets = UIEdgeInsetsMake(30,30,30,30)
self.view.addSubview(thursdayButton)
fridayButton.frame = CGRectMake(170,150,125,125)
fridayButton.addTarget(self, action: "fridayButtonTouch:", forControlEvents: UIControlEvents.TouchDown)
fridayButton.setImage(imageFriday, forState: .Normal)
fridayButton.imageEdgeInsets = UIEdgeInsetsMake(30,30,30,30)
self.view.addSubview(fridayButton)
saturdayButton.frame = CGRectMake(270,150,125,125)
saturdayButton.addTarget(self, action: "saturdayButtonTouch:", forControlEvents: UIControlEvents.TouchDown)
saturdayButton.setImage(imageSaturday, forState: .Normal)
saturdayButton.imageEdgeInsets = UIEdgeInsetsMake(30,30,30,30)
self.view.addSubview(saturdayButton)
//VAR AND LET
var sundayButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
var imageSunday = UIImage(named: "day.png")
var mondayButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
var imageMonday = UIImage(named: "day.png")
var tuesdayButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
var imageTuesday = UIImage(named: "day.png")
var wednesdayButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
var imageWednesday = UIImage(named: "day.png")
var thursdayButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
var imageThursday = UIImage(named: "day.png")
var fridayButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
var imageFriday = UIImage(named: "day.png")
var saturdayButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
var imageSaturday = UIImage(named: "day.png")
@IBOutlet var viewExerciseTableView: UITableView!
var daysArray = [TrainingDay]()
var detailsArray = [TrainingDetails]()
var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var fetchedResultsController: NSFetchedResultsController?
// FUNCTIONS
func sundayButtonTouch(sender: UIButton!)
println("future event will be added, button working fine - sunday")
func mondayButtonTouch(sender: UIButton!)
println("future event will be added, button working fine - monday")
func tuesdayButtonTouch(sender: UIButton!)
println("future event will be added, button working fine - tuesday")
func wednesdayButtonTouch(sender: UIButton!)
println("future event will be added, button working fine - wednesday")
func thursdayButtonTouch(sender: UIButton!)
println("future event will be added, button working fine - thursday")
func fridayButtonTouch(sender: UIButton!)
println("future event will be added, button working fine - friday")
func saturdayButtonTouch(sender: UIButton!)
println("future event will be added, button working fine - saturday")
// FETCH REQUEST METHODS
func fetchTrainingDay() -> NSFetchRequest
let fetchRequest = NSFetchRequest(entityName: "TrainingDay")
fetchRequest.predicate = nil
let sortDescriptor = NSSortDescriptor(key: "day", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
return fetchRequest
func fetchTrainingDetails() -> NSFetchRequest
let currentDay = daysArray
let fetchRequest = NSFetchRequest(entityName: "TrainingDetails")
var predicate = NSPredicate(format: "trainingDay = %@", currentDay)
fetchRequest.predicate = predicate
let sortDescriptor1 = NSSortDescriptor(key: "exerciseName", ascending: true)
let sortDescriptor2 = NSSortDescriptor(key: "repsNumber", ascending: true)
let sortDescriptor3 = NSSortDescriptor(key: "setsNumber", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor1, sortDescriptor2, sortDescriptor3]
fetchRequest.fetchBatchSize = 20
return fetchRequest
//TABLE VIEW DELEGATE METHODS
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cellIdentifier = "exCell"
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? UITableViewCell
if cell == nil
cell = UITableViewCell(style: UITableViewCellStyle.Value2, reuseIdentifier: cellIdentifier)
let row = indexPath.row
println("\(row)")
let details = detailsArray[indexPath.row]
cell!.textLabel!.text = details.exerciseName
cell?.detailTextLabel?.text = "Sets: #\(details.setsNumber) Reps: #\(details.repsNumber)"
return cell!
// MARK: NSFetchedResultsControllerDelegate
func controllerWillChangeContent(controller: NSFetchedResultsController)
self.viewExerciseTableView.beginUpdates()
func controller(controller: NSFetchedResultsController,
didChangeObject anObject: AnyObject,
atIndexPath indexPath: NSIndexPath?,
forChangeType type: NSFetchedResultsChangeType,
newIndexPath: NSIndexPath?)
switch(type)
case .Insert:
if let newIndexPath = newIndexPath
viewExerciseTableView.insertRowsAtIndexPaths([newIndexPath],
withRowAnimation:UITableViewRowAnimation.Fade)
case .Delete:
if let indexPath = indexPath
viewExerciseTableView.deleteRowsAtIndexPaths([indexPath],
withRowAnimation: UITableViewRowAnimation.Fade)
case .Update:
break
case .Move:
if let indexPath = indexPath
if let newIndexPath = newIndexPath
viewExerciseTableView.deleteRowsAtIndexPaths([indexPath],
withRowAnimation: UITableViewRowAnimation.Fade)
viewExerciseTableView.insertRowsAtIndexPaths([newIndexPath],
withRowAnimation: UITableViewRowAnimation.Fade)
func controller(controller: NSFetchedResultsController,
didChangeSection sectionInfo: NSFetchedResultsSectionInfo,
atIndex sectionIndex: Int,
forChangeType type: NSFetchedResultsChangeType)
switch(type)
case .Insert:
viewExerciseTableView.insertSections(NSIndexSet(index: sectionIndex),
withRowAnimation: UITableViewRowAnimation.Fade)
case .Delete:
viewExerciseTableView.deleteSections(NSIndexSet(index: sectionIndex),
withRowAnimation: UITableViewRowAnimation.Fade)
default:
break
func controllerDidChangeContent(controller: NSFetchedResultsController)
viewExerciseTableView.endUpdates()
这是第二个。
现在,当我尝试在这两者之间进行切换时,会发生这种情况:
将添加未来事件,按钮工作正常 - 查看 2015-08-20 15:05:58.047 Fit Fuse[941:13395] -[Swift._SwiftDeferredNSArray longLongValue]:无法识别的选择器发送到实例 0x7f920a651230 2015-08-20 15:05:58.053 Fit Fuse[941:13395] 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:'-[Swift._SwiftDeferredNSArray longLongValue]:无法识别选择器发送到实例 0x7f920a651230' 首先抛出调用堆栈:
有人知道为什么会这样吗?
更新
我是这样做的:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCellWithIdentifier("exCell", forIndexPath: indexPath) as! UITableViewCell
let details = fetchedResultsController!.objectAtIndexPath(indexPath) as! TrainingDetails
cell.textLabel!.text = "\(details.exerciseName)" //CRASHES RIGHT HERE: Thread 1:EXC_BAD_ACCESS(code=1, address=0x0)
cell.detailTextLabel!.text = "Sets: #\(details.setsNumber) Reps: #\(details.repsNumber)"
return cell
【问题讨论】:
我认为问题是fetchTrainingDetails
中的谓词,因为daysArray是空的。要检查,请尝试删除谓词并查看问题是否消失。
嗯,你没看错,但它在这行中崩溃了:let details = detailsArray[indexPath.row]
并出现错误:致命错误:数组索引超出范围。我打印了数组的索引,它说索引 0。索引 0 怎么会超出范围?
哦,在核心数据中保存这 3 个属性(名称、代表和集合)后,它就崩溃了。
在cellForRowAtIndexPath中,可以使用frc而不是detailsArray:"let details = fetchedResultsController.objectAtIndexPath(indexPath) as!TrainingDetails"
由于你使用的是frc,你根本不需要 detailsArray。
【参考方案1】:
为了在Core Data中正确保存东西,这个方法应该是这样的:
func appendTrainingDetailsToArray ()
let nameLabel = exerciseName.text
namesArray.append(nameLabel)
let numberOfSets = setsNumber.text?.toInt()
setsArray.append(numberOfSets!)
let numberOfReps = repsNumber.text?.toInt()
repsArray.append(numberOfReps!)
let row = daysPickerView.selectedRowInComponent(0)
let currentDay = daysArray[row]
let detailsEntity = NSEntityDescription.entityForName("TrainingDetails", inManagedObjectContext: moc!)
let trainingdetails = TrainingDetails(entity: detailsEntity!, insertIntoManagedObjectContext: moc)
trainingdetails.exerciseName = exerciseName.text
trainingdetails.repsNumber = repsNumber.text!
trainingdetails.setsNumber = setsNumber.text!
trainingdetails.trainingDay = currentDay
var error: NSError?
moc?.save(&error)
if let err = error
var status = err.localizedFailureReason
println("\(status)")
else
println("CURRENT SETTING: \(trainingdetails.trainingDay)")
有了这个,代码就可以正常工作了!!感谢@pbasdf
【讨论】:
以上是关于ViewControllers之间的segue问题的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 在 segue 之后保存 ViewController 设置
Segues 和从内存中清除历史 ViewControllers
仅在不切换 viewControllers 的情况下 Segue 动画
如何通过 viewControllers 的导航控制器设置自定义 segue 操作