Search code examples
iosswiftuitableviewtoday-extension

today extension shows "unable to load" after button event (iOS)


Good morning!

I have an "unable to load" problem in my iOS widget. I've read a lot of about the "unable to load" message but nothing fixed my problem. I'm not sure but I think my problem is to refresh the widget after changing my content.

My widget has one button and one label. If the user press the button the text from the label will changed - in this moment the widget shows "unable to load". Just a milisecond after pressing the button.

import UIKit
import NotificationCenter

class TodayViewController: UIViewController, NCWidgetProviding {

    @IBOutlet var segment_att: UISegmentedControl!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {

        completionHandler(NCUpdateResult.NewData)
    }

    func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets {
        return UIEdgeInsetsZero
    }

    @IBAction func button_ae(sender: AnyObject) {
       let tableviewclass = TodayTableViewController()
       tableviewclass.newData()
    }

}

Important is that the label is shown in a TableViewCell of a TableViewController. So the TableViewController is embeded in the ViewController within a Container... The listener from the button call the method newdata() of the file of the TableViewController.

import UIKit
import NotificationCenter

class TodayTableViewController: UITableViewController, NCWidgetProviding {

    @IBOutlet var table: UITableView!
    @IBOutlet var label1: UILabel!


    override func viewDidLoad() {
        super.viewDidLoad()
        init()
    }

    func init() {
        let meldung: String = "test"
        label1.text = meldung
    }

    func newData() {
        let meldung: String = "new test"
        label1.text = meldung
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }    

}

The code is really simple and basic - so I'm wondering about the problem in this simple mechanism. I hope you can help me!

Thanks at all!


Solution

  • Your code assumes that label1 has been set when newData() is called, even immediately after the constructor is called.

    Try using this optional chaining syntax instead, which will quietly fail if the property is nil:

    import UIKit
    import NotificationCenter
    
    class TodayTableViewController: UITableViewController, NCWidgetProviding {
    
        @IBOutlet var table: UITableView!
        @IBOutlet var label1: UILabel!
    
        var meldung: String = "test"     // <-- meldung is property
    
        override func viewDidLoad() {
            super.viewDidLoad()
            init()
        }
    
        func init() {
            label1?.text = melding       // <-- optional chaining
        }
    
        func newData() {
            melding = "new test"         // <-- set the class property
            label1?.text = meldung       // <-- optional chaining
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }    
    
    }
    

    and instead of calling newData(), you might instead just set the meldung property, e.g.:

    tableviewclass.meldung = "new test"
    

    as your viewDidLoad() will take care of setting the UILabel text from the property