I am using Apple's original Lightning Digital AV-adapter (Lightning-to-HDMI dongle) to connect my iPhone to an external display via a HDMI cable.
I need to synchronize rendering with the external display's refresh rate, so I create a new CADisplayLink tied to the external display's UIScreen: UIScreen.screens[externalDisplayIdx].displayLink(withTarget:, selector:).
The callback is being called regularly, but with increasing delay relative to the CADisplayLink.timestamp, so the next time the callback is called, I have less and less time to draw the next frame (see the snippet below).
Assuming 60 FPS, the value of secondsTillDeadline starts at an arbitrary value in the range of approx -0.0001 to 0.0166667, and then it slowly decreases towards zero (and for a brief period it goes into small negative numbers). Once it reaches zero, it flips back to 0.0166667 and continues to decrease again. This cycle repeats indefinitely.
Changing the external display's resolution (UIScreen's mode) or the CADisplayLink's preferredFrameRateRange to a lower FPS does not seem to have any effect on the temporal drifting (even the rate of change seem to be the same).
When I create a new CADisplayLink for the iPhone's main screen, the value of secondsTillDeadline is stable, it does not drift and it is very close to 0.0166667, as expected.
Is this drift caused by the external monitor or by Apple's Lightning-to-HDMI dongle ...or is the problem somewhere else?
Can the drifting be stopped?
func onDisplayLinkUpdate(displayLink: CADisplayLink) {
// Gradually decreases from 0.01667 to -0.0001, then flips back to 0.01667 and continues to decrease
let secondsTillDeadline = displayLink.targetTimestamp - CACurrentMediaTime()
}
Build captivating gaming experiences for Apple platforms.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi everyone,
I'm not an experienced developer. I'm interested in the low-latency related APIs in UIUpdateLink, but I failed to write even a minimal demo that works.
UIUpdateInfo.isImmediatePresentationExpected is always false here. My understanding must be wrong. I've totally no idea so I'm asking for help here. I appreciate anyone who gives suggestions of any kind.
Here's my (failed) demo about tracking touch inputs (of the 1st finger) and draw some shape at that place:
import UIKit
class ContentUIView: UIView {
// MARK: - About UIUpdateLink and drawing
required init?(coder: NSCoder) {
super.init(coder: coder)
initializeUpdateLink()
}
override init(frame: CGRect) {
super.init(frame: frame)
initializeUpdateLink()
}
private func initializeUpdateLink() {
self.updateLink = UIUpdateLink(view: self)
self.updateLink.addAction(to: .beforeCADisplayLinkDispatch,
target: self,
selector: #selector(update))
self.updateLink.wantsImmediatePresentation = true
self.updateLink.isEnabled = true
}
@objc func update(updateLink: UIUpdateLink,
updateInfo: UIUpdateInfo) {
print(updateInfo.isImmediatePresentationExpected) // FIXME: Why always false?
CATransaction.begin()
defer { CATransaction.commit() }
layer.setNeedsDisplay()
layer.displayIfNeeded()
}
override func draw(_ rect: CGRect) {
// FIXME: Any way to support opacity?
guard let context = UIGraphicsGetCurrentContext() else { return }
context.clear(rect)
guard let lastTouch = self.lastTouch else { return }
let location = lastTouch.location(in: self)
let circleBounds = CGRect(x: location.x - 16, y: location.y - 16, width: 32, height: 32)
context.setFillColor(.init(red: 1/2, green: 1/2, blue: 1/2, alpha: 1))
context.addLines(between: [])
context.fillEllipse(in: circleBounds)
}
// MARK: - Touch input
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
guard lastTouch == nil else { return }
lastTouch = touches.first
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
guard let lastTouch, touches.contains(lastTouch) else { return }
self.lastTouch = nil
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touchesEnded(touches, with: event)
}
private var lastTouch: UITouch?
private var updateLink: UIUpdateLink!
}
#Preview { ContentUIView() }
Anyway, I'm not meant to find alternative APIs and I'd be willing to know what it can't do.
Hello,
**I'm Using **
Unity 6 LTS
Unity Apple GameKit + Core plugins
Turn-based matchmaking interface w/ 2 players max
App Store Connect API for rule-based matchmaking
I have already
enabled game center in app store connect (I think)
authenticated players and matched via friend request
I am stuck
Using queues to match players automatically
I'm working on a rule-based matchmaking system which aims to place two players against each other into a GKTurnBasedMatch. I have a simple Unity Project that correctly authenticates a user and proceeds to send a matchmaking request. The matchmaking script utilizes the Unity plugins' GKTurnBasedMatchmakerViewController.Request(...) request function with a GKMatchRequest.Init() request configured with a QueueName equal to the App Store Connect API Queue I created.
The queue I created is also linked to a ruleset with a very basic rule that checks if the properties contains a key called 'preference' that contains a string value for what side the player wants to play for this match. If during the matchmaking, the preferences between players are different, then the match is made and both players should join the match; each player gets to play the side they have chosen. I have my rule expression designed to just check if the preferences are not equal:
requests[0].properties.faction_preference != requests[1].properties.faction_preference
When I launch the game with two physical iPads and begin the matchmaking request, each player is immediately presented with two options:
Invite a friend, or
Start game
The Problem: Inviting a friend works to get two players into a game, but queue seems to not matter, and clicking start game will just put the current player into its own match (no one joins).
The Question: How do I get queue based matchmaking to work in Unity for a Turn-based match with only two players who are able to select the enemy side they want to play dictated by a rule that compares enemy play-side preferences?
Resources I've used:
Apple Unity GameKit Plugin: https://github.com/apple/unityplugins
Matchmaking: https://developer.apple.com/documentation/gamekit/matchmaking-rules
Multiplayer rulesets: https://developer.apple.com/documentation/gamekit/finding-players-using-matchmaking-rules
Topic:
Graphics & Games
SubTopic:
GameKit
Tags:
GameKit
Graphics and Games
App Store Connect
Apple Unity Plug-Ins
Hi,
Since iOS 26 introduced the new Games app, I’ve noticed a problem when using a Nintendo Switch Pro Controller in wired USB-C mode, and also with third-party controllers that emulate it (like the GameSir X5 Lite).
In the Games app interface, only the L/R buttons respond, but the D-Pad and analog sticks don’t work at all. Once inside actual games, the controller works fine — the issue only affects the Games app UI.
What I’ve tested so far:
Xbox / PlayStation controllers → work fine in both wired and Bluetooth, including inside the Games app.
Switch Pro Controller (Bluetooth) → works fine, including in the Games app.
Switch Pro Controller (wired) → same issue as the X5 Lite, D-Pad and sticks don’t work in the Games app.
This makes it hard to use the new Games app launcher with these controllers, even though they work perfectly once a game is launched.
My question: is this an iOS bug (Apple needs to add proper support for wired Switch Pro controllers in the Games app), or something that Nintendo / GameSir would need to address?
Thanks in advance to anyone who can confirm this or provide more info.
Hello,
I have noticed a performance drop on SpriteKit-based projects running on iOS 26.0 (23A341).
Below is a SpriteKit scene used to test framerate on different devices:
import SpriteKit
import SwiftUI
class BareboneScene: SKScene {
override func didMove(to view: SKView) {
size = view.bounds.size
anchorPoint = CGPoint(x: 0.5, y: 0.5)
backgroundColor = .darkGray
let roundedSquare = SKShapeNode(rectOf: CGSize(width: 150, height: 75), cornerRadius: 12)
roundedSquare.fillColor = .systemRed
roundedSquare.strokeColor = .black
roundedSquare.lineWidth = 3
addChild(roundedSquare)
let action = SKAction.rotate(byAngle: .pi, duration: 1)
roundedSquare.run(.repeatForever(action))
}
}
struct BareboneSceneView: View {
var body: some View {
SpriteView(
scene: BareboneScene(),
debugOptions: [.showsFPS]
)
.ignoresSafeArea()
}
}
#Preview {
BareboneSceneView()
}
The scene is very simple, yet framerate drops to ~40 fps as shown by the Metal HUD. Tested on:
iPhone 13, iOS 26.0: framerate drops to 40 fps. Sometimes it runs at near 60fps. But if the screen is touched repeatedly, the framerate drops to 40-50 fps again.
iPhone 11 Pro, iOS 26.0: ~40fps.
iPad 9th Gen, iOS 18.6.2: 60fps, no issues.
See screenshots attached. These numbers were observed by me and members of our beloved SpriteKit Discord server.
Thank you for your attention.