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 操作

从 App Delegate (Swift) 调用 ViewControllers 方法或 Segue

在视图控制器之间有很多segues可以吗?