Todd
Todd

Reputation: 1953

Today Widget unable to load with a specific line of code

I've added a Today extension to my app and it all works fine until a specific line of code is compiled. NB: compiled, not executed!

My TodayViewController is:

class StoredDoses {
 func getDoses(doses: inout [Dose]) {
  if let userD = UserDefaults(suiteName: "com.btv.mySuite") {
   if let dosesData = userD.object(forKey: "doses_key") {
    do {
     // -----------------------------------------------
     // Comment the line below out and the widget works
     doses = try PropertyListDecoder().decode([Dose].self, from: dosesData as! Data)
     // -----------------------------------------------
    } catch {
      print ("ERROR")
    }
   }
  }
 }
}

class TodayViewController: UIViewController, NCWidgetProviding {

 @IBOutlet weak var aText: UILabel!
 @IBOutlet weak var bText: UILabel!

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

 func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
  // Perform any setup necessary in order to update the view.

  // If an error is encountered, use NCUpdateResult.Failed
  // If there's no update required, use NCUpdateResult.NoData
  // If there's an update, use NCUpdateResult.NewData

  //Just for development stage - not real, final code
  let form = DateFormatter()
  form.timeStyle = .short
  aText.text = form.string(from: Date())

  completionHandler(NCUpdateResult.newData)
 }
}

So, the above code isn't well written, but it's what I've used to finally narrow down the cause of the unloading widget. The array of Doses is a custom, codable class, but if I try to get an array of String then it's the same. The StoredDoses code is included in the main app and doesn't cause any problems.

Just to re-iterate: I'm not trying to execute any method in the StoredDoses class. I don't even have an instance of it in the widget. When the doses = ... line is merely commented out then the widget loads and the aText label in the widget appears with the current time in it.

Upvotes: 1

Views: 217

Answers (1)

Todd
Todd

Reputation: 1953

Ok, so thanks to @Chris' apparently unconnected advise I got it sorted!

It appears to have been an Interface Builder issue: somehow it had retained the original name of the UILabel that was auto-created when I added the Today extension in Xcode. At some point, after connecting an IBOutlet to the label with "Hello World" in it, I'd renamed it to something slightly more relevant but hadn't unconnected it before over-typing the new name in the TodayViewController.

The console didn't throw up any problems and at times seemed to work, but when the line with

try PropertyListDecoder().decode([Dose].self, from: dosesData as! Data)

was present then it stopped working without any console messages.

I only found that out after I explored @Chris comment about the as! Data. I re-wrote to first get the Data:

if let userD = UserDefaults(suiteName: "com.btv.mySuite") {
  if let dosesData = userD.object(forKey: "doses_key") {
     if let unwrappedData = dosesData as? Data {
       do {
           doses = try PropertyListDecoder().decode([SplitDose].self, from: unwrappedData)
       } catch {
         doses.removeAll()
       }
     }
  }
}

Once this was compiled (remember, it's still not being executed - this is just sitting there waiting to be used) the console threw up a message and the app crashed out showing the old UILabel name as not key-compliant. Reconnecting the UILabel in IB fixed everything and I could compile the original code....

This probably deserves a Radar entry but right now I don't want to waste another day re-creating (if at all possible) this problem!

Upvotes: 1

Related Questions