11 Replies
      Latest reply on Dec 1, 2019 2:46 PM by Claude31
      wlionel Level 1 Level 1 (0 points)

        Hello: I am trying to load an NSPopupButton from a property list, but running the code below results in a fatal error: "Unexpectedly found nil while implicitly unwrapping an Optional value" on line i4. The debug output shows the following:

        figures count 4

        viewDidLoad() figures count 4

        Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/wlionelwilliams/Desktop/ScorcentMasterReview/ScorcentMasterReview/FiguresViewController.swift, line 109

         

        Line 10 seems to suggest that the items for the Popupbutton list is available. What am I missing?

         

        overridefunc viewDidLoad() {
                super.viewDidLoad()
                if let filePath = Bundle.main.path(forResource: "TFigures", ofType: "plist") {
                            print("filePath", filePath)
                            figures = Figure.figuresList(filePath)
                                print("figures count", figures.count)
                           }
                          
              //             figuresButton.removeAllItems()
                           print(#function, "figures count", figures.count)
                          
                          
                for figure in figures {
                    figuresButton.addItem(withTitle:figure.title)
                                }
                print ("itemsCount", title!.count)
                        selectedFigure = figures [0]
                        figuresButton.selectItem(at: 0)
               
            }
        • Re: Not Loading NSPopupbutton. Why?
          Claude31 Level 8 Level 8 (7,245 points)

          How did you declare  figuresButton ?

          Do you create it in IB ? If so, have you checked the connection to the IBOutlet ?

           

          Are you sure the crash occurs line 14 and not 16 ?

          What is title ?

           

          Should change like this for testing:

           

                  for figure in figures {
                      print("figure.title", figure.title)
                      figuresButton.addItem(withTitle: figure.title)
                   }
                    if title == nil {
                         print("Title is nil")     
                    } else {
                        print ("itemsCount", title!.count) 
                        selectedFigure = figures [0]
                        figuresButton.selectItem(at: 0)
                }
              }
            • Re: Not Loading NSPopupbutton. Why?
              wlionel Level 1 Level 1 (0 points)

              Hello Claude31:

              I checked the connection. It shows connected in the Connections Inspector.

              The line I indicated is throwing the fatal error: line 80 for complete code.

               

              Here is the full code:

               

              import Cocoa
              class FiguresViewController: NSViewController {
                  var figures = [Figure]()
                  var selectedFigure: Figure?
                  var figureId:String = ""
                  @IBOutlet weak var figureImage: NSImageView!
                   var selectedProduct: Product? {
                          didSet {
                            updateUI()
                          }
                  }
                   override func viewWillAppear() {
                        super.viewWillAppear()  
                        updateUI()
                      }
                 
                   func updateUI() {
                    //1
                    if isViewLoaded {
                        if let figure = selectedFigure {
                          figureImage.image = figure.image
                           
                        } 
                      }
                  }
                  @IBAction func valueChanged(_ sender: NSPopUpButton) {
                     
                      if let _ = sender.selectedItem?.title,
                      let index = figures.firstIndex(where: {$0.title == title}) {
                          selectedFigure = figures[index]
                      }
                            }
                  @IBOutlet weak var figuresButton: NSPopUpButton!
                  struct Figure {
                       var selectedFigure: Figures?
                                let title: String
                                var image: NSImage? {
                                  get {
                                    let i = NSImage(named: figureName)
                                    return i
                                  }
                                }
                           fileprivate let figureName: String
                                static func figuresList(_ filePath: String) -> [Figure] {
                                  var figures = [Figure]()
                                  if let figuresList = NSArray(contentsOfFile: filePath) as? [[String: Any]] {
                                       print("figuresList ##START##", figuresList, "figuresList ##END##")
                                    for dict in figuresList {
                                    if let figure = Figure(dictionary: dict) {
                                       figures.append(figure)
                                      }
                                    }
                                  }
                                  print("Figures is", figures)
                                  return figures
                                }
                                init?(dictionary: [String: Any]) {
                               guard let title = dictionary["figureId"] as? String,
                                     let figureName = dictionary["figureName"] as? String else {
                                       print("Initialization of Product failed with \(dictionary)")
                                      return nil
                                  }
                                 self.title = title
                                 self.figureName = figureName
                  }
              }
                  override func viewDidLoad() {
                      super.viewDidLoad()
                      if let filePath = Bundle.main.path(forResource: "TFigures", ofType: "plist") {
                                  print("filePath", filePath)
                                  figures = Figure.figuresList(filePath)
                                      print("figures count", figures.count)
                                 }
                                
                    //             figuresButton.removeAllItems()
                                 print(#function, "figures count", figures.count)
                                
                                
                      for figure in figures {
                          figuresButton.addItem(withTitle:figure.title)Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
                                      }
                      print ("itemsCount", title!.count)
                              selectedFigure = figures [0]
                              figuresButton.selectItem(at: 0)
                  }
                 
                  }    class Figures: NSViewController {
                       
                         override func viewDidLoad() {
                 }       super.viewDidLoad()
                         
                             // Do view setup here.
                             

              Here is the Console Output:

               

              filePath /Users/wlionelwilliams/Library/Developer/Xcode/DerivedData/ScorcentMasterReview-gnzfghwosuggdydtgxnsezjfynal/Build/Products/Debug/ScorcentMasterReview.app/Contents/Resources/TFigures.plist

               

              figuresList ##START## [["figureName": SCFigures2, "figureId": 3312], ["figureId": 3313, "figureName": SCFigures4], ["figureId": 3314, "figureName": SCFigures6], ["figureId": 3315, "figureName": SCFigures8]] figuresList ##END##

               

              Figures is [ScorcentMasterReview.FiguresViewController.Figure(selectedFigure: nil, title: "3312", figureName: "SCFigures2"), ScorcentMasterReview.FiguresViewController.Figure(selectedFigure: nil, title: "3313", figureName: "SCFigures4"), ScorcentMasterReview.FiguresViewController.Figure(selectedFigure: nil, title: "3314", figureName: "SCFigures6"), ScorcentMasterReview.FiguresViewController.Figure(selectedFigure: nil, title: "3315", figureName: "SCFigures8")]

               

              figures count 4

              viewDidLoad() figures count 4

               

              Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/wlionelwilliams/Desktop/ScorcentMasterReview/ScorcentMasterReview/FiguresViewController.swift, line 109

                • Re: Not Loading NSPopupbutton. Why?
                  Claude31 Level 8 Level 8 (7,245 points)

                  Thanks.

                   

                  So, crash is on

                  figuresButton.addItem(withTitle:figure.title)  // Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

                   

                  Could come from:

                  • figuresButton. (most likely)
                  • figure.title

                  Need to check if nil or not:

                   

                          for figure in figures {
                              print("figure", figure, "figureButton", figuresButton)
                              print("item to add", figure.title)
                              figuresButton.addItem(withTitle:figure.title)  // Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
                              print("added item", figure.title)
                          }

                   

                  My guess is that lines 2 and 3 will print once, with figureButton nil.

                   

                  If so, we'll have to find why.

                  • Re: Not Loading NSPopupbutton. Why?
                    wlionel Level 1 Level 1 (0 points)

                    Hello Claude31: here are the results:

                     

                    figures count 4

                    viewDidLoad() figures count 4

                     

                                print("figure", figure, "figureButton", figuresButton) 

                    figure Figure(selectedFigure: nil, title: "3312", figureName: "SCFigures2") figureButton nil

                     

                                print("item to add", figure.title) 

                    item to add 3312

                     

                    figuresButton.addItem(withTitle:figure.title)

                    Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/wlionelwilliams/Desktop/ScorcentMasterReview/ScorcentMasterReview/FiguresViewController.swift, line 111

                    • Re: Not Loading NSPopupbutton. Why?
                      Claude31 Level 8 Level 8 (7,245 points)

                      I read again your code and found a few things.

                       

                      As for presentation, it is better to have all IBOutlets at the beginning, not scattered in code.

                      And to group all lifecycle methods at the beginning as well.

                      But that's just for ease of reading.

                       

                      More important, that could be cause of error:

                      You declare var figures several times:

                      line 3

                      line 45

                      So, the one defined line 3 is never initialized.

                      Is it intentional ?

                      Same issue probably with selectedFigure

                       

                      Lines 87 to 90.

                      class declaration should be on a new line: that cannot compile as is

                      you have a closing curly brace before super.viewDidLoad ; that cannot compile.

                       

                      So is it the real code ?

                       

                      You should first correct those errors and try again

                        • Re: Not Loading NSPopupbutton. Why?
                          wlionel Level 1 Level 1 (0 points)

                          Hello Claude:

                          In response to your suggestions:

                          "You declare var figures several times: line 3 and 45"

                          I am not sure how to correct this because

                          if I remove from line 3 the following errors arise:

                          Use of unresolved identifier 'figures' on line 50

                           

                          Anywhere "figures" is used outside the

                           

                          struct Figure {

                           

                          line 45"

                          I am not sure how to correct this because if I remove from line 45 the following errors arise:

                          "Instance member 'figures' of type 'FiguresViewController' cannot be used on instance of nested type 'FiguresViewController.Figure'"

                          on the lines 50 - 55

                                                   figures.append(figure) 
                                                  } 
                                                } 
                                              } 
                                              print("Figures is", figures) 
                                              return figures 

                           

                          "class declaration should be on a new line: that cannot compile as is

                          you have a closing curly brace before super.viewDidLoad ; that cannot compile."

                           

                          That was a copying error.

                           

                          The current structure of the code is given below:

                           

                          import Cocoa
                          
                          class FiguresViewController: NSViewController {
                             
                              @IBOutlet weak var figuresButton: NSPopUpButton!
                             
                          
                             var figures = [Figure]()
                              var selectedFigure: Figure?
                              var figureId:String = ""
                             
                              @IBOutlet weak var figureImage: NSImageView!
                             
                              var selectedProduct: Product? {
                                      didSet {
                                        updateUI()
                                        print ("FProcess A")
                                      }
                              }
                              override func viewWillAppear() {
                                   super.viewWillAppear()
                                    
                                   updateUI()
                                 }
                               private func updateUI() {
                                   //1
                                   if isViewLoaded {
                                       if let figure = selectedFigure {
                                         figureImage.image = figure.image
                                         print ("FProcess B")
                                         print ("FProcess D")
                             
                                        
                                       }
                                      
                                     }
                                 }
                             
                              override func viewDidLoad() {
                                  super.viewDidLoad()
                                  if let filePath = Bundle.main.path(forResource: "TFigures", ofType: "plist") {
                                              print("filePath", filePath)
                                              figures = Figure.figuresList(filePath)
                                                  print("figures count", figures.count)
                                                  print ("FProcess G")
                                             }
                                  updateUI()
                                            
                               //             figuresButton.removeAllItems()
                                             print(#function, "figures count", figures.count)
                                            
                                            
                                  for figure in figures {
                                       
                                      print("figure", figure, "figuresButton", figuresButton as Any)
                                      print("item to add", figure.title)
                                      print ("FProcess H")
                                      figuresButton.selectItem(at: 0)
                                      figuresButton.addItem(withTitle:figure.title)
                                     
                                                     }
                                        if title == nil {
                                               print("Title is nil")
                                          } else {
                                              print ("itemsCount", title!.count)
                              }
                             
                          //       selectedFigure = figures [0]
                              }    
                              @IBAction func valueChanged(_ sender: NSPopUpButton) {
                          
                              if let title = sender.selectedItem?.title,
                                  let index = figures.firstIndex(where: {$0.title == title}) {
                                      selectedFigure = figures[index]
                                      print ("FProcess F")
                                  }
                                        }
                          
                              struct Figure {
                             
                                            let title: String
                                            var image: NSImage? {
                                              get {
                                                let i = NSImage(named: figureName)
                                                  print("FProcess J")
                                                return i
                                              }
                                            }
                                   
                                       fileprivate let figureName: String
                                   
                                            static func figuresList(_ filePath: String) -> [Figure] {
                                        var figures = [Figure]()
                                              print ("FProcess K")
                                   
                                              if let figuresList = NSArray(contentsOfFile: filePath) as? [[String: Any]] {
                                                   print("figuresList ##START##", figuresList, "figuresList ##END##")
                                                for dict in figuresList {
                                                if let figure = Figure(dictionary: dict) {
                                                   figures.append(figure)
                                                  print ("FProcess L")
                                                  }
                                                }
                                              }
                                              print("Figures is", figures)
                                              return figures
                                             
                                            }
                                   
                                            init?(dictionary: [String: Any]) {
                                            
                                           guard let title = dictionary["figureId"] as? String,
                                                 let figureName = dictionary["figureName"] as? String else {
                                                   print("Initialization of Product failed with \(dictionary)")
                                                  return nil
                                              }
                                              print("FProcess M")
                                             self.title = title
                                             self.figureName = figureName
                          
                              }
                          }
                              class Figures: NSViewController {
                                  
                                     override func viewDidLoad() {
                                         super.viewDidLoad()
                                      print ("Process C")
                                    
                                         // Do view setup here.
                                        
                                      }
                                     
                                 }
                             
                          }

                           

                          Thanks for your assistance.