ios - MBProgressHUD 导致 iOS 应用程序崩溃(Swift 2.0)

标签 ios swift core-data uipickerview mbprogresshud

我有一个 ViewController,它将用户输入保存到 CoreData,并在尝试保存后显示 MBProgressHUD 以说明保存是否成功。

我有一个 AddNewViewController 类

class AddNewViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {

@IBOutlet weak var inputErrorMessage: UILabel!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var amountLabel: UILabel!
    @IBOutlet weak var dayPicker: UIPickerView!
    @IBOutlet weak var durationPicker: UIPickerView!
    @IBOutlet weak var nameTextField: UITextField!
    @IBOutlet weak var amountTextField: UITextField!
    @IBOutlet weak var notesTextField: UITextField!

//variable to contrain the origin view controller
var originVC: String?

    // variables to hold user input
    var name: String?
    var amount: Double?
    var notes: String?
    var durationDay: Double?
    var durationType: String?

// The days and duration options to display in the pickers
    var durationPickerDataSource = ["Day(s)","Week(s)","Month(s)","Year(s)"];
    var dayPickerDataSource = ["1","2","3","4","5","6","7","8","9","10","11","12"];

@IBAction func saveButton(sender: AnyObject) {
        CoreDataStatic.data.saveIncomeBudgetAndExpenses(originVC!, name: name!, amount: amount, durationDay: durationDay!, durationType: durationType!, notes: notes!)
    }


/**
    The number of columns in the picker view.
    */
    func numberOfComponentsInPickerView(dayPickerView: UIPickerView) -> Int {
        return 1
    }

    /**
    The number of items in the picker view. Equal to the number of days(12) and duration options(4) .
    */
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if pickerView == durationPicker {
            return durationPickerDataSource.count;
        }
        else {
            return dayPickerDataSource.count;
        }
    }

    /**
    Gets the titles to use for each element of the picker view.
    */
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerView == durationPicker{
            durationType = durationPickerDataSource[row]
            return durationType
        }
        else {
            durationDay = Double(dayPickerDataSource[row])
            return dayPickerDataSource[row]
        }
    }
/**
    Display acknowledgement if the Income, Budget or Fixed Expense saved.
    */
    func displayMessage(origin: String) {
        var message : String

        //Changes the message depending on what the user was trying to save.
        if CoreDataStatic.data.saved == true {
        message = "\(origin) saved!"
                    }
        else if CoreDataStatic.data.saved == false {
            message = "Error: \(origin) failed to save!"
        }
        else {
            message = "Error!"
        }

        print(message)

        //displays acknowledgement for 2 seconds.
        /*let acknowledgement = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
        acknowledgement.mode = MBProgressHUDMode.Text
        acknowledgement.label.text = message
            acknowledgement.hideAnimated(true, afterDelay: 2)*/
    }

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        self.durationPicker.dataSource = self;
        self.durationPicker.delegate = self;
        self.dayPicker.dataSource = self;
        self.dayPicker.delegate = self;
    }

CoreData 类:

struct CoreDataStatic {
    static let data = CoreData()
}

public class CoreData {

    var appDel : AppDelegate

    //Manage a collection of managed objects.
    let context : NSManagedObjectContext

    //Describes an entity in Core Data.
    let incomeEntity : NSEntityDescription
    let budgetEntity : NSEntityDescription
    let fixedExpenseEntity : NSEntityDescription

    //Retrieve data from Core Data with the entity 'Scores'.
    let income = NSFetchRequest(entityName: "Income")
    let budget = NSFetchRequest(entityName: "Budget")
    let fixedExpense = NSFetchRequest(entityName: "FixedExpenses")

    //Set the key that needs updating which is always 'score'
    let nameKeyToUpdate = "name"
    let amountDayKeyToUpdate = "amountDay"
    let amountWeekKeyToUpdate = "amountWeek"
    let amountMonthKeyToUpdate = "amountMonth"
    let amountYearKeyToUpdate = "amountYear"
    let durationDayKeyToUpdate = "durationDay"
    let durationTypeKeyToUpdate = "durationType"
    let notesKeyToUpdate = "notes"

