Keeping the score off every screen: building Hide Scores
A customer emailed to say he couldn't find a way to hide scores. He was right, and it was worse than hard to find. The only switch was buried inside Notification Settings, it was labeled "Hide scores in notifications and widgets", and that's all it did. The game list, the detail sheet, the Live Activity on the lock screen, Siri and Spotlight all ignored it.
That's the problem with a spoiler mode. If you're recording a game to watch at ten, one screen that shows the result is the same as every screen showing it. So I rebuilt it as Hide Scores, a top-level setting that has to hold everywhere the app can draw a game. This is how that went. If you just want to use it, here's how to turn it on.
A spoiler is more than a score
Before writing any code I went through the app looking for everything that gives away how a game went. The digits were the easy part. The rest was everywhere:
- Labels like Comeback, Upset and Walk-off.
- How a game ended. "Final/OT" tells you it was tied late.
- Write-ups, including pre-game ones that cite earlier games, like "Vegas won Game 1, 3-1".
- Records, series lines like "leads 3-1", recent form and past meetings.
- Who's dimmed as the loser, win probability, the box score, goal scorers, red cards.
So I wrote one rule for every surface, which I called the spoiler standard. Hidden until you choose to see it: scores, who leads or won, direction labels, live and post-game write-ups, the stats, any extra-period marker on a final, and anything built from earlier results. Kept on purpose: the Lineup score, which games are worth watching and in what order, live closeness signals like Close game or Overtime, and the fact that an alert arrived. Those tell you a game is worth your evening. They don't tell you who won it.
That second list is the whole point of the app. Hide Scores can't turn it into a blank screen, or there's no reason to open it.
Leaks that were already live
Some of what I found leaked even for people who had the old switch on. I fixed those first, in a server-only change that didn't need an app update.
A rain delay rewrote the preview. When a game paused mid-way, a template replaced the pre-game write-up with something like "In a rain delay at NYY 3, BOS 1". Spoiler-safe share cards read that pre-game text, so they printed the score. Now the delay copy only replaces the preview before first pitch. Once a game starts, the pre-game text is left alone.
A "spoiler-safe" alert gave away the game. The safe version of the comeback alert said "A comeback is on". No score, but a delayed viewer now knows someone fell well behind. It uses the close-game wording instead.
The game-start alert carried the preview. That preview could cite earlier results. In spoiler-safe mode the start alert skips it.
A race Live Activity sent the podium. During the window where a race result is supposed to be hidden, the lock-screen card still received the podium and the final write-up. It doesn't anymore.
One reveal, everywhere
The first design question was what happens when you tap a hidden game. One option was to let the first tap show the score. I rejected it. A spoiler mode fails the moment just moving around the app reveals something.
So a tap always opens the game. A hidden game opens in a pre-game form: where to watch, the Lineup score, the forecast, who's out. The score slot becomes a labeled Show score button, on the card and in the header of the detail sheet.
When you press it, that game is revealed everywhere, not just on the screen you pressed it on. The card, the detail sheet, the Live Activity and the widgets all show it. The app and its extensions share one App Group, so a reveal is written once and read by every surface. Widgets get a nudge to redraw:
let shared = UserDefaults(suiteName: "group.example.app")
shared?.set(revealedData, forKey: "revealed")
WidgetCenter.shared.reloadAllTimelines()
Reveals stay on the phone. They never go to the server, so anything the server writes stays score-free. If the two disagree, the server text is the safe one, which is the right direction to be wrong in.
The settings screen has a master switch, "Hide scores everywhere", and four switches under it: In the app, Live Activities, Notifications and Widgets. The master isn't stored. It's on when all four are on. People who had the old switch on got Notifications and Widgets on and nothing else, which is what their label had promised.
Surface by surface
The app
Cards lost loser dimming, penalties, scorers, sets and leaderboards while hidden. Finals read "Final", never "Final/OT". The one-line summary under a card became the game's stakes, a live "Close game", or the rating's phrase. VoiceOver stopped announcing a winner. Share cards follow the same switch, which fixed a hidden final printing the result sentence, the overtime marker and the next series game.
History before kickoff
A game that hasn't started has no score to hide, but its detail sheet still told you how earlier games went. Form, past meetings and the series now sit behind one "Recent results hidden" cover that you can open per game. A two-legged cup tie's name lost its aggregate, so "leads 2-1 on aggregate" doesn't show up on the card before the second leg.
Pre-game write-ups had the same problem: they cite earlier results. The spoiler-free preview is written on the phone from facts no result can change, like who's playing, where, the stage of the competition, the starters and who's out. Anything that comes back with a result word or a number it wasn't given gets thrown away. If there's no safe preview, there's no preview. It never falls back to a write-up that might mention a result.
The Live Activity
This was the hardest one, because two things draw it. The server pushes updates, and the app draws the card from what arrives. A push can leave keys out, and the app fills them back in from the last state it saved, so cleaning the payload isn't enough. The app redacts once, at the moment it draws, for every started game you haven't revealed. That covers the Lock Screen, Dynamic Island, Smart Stack and CarPlay.
The server does its half too. Your Live Activities switch travels with the card's push token, and for those cards the server writes score-free text. Start alerts carry the clock, not the score. The verdict on a finished card reads "It's final — tap to see how it ended". Moment chips are closeness only. The app only shows the verdict and why-line when the server has marked the card as written score-free.
Widgets, Siri and Spotlight
The widget status helper said it was spoiler-safe as is. It wasn't: it showed "Final/OT". Hidden widgets now say "Final", drop the series and records line, and show no write-up at all. Siri used to answer "Celtics won 112 to 108". With Hide Scores on, it says "Knicks at Celtics is over". Spotlight's index drops scores and results, and it rebuilds whenever a switch or a reveal changes.
The long-press notification
The expanded notification card showed team records and "Final/OT" even when the alert itself was spoiler-safe. Both are gone when the alert is marked safe.
What I left alone
Playoff games marked "if necessary" stay as the schedule has them. I looked at holding them in place so a vanishing Game 6 couldn't spoil Game 5, and decided against it. The schedule itself says whether a series went on, so I left it to say so.
Hide Scores is free, it's off by default, and it covers every game, not just your teams. The bar I set was simple: with it on, nothing on any screen tells you who won until you ask. You still know exactly which games are worth watching.
The Lineup Is is an iPhone app that ranks every game by whether it's worth watching, with alerts, a self-starting Live Activity, widgets, Siri and Hide Scores.
Get The Lineup Is on iOS — free — or see tonight's best games ranked right now. More from the blog.