Getting the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
I am making a registration form application. The app allows users to create custom questions to be added to a form. At the moment I'm using a Singleton design pattern to pass the list of questions between the editing tab and the tab used to display the form.
My singleton class:
class Singleton {
static let sharedInstance = Singleton()
var questions: [Question] = []
}
In the editing form the user will press a button to update the form that people can then fill out. Here is that code and is also where I'm getting the error:
var mySingleton: Singleton!
#IBAction func updateForm(sender: AnyObject) {
for index in mySingleton.questions.count...questionsArray.count {
mySingleton.questions.append(questionsArray[index])
}
}
Thank you for your help.
This is where the error is occurring:
for index in mySingleton.questions.count...questionsArray.count {
mySingleton.questions.append(questionsArray[index])
}
The final index that is looped through is questionsArray.count. When you access questionsArray[questionsArray.count], you are outside the bounds of the array. This index should never be accessed.
Instead, change your loop to the following:
for index in mySingleton.questions.count..<questionsArray.count {
mySingleton.questions.append(questionsArray[index])
}
The only difference is that ... becomes ..<, in order to leave out the last index that is causing the error.
Edit: after looking back at the code, it seems likely that mySingleton was never set equal to anything. Before this code is executed, you could set mySingleton = Singleton.sharedInstance, or simply get rid of mySingleton and directly use Singleton.sharedInstance.
Related
I'm getting a crash in the following code:
var gmsBounds: GMSMutablePath {
get {
let path = GMSMutablePath(with: self.boundaries)
return path!
}
}
Currently it crashes when initializing the GMSMutablePath according to Crashlytics. However this code isn't ever called before the class is initialized, and self.boundaries is stored during initialization, so I'm not sure how self.boundaries could be nil. I'm also personally unable to recreate the crash, so it is not a bug that affects every user. Any help is appreciated, computed variables are a new concept for me.
When I make code reviews always i avoid forced unwrapping, at first sight you can believe that it never will turn to nil but I prefer avoid that
return path!
Try to unwrapping (safely) it first or change the variable definition for optional:
var gmsBounds: GMSMutablePath? {
get {
let path = GMSMutablePath(with: self.boundaries)
return path!
}
}
I have a feeling there is more than one problem with this code, but my first issue is that my delegate returns nil and I do not know why. First, is my delegate:
import UIKit
//delegate to move information to next screen
protocol userEnteredDataDelegate {
func userDidEnterInformation(info:NSArray)
}
Next, I have a var defined for the delegate and I believe the ? makes it an optional variable? This is defined inside the class
var dataPassDelegate:userEnteredDataDelegate? = nil
Now, after my user has entered information into the fields in the view, I want to add those field values to an array and then pass that array on to the next view where it will be added to. I have pieced this code together from some YouTube examples but I think I am missing a needed part. When do I assign some kind of value to the dataPassDelegate var so it is not nil when the if statement comes? Do I even need that if statement?
if blankData != 1 {
//add code to pass data to next veiw controller
enteredDataArray = [enterDate.text, enterSeason.text, enterSport.text, enterDispTo.text]
//println(enteredDataArray)
self.appIsWorking ()
if (dataPassDelegate != nil) {
let information: NSArray = enteredDataArray
println(information)
dataPassDelegate!.userDidEnterInformation(information)
self.navigationController?.popViewControllerAnimated(true)
} else {
println ("dataPassDelegate = nil")
}
//performSegueWithIdentifier("goToDispenseScreenTwo", sender: self)
activityIndicator.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
}
blankData = 0
}
Your help is appreciated.
A delegate is a pointer to another object that conforms to a particular protocol. Often you use delegates to refine the behavior of your class, or to send back status information o the results of an async network request
When you set your dataPassDelegate delegate is up to you.
What is the object that has the dataPassDelegate property? What object will be serving as the delegate?
You need to create 2 objects (the object that will be serving as the delegate, and the object that has the dataPassDelegate property) and link them up.
We can't tell you when to do that because we don't know what you're trying to do or where these objects will be used.
I am trying to add names into a UITableView. The names will be stored as a NSUserDefault.
My viewDidLoad:
var PlayersUserDefault = NSUserDefaults.standardUserDefaults()
if (PlayersUserDefault.arrayForKey("playersKey") != nil){
players = PlayersUserDefault.arrayForKey("playersKey")
}
Add name button:
#IBAction func addButtonAction(sender: AnyObject) {
players!.append(namesTextBox.text)
myTableView.reloadData()
}
When I press the addButtonAction, I am getting error on following:
players!.append(namesTextBox.text)
Players declaration:
var players = NSUserDefaults().arrayForKey("playersKey")
Any idea why I am getting error?
Error image:
In one line you use NSUserDefaults.standardUserDefaults() and in the other you create new instance of NSUserDefaults and ask for "playersKey". What you should do is to use NSUserDefaults.standardUserDefaults() for retrieving AND saving your players.
Take a look at the refence:
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/#//apple_ref/doc/constant_group/NSUserDefaults_Domains
For init:
This method does not put anything in the search list. Invoke it only
if you’ve allocated your own NSUserDefaults instance instead of using
the shared one.
and for shared instance:
If the shared defaults object does not exist yet, it is created with a
search list containing the names of the following domains, in this
order:
NSArgumentDomain, consisting of defaults parsed from the application’s
arguments
A domain identified by the application’s bundle identifier
NSGlobalDomain, consisting of defaults meant to be seen by all
applications
Separate domains for each of the user’s preferred languages
NSRegistrationDomain, a set of temporary defaults whose values can be
set by the application to ensure that searches will always be
successful
The defaults are initialized for the current user. Subsequent
modifications to the standard search list remain in effect even when
this method is invoked again—the search list is guaranteed to be
standard only the first time this method is invoked.
The players array is nil at the point of time thats why the array is not unwrapped. If you tap the button at the first time, your UserDefaults will not be having players, So the players array is nil. So you can solve this in two ways do like this.
On your viewDidLoad()
var PlayersUserDefault = NSUserDefaults.standardUserDefaults()
if (PlayersUserDefault.arrayForKey("playersKey") != nil){
players = PlayersUserDefault.arrayForKey("playersKey")
}else {
players = [String]()
}
Otherwise, initialise the players array with an empty string array like this:
var players = [String]()
This may help you.
You could try unwrapping the value of players before attempting to do append. Then you will know for sure if it's nil or not.
Try:
#IBAction func addButtonAction(sender: AnyObject) {
if let playerValue = players {
players!.append(namesTextBox.text)
myTableView.reloadData()
}else{
println("players is nil!")
}
}
I have a custom UITableViewCell class named PinCell.swift which contains a reference to a UITableViewController and an IBAction that passes data from the cell to the UITableViewController. I have no errors and everything builds fine.
PinCell.swift (UITableViewCell):
var viewControllerB:UITableViewController!
#IBAction func titleButtonPressed(sender: AnyObject) {
var venueIDFromRequest = self.pin?["venue"]["id"].stringValue
println("venueIDFromRequest is: \(venueIDFromRequest)")
if venueIDFromRequest != nil {
let venueDetailRef = viewControllerB as! VenueDetailViewController
venueDetailRef.venueIDPassed = venueIDFromRequest!
}
if(self.delegate != nil){ //Just to be safe.
self.delegate.callSegueFromCell(venueIDFromRequest: venueIDFromRequest!)
}
}
VenueDetailViewController.swift (UITableViewController)
var venueIDPassed:String! = "asdklasdkas"
When I tap the button in my app, it crashes and the following is printed out to the console fatal error: unexpectedly found nil while unwrapping an Optional value which we have all seen before and I realize what this error means. My question is why is this happening when it seems to have a reference to the variable in the other view controller? Even when I println(venueIDFromRequest) I get the correct data. What am I doing wrong here and how can I assign venueIDFromRequest to self.viewControllerB.venueIDPassed ?
Here is a screenshot if it can help diagnose what is actually going on:
I started getting this error randomly (may be due to updating swift) but when I reach, didSet in detailItem, I call configureView. In configureView I check to see if detailItem is indeed set and then start assigning values to my outlets.
if let detail: Posting = self.detailItem {
print("detail title is ")
println(detail.title)
// Title
self.titleLabel.text = detail.title
However this crashes with output:
detail title is Skiing in Vail
fatal error: unexpectedly found nil while unwrapping an Optional value
The error is on the line:
self.titleLabel.text = detail.title
I don't understand why it is crashing when it is is clearly set...
Note that this doesn't happen if I call configureView from within viewDidLoad.
This only happens when I call it from
var detailItem: Posting? {
didSet { self.configureView() }
}
Something I'm missing? Is this working asynchronously or something?
Referencing your comment on how to implement this, there are a few trains of thought. First, the reason you can modify it directly from your MasterVC is because the IBOutlet hasn't been instantiated in the DetailVC and thus isn't available to be modified yet.
One option, which I'd probably follow, is to have a helper variable on your detail view where you can place the value. Then viewWillAppear() you can take whatever's in the variable and set it as the label's text. Here's a tutorial on it, but to answer your specific quesiton please jump to the prepareForSegue method in this tutorial. It gives a good rundown of the whole process:
http://www.codingexplorer.com/segue-swift-view-controllers/
Let me know if this doesn't solve your problem.