Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS - Today extension widget cleared over time

Situation as it should be

Proper situation

We have a today widget that shows a maximum of 6 buttons depending on data set in the corresponding app. This data is shared using app-groups. If at least one button is configured it will show up as shown in the image above. If the user is not logged in, or if no buttons are configured, it will show a message as shown in the image below.

No buttons configured

Problem

After several hours (somewhere between 4 and 7) of not having opened the app, the widget reverts to the 'No buttons configured' view.

Analysis so far

The way the data is loaded from the app-group is done using the code as shown below. (gist for full code) In the way I had written it, the only way the 'No buttons configured' view can be shown is if the buttons array actually exists but has a length of zero.

I expected something like a cache clearing or a background service stopping, but as far as I can see, exceptions should be caught earlier:

  • If no connection could be made to the app-group data, userDefaults should be nil, so it should show the 'Not logged in view'.
  • In case the buttons were never defined, buttons should be nil and so again it should show the 'Not logged in view'

Considering the app does nothing in the background, the app itself could not be changing the buttons.

I tried reproducing this while having the debugger connected, but the problem will not reproduce.

Does anyone even have the slightest idea on how to fix this issue or how to start debugging this?

Relevant files:

  • TodayViewController
  • Cordova Plugin

Relevant code:

private struct sharedData {
        static var baseUrl: String?
        static var token: String?
        static var phoneDeviceId: String?
        static var buttons: Array<Button>?
    }

func loadData() {
        let groupIdentifier = "group." + NSBundle.mainBundle().bundleIdentifier!
        var groupIdArray = groupIdentifier.componentsSeparatedByString(".")
        groupIdArray.removeAtIndex(groupIdArray.count - 1)
        let appGroupIdentifier = groupIdArray.joinWithSeparator(".");

        let userDefaults = NSUserDefaults.init(suiteName: appGroupIdentifier)
        if (userDefaults == nil) {
            print("Error in user defaults")
            setButtonTitle("Not logged in. Open Triggi to continue.")
            return false
        }
        sharedData.baseUrl = userDefaults?.valueForKey("baseUrl") as? String
        sharedData.token = userDefaults?.valueForKey("token") as? String
        sharedData.phoneDeviceId = userDefaults?.valueForKey("phoneDeviceId") as? String
        let buttons = userDefaults?.valueForKey("buttons") as? NSArray

        if (sharedData.baseUrl == nil || sharedData.token == nil || sharedData.phoneDeviceId == nil || buttons == nil) {
            print("Missing data")
            setButtonTitle("Not logged in. Open Triggi to continue.")
            return false
        }

        if (buttons?.count == 0) {
            print("No buttons configured")
            setButtonTitle("No buttons configured. Open Triggi to continue.")
            return false;
        }

    // More things are done with the data here
}
like image 662
Remy Kabel Avatar asked Jun 08 '17 11:06

Remy Kabel


1 Answers

Today Extension Controller is a UIViewController and thus follows the same lifecycle as that of a UIViewController. So, the lifecycle method viewDidLoad() is called everytime whenever the widget is loaded.

Also, widgetPerformUpdateWithCompletionHandler is called:

  1. when widget is updated in background
  2. before widget snapshot is taken

So, instead of just calling loadData() in widgetPerformUpdateWithCompletionHandler, also call it from viewDidLoad().

Also, where have you written the code to add/remove UIButtons from superview and to show "No buttons configured" in your code?

like image 158
PGDev Avatar answered Nov 07 '22 10:11

PGDev