We have an app that optionally includes UIKit, and in Xcode 16.3 it builds just fine, but with Xcode 26 it fails because it cannot find UIDefines.h.
Error:
/Applications/Xcode-beta.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS26.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIKitDefines.h:10:9: fatal error: 'UIUtilities/UIDefines.h' file not found
I looked for it, and inside of Xcode 26 there is a new folder(SubFrameworks) inside of the TV Simulator that does not exist in 18 and it only has one thing in that folder and it's UIUtilities.framework.
Reference path: /Applications/Xcode-beta.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/System/Library/SubFrameworks/UIUtilities.framework/
Not sure how to get around this except to put in a bunch of new ifdefines maybe to deal with it, but it is weird that the subframeworks file is part of the issue. Anyone have any ideas besides copying the files over (doesn't work anyway)?
Posts under tvOS tag
93 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Just noticed a bug in tvOS 18+:
If you present a modal (.sheet or similar) that contains a TextField, click into the text field to select your text from keyboard, then press the Back button, the TextField becomes unclickable and we are not able to update the textfield again.
This behavior didn’t happen in tvOS 17, so it seems to be a regression introduced in tvOS 18.3, tested only on silumator
Repro steps:
Present a modal with a TextField
Focus and click the TextField
Press the Back button to dismiss the keyBoard
Try clicking the TextField → nothing happens (and textfield is full white)
If anyone has a workaround, I’d love to hear it!
struct ModalView: View {
@State var text: String = ""
var body: some View {
TextField("", text: $text,
prompt: Text("Prompt"))
}
}
struct ContentView: View {
@State var isModal: Bool = false
var body: some View {
NavigationView {
ZStack {
SwiftUI.Button.init {
isModal = true
} label: {
Text("click")
}
}
}.sheet(isPresented: $isModal) {
ModalView()
}
}
}
I'm working on a media app that would like to be able to tell if the TV connected to tvOS is running at 59.94hz or 60.00hz, so it can optimize a video stream. It looks like the best I can currently do is to check if the user has Match Content Rate enabled, and based on that, when calling displayManager.preferredDisplayCriteria to change video modes, I could guess which rate their TV might be in. It's not very ideal, because not all TVs support both of these rates, and my request for 59.94 might end up as 60 and vice versa.
I dug around and can't find any available method in UIScreen to get this info. The odd thing is, the data is right there in currentMode when I look in the debugger, but it seems to be in a private or undocumented class. Is there any way to get at it?
Building my multiplatform target, works great for iOS, visionOS, MacOS.
tvOS builds fine, if I do not include any of the items in the .xcassets file.
I have attempted to add a second .xcassets file for just tvOS, but Xcode will not detect the second .xcassets if created manually, and will just "spin" when adding via the add file menu option.
If I add tvOS to the target membership for any of the .xcassets items (Xcode applies that target membership for ALL items in the .xcassets) we then we get the distill failed error.
The issue will sporadically be solved by removing the visionOS app icon from the .xcassets file and building that way, but it is not a perfect solution, as it does not work every time.
If there is a more targeted "membership options" that doesn't apply .xcassets wide, that would probably be the simplest solution.
Hi,
I am trying to update an old prototype I made for tvOS using DNSServiceBrowse(). The target was tvOS 17.
My old build from September 2023 still works fine: It can discover computers on the same local network as the Apple TV (simulator).
However, now that I am using Xcode 16, the DNSServiceBrowse() callback (of type DNSServiceBrowseReply) receives the error code: -65570.
The call to DNSServiceBrowse() itself returns no error, neither does the following call to DNSServiceProcessResult() — which actually triggers the call of the callback.
I found nowhere in the Internet any list of possible error codes received by the callback, so I have no idea what it means.
So, my first question is: What does this error code mean? (And is there any list of the possible errors somewehere, with their meaning?)
Since it was a prototype, I have no provisioning profile defined for it. Could that be related to the issue? Since I will make a real app out that prototype (targeting tvOS 18), I will have to define a provisioning profile for it.
Would a provisioning profile for the app solve the issue?
If yes, are there any requirements for that profile that I should take into account to solve the issue?
Thank you in advance for any help,
Marc
Please make sure this feature gets placed back. Parents need a way to provide the ability for kids to watch and not watch at their discretion. The new system doesn’t allow this to happen. Are there any workarounds?
I'm working on a tvOS application that plays video content using TVMLKit/TVJS. I'm trying to integrate Google IMA SDK to show pre-roll, mid-roll, and post-roll ads in my app.
Here’s what I’ve done so far:
Video playback is handled through JavaScript in application.js.
Ads are managed in Swift using Google IMA SDK.
I use the evaluateJavaScript bridge to control video playback from Swift.
I pause and resume the TVJS player (Player object) using a function like startPlayingVideo(value) from Swift based on the ad lifecycle.
Current Flow:
When the video is about to start, I call loadAds() from JS.
This presents a Swift ViewController that handles IMA ad requests.
On adsManagerDidRequestContentPause, I pause the video using JS via the bridge.
On adsManagerDidRequestContentResume, I resume the video.
The Issue:
This setup doesn't behave consistently:
Sometimes the ad plays in the background and video started playing as well but can not see the ad.
Not able to see the post-roll ads
Relevant Code Snippets:
application.js
function startPlayingVideo(value) {
if (playerReference != undefined) {
if (value == true) {
playerReference.play();
else {
playerReference.pause();
}
}
}
function playVideo(videoURL) {
setup playerReference, push mediaItem, etc.
loadAds();
player.present();
}
AppDelegate.swift
let loadAds: @convention(block) () -\> Void = {
DispatchQueue.main.async {
let adManagerVC = ViewController()
AppDelegate.tvController?.navigationController.present(adManagerVC, animated: true)
}
}
let updateVideoPlayTime: @convention(block) (Double) -\> Void = { time in
CustomContentPlayhead.shared.currentTime = TimeInterval(time)
}
ViewController.swift
func adsManagerDidRequestContentPause(\_ adsManager: IMAAdsManager) {
showAdUI()
playerViewController.player?.pause()
}
func adsManagerDidRequestContentResume(\_ adsManager: IMAAdsManager) {
hideAdUI()
// Expecting JS video to resume via bridge
}
And yeah my IMSDK Implementation is working fine if I am using it with swift AVPlayer.
What I Need Help With:
Best practice for coordinating video playback between JS (Player) and Swift (IMAAdsManager).
How can I sync the playhead reliably between JS and Swift?
Is there a better way to pause/resume TVJS player from Swift during ad lifecycle?
How to reliably insert mid-roll ads when the playback is primarily controlled in JS?
Any insights, code examples, or recommended architecture improvements would be greatly appreciated!
ISSUE:
Warning: None of the input catalogs contained a matching App Icon & Top Shelf Image brand assets collection named "AppIcon"
INFORMATION:
So I currently have my app published and it works for iOS, and visionOS. (iPhone, iPad, Mac & Apple Vision Pro)
There is one target for all OS versions.
I have recently updated it to work with tvOS, however upon building I run into the warning listed at the top of this post.
I have the following within the project:
'AppIcon.icon' (from the new icon composer for iOS, macOS and watchOS)
And within .xcassets:
'AppIcon' (which contains the majority of the icons)
'Brand Assets' Folder (created by right click, tvOS, New tvOS App Icon and Top Shelf Image; which contains these icons in layers and the correct sizes)
Brand Assets retains the names created by Xcode, App Icon - App Store, App Icon, Top Shelf Image Wide, Top Shelf Image
In "General" in the target, I have AppIcon, still listed as the AppIcon name.
Adding a second entry here for just tvOS does not resolve my issue, our could be that I do not what to call it so it can properly find it.
QUESTION:
What am I missing so that the build process detects these images properly and completes a successful build for tvOS?
I am assuming I need to add options to the App Icons and Launch Screens area, but what is the name I place here for tvOS?
SCREENSHOTS:
I recently updated to tvOS 26 on my Apple TV 4K (1st generation) and was disappointed to find that apps I restrict no longer appear at all. In earlier versions, restricted apps would still be visible and simply prompt for a passcode — this was much more convenient for adults in the household.
Now, if I restrict apps for my children, they disappear completely. To use them again, I have to go deep into settings, turn restrictions off, and even recreate the passcode each time, which is frustrating and impractical for daily use.
I also tried adding a Kids user account, but most restrictions still apply system-wide. Only the Apple TV app behaves differently between users. This makes switching between parent and child accounts nearly pointless for managing access.
Please consider one or both of the following:
1. Bring back the passcode-on-launch behavior for restricted apps (instead of hiding them).
2. Give each user their own isolated settings environment, like how profiles work on iOS/iPadOS or even a fresh Apple TV—this way, restrictions, home screen, and app access could be personalized.
Families are a huge part of the Apple TV audience, and these recent changes have made it much harder to use the device in a shared household.
Thank you!
I have a music app I'm developing and having a weird issue where I can see now playing info for every other platform than tvOS. As far as I can tell I have correctly configured the MPNowPlayingInfoCenter
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo MPNowPlayingInfoCenter.default().playbackState = .playing
Are there any extra requirements to get my app's now-playing info showing in control center on tvOS? Another strange issue that might be related is I can use the apple TV remote to pause audio but not resume playback, so I feel like there's something I'm missing about registering audio playback on tvOS specifically.
I'm encountering an issue with In-App Purchases on Apple TV (tvOS):
When a user initiates an IAP for the first time, the system prompts them to sign in with their Apple ID, and the purchase proceeds normally.
However, on subsequent purchase attempts, if the Apple ID session has expired or additional verification is required, the system redirects the user to the Settings app to sign in again.
After the user signs in via Settings, the app does not automatically return to the foreground. The user must manually press the Menu button to come back.
Is this is the normal behaviour of apple tv for InApp purchase? or did I need any code improvement to solve this?
What I'm trying to achieve:
I'd like the app to automatically return to the foreground once the user has completed the Apple ID login in Settings. Is this behavior supported on tvOS? If not, is there any known workaround or best practice to guide the user back to the app smoothly?
Any advice or guidance from Apple or other developers would be greatly appreciated!
Hi Apple Developer Team,
In my tvOS app built with SwiftUI, I have a tab-based interface with several sections. The first tab (index 0) is the Home tab. Other tabs include Contact, WiFi, Welcome, etc.
I want to handle the remote's Menu / Back button (.onExitCommand) so that:
If the user is on any tab other than Home (tabs 1, 2, 3, etc.), pressing the Menu button takes them back to the Home tab.
If the user is already on the Home tab, then pressing the TV/Home button (not Menu) behaves as expected — suspending or exiting the app (handled by the system, no code involved).
Here's a simplified version of what I implemented:
.onExitCommand {
if selectedTab != 0 {
selectedTab = 0
focusedTab = 0
} else {
// Let system handle the exit when user presses the TV/Home button
}
}
This behavior ensures users don’t accidentally exit the app when they're browsing other tabs, and provides a consistent navigation experience.
Question:
Is this an acceptable and App Store-compliant use of .onExitCommand on tvOS?
I'm not calling exit(0) or trying to force-terminate the app — just using .onExitCommand for in-app navigation purposes.
Any official guidance or best practices would be greatly appreciated!
Thanks,
Prashant
Summary:
When using the new .focused modifier to track focus within a large LazyVStack or LazyHStack, we observe a major frame-rate drop and stuttering on Apple TV (1st and 2nd generation).
Steps to Reproduce:
Create a LazyVStack (or LazyHStack) displaying a substantial list of data models (e.g., 100+ GroupData items).
Attach the .focused(::) modifier to each row, binding to an @FocusState variable of the same model type.
Build and run on an Apple TV device or simulator.
Scroll through the list using the remote.
static func == (lhs: GroupData, rhs: GroupData) -> Bool {
lhs.id == rhs.id
}
var id: String
var name: String
var subName: String
var subGroup: [GroupData] = []
var logo: URL?
}
struct TestView: View {
@FocusState var focusedGroup: GroupData?
let groupsArr: [GroupData]
var body: some View {
ScrollView {
LazyVStack {
ForEach(groupsArr, id: \.id) { group in
Button {
} label: {
GroupTestView(group: group)
}
.id(group.id)
.focused($focusedGroup, equals: group)
}
}
}
}
}
struct GroupTestView: View {
let group: GroupData
var body: some View {
HStack {
KFImage.url(group.logo)
.placeholder {
Image(systemName: "photo")
.opacity(0.2)
.imageScale(.large)
}
.resizable()
.scaledToFit()
.frame(width: 70)
VStack {
Text(group.name)
Text(group.subName)
}
}
}
}
Expected Behavior
Scrolling remains smooth (60 fps) regardless of list size.
Focus updates without introducing visible lag.
Observed Behavior
Frame rate drops significantly when .focused is applied.
Scrolling becomes visibly laggy, especially on older Apple TV hardware.
Even when binding an @FocusState<String?> (storing only the id), performance improves slightly but remains suboptimal.
Workarounds Tried
Switched to @FocusState of type String to track only the ID of each group, this has helped but there is still a big performance decrease.
Minimised view-body complexity and removed other modifiers.
Verified that excluding .focused entirely restores smooth scrolling.
Any guidance or suggestions would be greatly appreciated.
I've been looking for a solution to configure the Apple TV remote(s) from the 5th generation and upwards.
Some of the basic functionalities are disabling buttons on the physical remote control while maintaining proper functionality on remote controller apps on iOS devices.
There seems to be a lack of relevant entitlements in that category, and without it I can't seem to figure out a way to make it work.
Any ideas on the matter?
Maybe a workaround that allows to configure the Apple TV to work with other remotes?
Thank you in advance to anyone that put in thought to my query.
Hi,
Having a weird issue that I’m noticing on Apple TVs with some apps that are by the same company. I think it’s storing residual user data if if you delete the app and all other apps relating to this. I have even tried deleting every app and reinstalling but we found two apps to be still logged in. Seams like a sandboxing bug and I presume it’s to do with App data stored in the shared app groups.
I can only reset the apple tv to remove the user data. The two apps we can see are being persistent is Binge and Kayo by streamotion.
We have tried problem solving this in every way imaginable but it’s Interesting that this is allowed to happen on an Apple platform. There is no active user logged into the apple TV with an Apple ID either
When attempting to replicate the tvOS Settings menu layout, where the screen is divided horizontally into two sections, placing a NavigationStack or a Form view on either side of the screen causes focusable views (such as Button, TextField, Toggle, etc.) to be visually clipped when they receive focus and apply the default scaling animation.
Specifically:
If the Form or NavigationStack is placed on the right side, the left edge of the focused view gets clipped.
If placed on the left side, the right edge of the focused view gets clipped.
This issue affects any focusable child view inside the Form or NavigationStack when focus scaling is triggered.
Example code:
struct TVAppMenuMainView: View {
var body: some View {
VStack {
Text("Settings Menu")
.font(.title)
HStack {
VStack {
Text("Left Pane")
}
.frame(width: UIScreen.main.bounds.width * 0.4) // represents only 40% of the screen
.frame(maxHeight: .infinity)
.padding(.bottom)
Divider()
NavigationStack {
Form { // All the buttons will get cut on the left side when each button is focused
Button("First Button"){}
Button("Second Button"){}
Button("Third Button"){}
Button("Forth Button"){}
}
}
}
.frame(maxHeight: .infinity)
.frame(maxWidth: .infinity)
}
.background(.ultraThickMaterial)
}
}
How it looks:
What I have tried:
.clipped modifiers
.ignoresSafeArea
Modifying the size manually
Using just a ScrollView with VStack works as intended, but as soon as NavigationStack or Form are added, the buttons get clipped.
This was tested on the latest 18.5 tvOS BETA
Hello,
We are working on a real-time 2-player online game targeting multiple Apple devices. The following issue only occurs on tvOS:
When selecting matchmaking to connect with another player, the native Game Center interface opens and begins the matchmaking process.
Almost immediately, the following log appears in the console, and the matchmaking screen remains indefinitely without completing:
Timeout while starting matching with request: <GKMatchRequestInternal 0x30d62f690> {
defaultNumberOfPlayers : 0
isLateJoin : 0
localPlayerID : U:bea182d69b85f0839e3958742fbc4609
matchType : 0
maxPlayers : 2
minPlayers : 2
playerAttributes : 4294967295
playerGroup : 1
preloadedMatch : 0
recipientPlayerIDs : <__NSArrayM 0x3034ed5c0> {}
recipients : <__NSArrayM 0x3034ee280> {}
restrictToAutomatch : 0
version : 1
archivedSharePlayInviteeTokensFromProgrammaticInvite, inviteMessage, localizableInviteMessage, messagesBasedRecipients, properties, queueName, recipientProperties, rid, sessionToken : (null)
} . Error: (null)
However, the task does not complete when the log appears (our Debug.Log are nerver called).
But if we manually cancel the matchmaking process, the "User cancel" log is correctly triggered.
Here is a code snippet for the request :
var gkMatchRequest = GKMatchRequest.Init();
gkMatchRequest.MinPlayers = 2;
gkMatchRequest.MaxPlayers = 2;
var matchRequestTask = GKMatchmakerViewController.Request(gkMatchRequest);
matchRequestTask.ContinueWith(t => { Debug.LogException(t.Exception); }, TaskContinuationOptions.OnlyOnFaulted);
matchRequestTask.ContinueWith(t => { Debug.LogInfo("User cancel"); }, TaskContinuationOptions.OnlyOnCanceled);
matchRequestTask.ContinueWith(t => { Debug.LogInfo("Success"); }, TaskContinuationOptions.OnlyOnRanToCompletion);
We have tested this on multiple devices and network types (Wi-Fi, 5G, Ethernet), but we consistently encounter this bug along with the same log message.
Could you please help us understand or resolve this issue?
Thank you.
Hello !
We are working on a real-time 2-player online game targeting multiple Apple devices.
The following issue only occurs on tvOS:
When selecting matchmaking to connect with another random player, the native Game Center interface opens and begins the matchmaking process.
Almost immediately after clicking "start", the following log appears in the console, and the matchmaking screen remains indefinitely without completing:
Timeout while starting matching with request: <GKMatchRequestInternal 0x30d62f690> {
defaultNumberOfPlayers : 0
isLateJoin : 0
localPlayerID : U:bea182d69b85f0839e3958742fbc4609
matchType : 0
maxPlayers : 2
minPlayers : 2
playerAttributes : 4294967295
playerGroup : 1
preloadedMatch : 0
recipientPlayerIDs : <__NSArrayM 0x3034ed5c0> {}
recipients : <__NSArrayM 0x3034ee280> {}
restrictToAutomatch : 0
version : 1
archivedSharePlayInviteeTokensFromProgrammaticInvite, inviteMessage, localizableInviteMessage, messagesBasedRecipients, properties, queueName, recipientProperties, rid, sessionToken : (null)
} . Error: (null)
However, as shown in the code snippet below, the task does not complete when the log appears. But when we manually cancel the matchmaking process, the "User cancel" log is correctly triggered.
var gkMatchRequest = GKMatchRequest.Init();
gkMatchRequest.MinPlayers = 2;
gkMatchRequest.MaxPlayers = 2;
var matchRequestTask = GKMatchmakerViewController.Request(gkMatchRequest);
matchRequestTask.ContinueWith(t => { Debug.LogException(t.Exception); }, TaskContinuationOptions.OnlyOnFaulted);
matchRequestTask.ContinueWith(t => { Debug.Log("User cancel"); }, TaskContinuationOptions.OnlyOnCanceled);
matchRequestTask.ContinueWith(t => { Debug.Log("Success"); }, TaskContinuationOptions.OnlyOnRanToCompletion);
We have tested this on multiple Apple TV and network types (Wi-Fi, 5G, Ethernet), but we consistently encounter this bug along with the same log message.
Could you please help us understand or resolve this issue?
Thank you.
When running UITests on tvOS, tabBar viewIdentifiers (UIKit) are no longer appearing. When you run the test, accessibility identifiers for tabs are no longer locatable but all other identifiers appears except for the tabs in the tabBar. In the stack trace of the debugger, if I print application, I can see all existing viewIdentifiers except those that were set for the tabs (on tvOS only).
If I force an action on the simulator after the app has launched and the view appeared ie move left or right, the identifiers appears (confirmed by stack trace) and the test will continue as expected. This was not an issue in the past (no code changes). I am not sure if this appeared after updating my mac to Sequoia. But for iOS, there is no issue. This bug only appears on tvOS and specifically the tabs.
Issue persists on:
Sequoia 15.4.1
Xcode 16.3
Hi,
This maybe somewhat confusing, but please bear with me.
I currently have an app in the App Store that supports iOS and tvOS. But the tvOS version was a separate app during the development process. I'd like to combine the iOS and tvOS app into one project so its easier to handle and keep track of internally.
Can I upload the new Apple TV version to the same place where the current one is, or would I have to delete the current Apple TV version before uploading the newly combined version?
I hope I made that clear enough :-)
Thank you,
Dan Uff