1

I'm trying to create an alert view that adds an item or items to my table view after taping an ad button. On pressing the add button the alertview should appear with three text fields for item name price and quantity and when pressing the ok button it will then add the item, however many times the quantity is. When I tap the button though I get the following error:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'

Here are the functions:

func createAlertView() -> UIAlertController {

    let view = UIView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(250), height: CGFloat(100)))
    let itemName = UITextField(frame: CGRect(x: CGFloat(10), y: CGFloat(0), width: CGFloat(252), height: CGFloat(25)))
    itemName.borderStyle = .RoundedRect
    itemName.placeholder = "Item Name"
    itemName.keyboardAppearance = .Alert
    itemName.delegate = self
    view.addSubview(itemName)

    let itemPrice = UITextField(frame: CGRect(x: CGFloat(10), y: CGFloat(30), width: CGFloat(252), height: CGFloat(25)))
    itemPrice.placeholder = "Item Price"
    itemPrice.borderStyle = .RoundedRect
    itemPrice.keyboardAppearance = .Alert
    itemPrice.delegate = self
    view.addSubview(itemPrice)

    let itemQuantity = UITextField(frame: CGRect(x: CGFloat(10), y: CGFloat(60), width: CGFloat(252), height: CGFloat(25)))
    itemQuantity.placeholder = "Item Quantity"
    itemQuantity.borderStyle = .RoundedRect
    itemQuantity.keyboardAppearance = .Alert
    itemQuantity.delegate = self
    view.addSubview(itemQuantity)

    let alertController = UIAlertController(title: "Add Item", message: nil, preferredStyle: .Alert)
    alertController.view.addSubview(view)

    return alertController
}

func createAlertViewItem(alertController: UIAlertController, itemName: String, itemStringPrice: String) {

    let managedContext = self.bill.managedObjectContext
    let entity = NSEntityDescription.entityForName("Item", inManagedObjectContext: managedContext!)
    let newItem = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)

    if let itemName = alertController.textFields?.first?.text {

        newItem.setValue(itemName, forKey: "name")

    }
    if let itemPriceString = alertController.textFields?[1].text {

        let itemPriceNumber = Int(itemPriceString)

        newItem.setValue(itemPriceNumber, forKey: "price")
    }

    do {
        try managedContext!.save()
    }
    catch let error as NSError {
        print("Core Data save failed: \(error)")
    }

    let currentItems = self.bill.mutableSetValueForKey("items")
    currentItems.addObject(newItem)

    self.tableView.reloadData()
}

@IBAction func addNewItem(sender: UIButton) {

    let alertController = createAlertView()

    let itemName = alertController.textFields![0].text
    let itemPrice = alertController.textFields?[1].text
    let itemQuantity: Int!

    if alertController.textFields![2].text == "" {
        itemQuantity = 0
    } else {
        itemQuantity = Int((alertController.textFields?[2].text)!)!
    }

    let okAction = UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
        if itemQuantity == 0 || itemQuantity == 1 {
            print(2)
            self.createAlertViewItem(alertController, itemName: itemName!, itemStringPrice: itemPrice!)
        } else {
            for _ in 0...itemQuantity {
                print(3)
                self.createAlertViewItem(alertController, itemName: itemName!, itemStringPrice: itemPrice!)
            }
        }
    })

    alertController.addAction(okAction)

    let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
    alertController.addAction(cancelAction)

    presentViewController(alertController, animated: true, completion: nil)
}

I think I'm missing something when adding the view to the alert view but I can't see what as I think the error is stating that it can't find the textfields. I can't be sure though. Any help would be great though. Thanks!

Wazza
  • 1,725
  • 2
  • 17
  • 49
  • Alternatively - You could also create a custom view in your storyboard. Add it to the view controller where you want it displayed. Make it invisible or position it off-screen. Then present it with some animation whenever you want to display it. This process would give you complete control over the look and feel. – Tommie C. Dec 17 '16 at 21:05
  • Thanks for your help. I will try that if i cant find a solution to the alertviewcontroller. – Wazza Dec 17 '16 at 21:17

2 Answers2

1

You should not try to manaipulate the alert controller's view hierarchy. Instead, use the method addTextField(configurationHandler:) to add text fields to your alert controller. I suggest taking a look at the UIAlertController Class reference in Xcode. It is well documented.

EDIT:

Also, I would suggest not referring to a UIAlertController as an "alertview". In previous versions of iOS we used a class called a UIAlertView, but that's now deprecated. The term "alertview" is going to make people think you're using the old deprecated class.

Community
  • 1
  • 1
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • But when i add a third textfield to the UIAlertController i cant access it which is why i though i had to add them by creating a custom view. Or am i missing something? – Wazza Dec 17 '16 at 20:46
0

Have you seen these other SO Questions? If so try to extrapolate. The error message seems to indicate a nil object between your method calls so make sure you are using a shared reference between these methods. Check the object values before and after adding the UITextfield to validate the state of the controller. Add your alertController as a reference to your UIViewController class and check its state when you make the desired changes.

Community
  • 1
  • 1
Tommie C.
  • 12,895
  • 5
  • 82
  • 100