iOS 10 Today View Widget: How to tell if it's *actually* on screen / visible?
Asked Answered
L

2

9

I have a widget which retrieves updates from a server at regular intervals throughout the day, but want it to immediately update again if the user actually looks at it. This always worked fine in iOS 8/9... viewWillAppear fired specifically when, well, the view was about to appear.

But in iOS 10, it seems to happen at other times as well. Not sure when. But suddenly I'm getting about 5x as many hits on the update service, which is a paid service, so this is a real problem.

Is there a way, on a Today widget, to be guaranteed that the widget is actually visible? Or, at the very least, that the Today View is actually visible?

Lubberly answered 22/10, 2016 at 13:38 Comment(5)
I just created a Today Widget myself and checked it on iPhone 5s(10.1). Whenever I opened the widget section to view my widget, both viewDidLoad() and viewDidAppear() are called, but only once. Apart from this situation, you said other times. What are those other scenarios? Can you please tell me so that I can look into itColombi
I can't seem to figure out when or why - just that fairly often if I open up the widget, it has clearly updated very recently despite my not having opened it.Lubberly
I believe that you used breakpoints in viewDidLoad() and viewDidAppear() to observe the info. If not, can you check it by setting breakpoints. You might be able to find out a specific scenario by debugging it. Otherwise, can you please post relevant code for others to observe?Colombi
Will give it a try when I get home tonight... maybe I just need to leave it connected to the debugger for a while while I do other things on the phone and see what happens...Lubberly
Hi, did you have any luck with debugging yesterday?Colombi
P
6

I'd bet that the 5x as many hits is because of how users unlock their devices on iOS 10 now. Swiping from the lock screen shows the users widgets instead of unlocking their device. If you're requesting in your viewWillAppear then every time a users muscle memory tries to unlock the device the old way, by swiping, your widget is sending a server request. You might want to setup a timer for the request, or add a refresh button.

Precipitate answered 4/11, 2016 at 11:59 Comment(4)
Now that's an interesting thought... incidentally that change drives me absolutely insane. Will give that a try.Lubberly
Is it possible to check whether it's currently visible / onscreen? If so, the timer idea will work. (sorry for the slow reply -- was out for the weekend)Lubberly
@Lubberly I haven't tested but I'd imagine viewWillAppear and viewWillDisappear would be what you're after. I know widget life cycles are a little unpredictable sometimes. I'll try to test it out sometime this week and will update my answer depending on what I find.Precipitate
This seems to do the trick relatively well; setting up a timer in viewWillAppear for a quarter second, and then cancelling it in viewWillDisappear. Thanks!Lubberly
L
2

I think you really need to rethink this one, and I disagree strongly with the advice you've been given so far. Let me explain:

  • I never used to use widgets, but as of iOS 10, I now use them all the time. I don't think I'm the only one - they're much more front and centre, and easier to get to. I'd say that a very large chunk of the 5x is people that genuinely use your widget a lot more now.

  • Although people do unlock their device the old way still, it's just a habit that people will grow out of very soon, if they haven't already. I don't think modifying your widget to respond to a short term habit is a good idea.

  • Most other widgets refresh automatically, so adding a refresh button goes against good UI, what people expect, and how Apple intends widgets to work. Trying to fight the system isn't a good idea. Adding a refresh button goes against the idea of widgets being a super quick way to see updates.

As a solution, I think you need to look at different server options (AWS is incredibly cheap). Look at the data you're sending - see if you can decrease the size, or only send data that has changed. Add a minimum refresh time, i.e. don't refresh multiple times within 10 mins. If you're not already, look at monetising your app by adding some small but genuinely useful premium features to offset server costs.

Lati answered 8/11, 2016 at 21:27 Comment(3)
Great points. I was more focused on answering the question than thinking of a better solution. +1Precipitate
Hi - sorry for the slow response... The problem is it's using a paid weather service (Dark Sky API), which has a cost per use over a certain level of free uses. Caching on my own server is the ideal solution if I wind up with high volume (a LOT more people using the widget), but it's not enough at my current # of users. Will see.Lubberly
All good, understand your predicament. Unfortunately, I'm still sticking by what I said - I think more people are genuinely using your widget. If putting a 1/4 second delay like @DanielStorm 's answer mentions doesn't make a big enough impact, you need to think outside the box. Different weather API, caching on your own service like you suggest, rate limiting. Also, looking at the DarkSky website... it's only $0.0001 per weather forecast. I don't think it's going to cost you much, if your widget is used enough for this to be an issue, then this is probably quite a good problem to have :)Lati

© 2022 - 2024 — McMap. All rights reserved.