    var saved : Bool?

func saveIncomeBudgetAndExpenses(origin: String, name: String, amountDay: Double, amountWeek: Double, amountMonth: Double, amountYear: Double, durationDay: Double, durationType: String, notes: String) {

        //saving in enity depending on origin view controller
        let entity : NSEntityDescription
        if origin == "Income" {
            entity = NSEntityDescription.entityForName("Income", inManagedObjectContext: context)!
        }
        else if origin == "Budget" {
            entity = NSEntityDescription.entityForName("Budget", inManagedObjectContext: context)!
        }
        else {
            entity = NSEntityDescription.entityForName("FixedExpenses", inManagedObjectContext: context)!
        }

        let saveNew = NSManagedObject(entity: entity,
            insertIntoManagedObjectContext:context)

        // add user input to the relevant entity
        saveNew.setValue(name, forKey: nameKeyToUpdate)
        saveNew.setValue(amountDay, forKey: amountDayKeyToUpdate)
        saveNew.setValue(amountWeek, forKey: amountWeekKeyToUpdate)
        saveNew.setValue(amountMonth, forKey: amountMonthKeyToUpdate)
        saveNew.setValue(amountYear, forKey: amountYearKeyToUpdate)
        saveNew.setValue(durationDay, forKey: durationDayKeyToUpdate)
        saveNew.setValue(durationType, forKey: durationTypeKeyToUpdate)
        saveNew.setValue(notes, forKey: notesKeyToUpdate)


    do {
    try context.save()
        print("saved")
        saved = true
    }
    catch _ {
        print("didnt save")
        saved = false
        }

        AddNewViewController().displayMessage(origin)
    }

    init(){
        appDel      = (UIApplication.sharedApplication().delegate as! AppDelegate)
        context     = appDel.managedObjectContext
        incomeEntity =  NSEntityDescription.entityForName("Income", inManagedObjectContext: context)!
        budgetEntity =  NSEntityDescription.entityForName("Budget", inManagedObjectContext: context)!
        fixedExpenseEntity =  NSEntityDescription.entityForName("FixedExpenses", inManagedObjectContext: context)!
    }
}

此代码按预期运行,但是当 displayMessage() 函数中的注释部分取消注释时,我收到以下错误: “ fatal error :在解包可选值时意外发现 nil”

由于 self.durationPicker.dataSource = self; 行在重写 viewDidLoad()

如有任何帮助,我们将不胜感激。

注意*如果我在 saveButton 函数中调用 displayMessage() ,则代码可以正常工作,因此不确定为什么在从 CoreData 类调用消息时它不起作用。

最佳答案

我不确定这是否是正确的方法,但我找到了解决办法。

创建了一个名为 attemptsSave 的变量 (bool),默认为 false。

在 saveIncomeBudgetAndExpenses try 和 catch 中,attemptSave 更改为 true。

现在,在两次按钮单击中都会调用 displayMessage() 函数,使用 if 语句来检查 attemptsSave 是否为 yes,如果是,则调用函数。

关于ios - MBProgressHUD 导致 iOS 应用程序崩溃(Swift 2.0),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35542545/

相关文章:

ios - 如何通过应用内购买锁定表格 View 中的特定行?

ios - 使用 Swift 读/写数组 plist

ios - Swift 中自定义 UIView 的加载时间缓慢

swift - 从后台线程合并到主线程上下文 : delete order random so crashes NSTableView

ios - 从包含 id 的字符串中形成 NSPredicate

ios - UITableView 使用 NSFetchedResultsController 和 CoreData 意外反弹到 beginUpdates()/endUpdates()/performBatchUpdates()

ios - iOS 的 codename1.ext.codescan cn1lib 有问题

ios - 检测 MTLTexture 是否为空白

ios - Swift:字符串 url 编码没有按预期工作

ios - 核心数据和 UIImage 的性能