tvOS has no Local Network permission prompt

My tvOS app (AmbientCast, which watches a 3D printer's camera) talks to hardware on the same Wi-Fi network: an RTSP camera stream, an MQTT broker, and a multicast discovery probe to find the printer in the first place. So the target declared NSLocalNetworkUsageDescription, the way an iOS target would.

No prompt ever appeared. That did not look like a problem — plenty of permissions get granted once and never asked again, and the networking worked. What it did instead was supply an explanation for something else. Connections at launch sometimes sat in NWConnection's .waiting state for a few seconds, and two comments in my networking code said why: the user had not answered the Local Network prompt yet.

There is no prompt. There has never been one on this platform, and the key I had declared could not be displayed by anything on an Apple TV.

The answer is one row of one table

Apple's TN3179, Understanding local network privacy, lists the platforms that have the feature. Both absences are the interesting part:

Platform    Supported   Introduced
iOS         yes         iOS 14
iPadOS      yes         iPadOS 14
macOS       yes         macOS 15
tvOS        no          -
visionOS    yes         visionOS 1
watchOS     no          -

tvOS and watchOS do not have local network privacy. Not "it is granted automatically", not "it prompts somewhere else" — the mechanism is absent, so there is no privilege, no alert, and nothing in Settings. The same technote notes separately that "The simulator doesn’t support local network privacy." That one bites iOS developers; the table above is the tvOS version of the same surprise.

ELI5: what's a purpose string?

A sentence you put in your app's settings file explaining why you want access to something private — the camera, contacts, the local network. When the system asks the user for permission, your sentence is the text in the dialog. No dialog, nothing to read it.

The key's own documentation disagrees

Here is why this is easy to get wrong rather than careless. The reference page for NSLocalNetworkUsageDescription carries an availability badge reading tvOS 14.0+, and its description is two sentences: "Any app that uses the local network, directly or indirectly, should include this description. This includes apps that use Bonjour and services implemented with Bonjour, as well as direct unicast or multicast connections to local hosts." My app makes unicast and multicast connections to local hosts. I included the description.

NSBonjourServices says tvOS 14.0+ too. So two plist keys advertise themselves as available on a platform that the technote governing them says has nothing to configure. The key reference is the page you land on from a search for the key name. The technote is the page that is right.

The multicast side is at least consistent. TN3179 scopes it explicitly — "Additionally, if your iOS app performs multicast operations, sign it with the com.apple.developer.networking.multicast entitlement" — and adds that "The multicast entitlement isn’t required on macOS." On tvOS you need neither it nor the purpose string.

ELI5: what's multicast discovery?

Shouting into a room instead of calling someone by name. An app sends one message to a special address that every device on the network is listening to, and whatever it was looking for answers. It is how an app finds a printer or a speaker without being told its address first.

What the declared key cost

Nothing, directly. It is inert. The cost was that it read as evidence.

A purpose string in the bundle is a statement that the thing it configures exists. So when a connection sat in .waiting at launch, "the permission prompt hasn't been answered" was a tidy explanation standing right next to a key that appeared to confirm it. That comment lived in my code for nearly three months, in the one file someone would open to decide whether the patience was still needed.

The direction that makes it dangerous is the correction, not the error. .waiting at tvOS launch is real — it is Wi-Fi associating or DNS settling after the device wakes, and the connection does reach .ready on its own. Learning that tvOS has no prompt reads as an argument for deleting the timeout that bounds the wait. That timeout is the thing standing between an unreachable host and a connect call that hangs forever.

What actually happens on tvOS is simpler than the permission story. The app's discovery joins its multicast group and finds the printer about a second after launch. With the key removed, a 33-minute run on the Apple TV heard both printers announcing themselves every few seconds. There is nothing to grant and no state to check, which cuts both ways: you cannot be denied, and you cannot ask.

The same thing had happened with App Transport Security

The tvOS target also carried an NSAppTransportSecurity dictionary with NSAllowsLocalNetworking in it, justified by the printer's video and a diagnostic stream URL. Checking that turned out to be the same exercise twice.

Neither NSAppTransportSecurity nor NSAllowsLocalNetworking lists tvOS in its availability at all — iOS, iPadOS, macOS and visionOS only. And ATS is described as changing "the default security for HTTP connections". The camera and the broker are not HTTP: both are raw NWConnection sockets rather than URLSession requests.

ELI5: what's App Transport Security?

A rule Apple applies to an app's web requests: use HTTPS, with a modern enough encryption setup, or the request fails. Apps that genuinely need an exception declare it in the settings file. It governs web-style requests, not every byte an app puts on the network.

That was still reasoning, so I measured it. A release build with the dictionary removed, installed on a physical Apple TV 4K running tvOS 27, against a live camera: the app's local HLS server served 98 and 99 requests per minute against a 97-to-100 baseline, Picture in Picture became available 13 seconds after launch, and the log recorded no transport errors. The iOS target has never declared the key and drives the same loopback player. It was load-bearing for nothing.

What I'd tell you to check first

If you are porting something that talks to hardware on the LAN:

The general version: a configuration key is not an observation. I had a purpose string, a plausible symptom and a documented API, and the three of them agreed with each other for nearly three months without any of them being checked against the platform. The thing that settled it was a table with a "no" in it, which no amount of reading my own code was going to produce.

Somebody asked this on the Apple Developer Forums in July 2021 — "Also there seems to be no 'local networking' permission dialog in tvOS - is that also correct?" — in a thread that is otherwise about a UDP port. An Apple engineer answered the multicast half and never that sentence. It is still unanswered, which is some of why this post exists: at the time, the technote carrying the table had not yet been published under its current name.