In iOS 26, when using the liquid glass and the custom clear mode, the pictures of the widgets all display as gray squares and cannot show the actual images anymore.
What should I do to display them?
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
As the title says, when I try to add a Toolbar with a Button to my NavigationSplitView I get a warning about satisfying constraints.
Here is a minimal reproducible example:
import SwiftUI
@main
struct ViewTestingApp: App {
var body: some Scene {
WindowGroup {
NavigationSplitView {
Text("Sidebar")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button {
debugPrint("Hello World!")
} label: {
Label("", systemImage: "flame")
}
}
}
} content: {
Text("Content")
} detail: {
Text("Detail")
}
}
}
}
This is the specific warning I get:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSAutoresizingMaskLayoutConstraint:0x600002164960 h=--& v=--& _TtCC5UIKit19NavigationButtonBar15ItemWrapperView:0x100f80fa0.width == 0 (active)>",
"<NSLayoutConstraint:0x600002160370 _TtCC5UIKit19NavigationButtonBar15ItemWrapperView:0x100f80fa0.leading == _UIButtonBarButton:0x100f7d360.leading (active)>",
"<NSLayoutConstraint:0x6000021603c0 H:[_UIButtonBarButton:0x100f7d360]-(0)-| (active, names: '|':_TtCC5UIKit19NavigationButtonBar15ItemWrapperView:0x100f80fa0 )>",
"<NSLayoutConstraint:0x600002160050 'IB_Leading_Leading' H:|-(2)-[_UIModernBarButton:0x100f7e6c0] (active, names: '|':_UIButtonBarButton:0x100f7d360 )>",
"<NSLayoutConstraint:0x6000021600a0 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x100f7e6c0]-(2)-| (active, names: '|':_UIButtonBarButton:0x100f7d360 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000021600a0 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x100f7e6c0]-(2)-| (active, names: '|':_UIButtonBarButton:0x100f7d360 )>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
The project settings are all at their defaults, but in case anyone wants to try it with the whole project:
https://github.com/OddMagnet/ViewTesting
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hi,
On a SwiftUI map I render a mix of MapPolygon and MapPolyline. All overlays must use the same overlay level (.aboveLabels).
Goal:
Ensure MapPolyline always renders on top of MapPolygon.
Issue:
I order data so polylines are last and even render in two passes (polygons first, polylines second), all at .aboveLabels.
Despite that, after polygons change (items removed/added based on zoom levels), I see polygons visually on top of polylines. It seems MapKit may batch/reorder rendering internally.
Questions:
Is there a reliable way in SwiftUI Map to enforce z-order within the same overlay level so MapPolyline always appears above MapPolygon?
If not, any known workarounds or best practices? (e.g. different composition patterns, using annotations with zIndex, or other techniques compatible with SwiftUI Map)
I know you can do this with UIKit, but first looking for a solution compatible with SwiftUI's version of MapKit.
Thanks
I'm using a custom modifier called AutoSheetDetentModifier to automatically size a sheet based on its content.
On iOS 26, it works as expected: the content height is measured correctly and the sheet shrinks to match that height.
However, on iOS 16, 17 and 18, the same code doesn’t work. The content height is still measured, but the sheet does not reduce its height. Instead, the sheet remains larger and the content appears vertically centered. (Note that content() includes ScrollView)
public struct AutoSheetDetentModifier: ViewModifier {
@State private var height: CGFloat = 380 // default value to avoid bouncing
public func body(content: Content) -> some View {
content
.modifier(MeasureHeightViewModifier(height: $height))
.presentationDetents([.height(height)])
}
}
public struct MeasureHeightViewModifier: ViewModifier {
@Binding var height: CGFloat
public func body(content: Content) -> some View {
content
.fixedSize(horizontal: false, vertical: true)
.background(
GeometryReader { geo -> Color in
DispatchQueue.main.async {
height = geo.size.height
}
return Color.clear
}
)
}
}
extension View {
public func applyAutoSheetDetent() -> some View {
self
.modifier(AutoSheetDetentModifier())
}
}
public var body: some View {
VStack {
header()
content() // includes ScrollView
footer()
}
.background(Color.customGray)
.applyAutoSheetDetent()
}
func content() -> some View {
ScrollView {
VStack {
ForEach(items) { item in
itemRow(item)
}
}
}
.frame(maxHeight: UIScreen.main.bounds.height * 0.7)
}
Screenshot from iOS 26 (working as expected):
Screenshot from iOS 18 (not working):
How can I make .presentationDetents(.height) shrink the sheet correctly on iOS 16–18, the same way it does on iOS 26?
With iOS 26.1 we started seeing a bug that only appears on iPhone Air. This bug is visible with simulators too. I have tried so many different ways to fix the issue, but Instruments Profiler is pointing at UIKitCore.
We load a tab bar, when the user attempts to switch a tab, the app hangs and never recovers. It happens right as the animation of the Glass bubble is in progress.
I have tried a UIKit Tab bar, a SwiftUI Tab bar. I tore out AppDelegate and did a direct @main SwiftUI entry for my application. This issue appears with every tab bar instance I try.
I attempted to disable LiquidGlass by utilizing this flag UIDesignRequiresCompatibility in my plist, but the flag seems to be ignored by the system.
I am not sure what else to try. I have a trace file if that is helpful. What else can I upload?
Here is what the code looks like.
struct ContentView: View {
@State private var selectedTab = 2
var body: some View {
TabView(selection: $selectedTab) {
Text("Profile")
.tabItem {
Label("Me", systemImage: "person")
}
.tag(0)
Text("Training")
.tabItem {
Label("Training", systemImage: "calendar")
}
.tag(1)
Text("Home")
.tabItem {
Label("Home", systemImage: "house")
}
.tag(2)
Text("Goals")
.tabItem {
Label("Goals", systemImage: "target")
}
.tag(3)
Text("Coach")
.tabItem {
Label("Coach", systemImage: "person.2")
}
.tag(4)
}
}
}
#Preview {
ContentView()
}
and AppView entry point
import SwiftUI
@main
struct RunCoachApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
SwiftUI sheet with TextField using autocorrectionDisabled() prevents view model deinit after editing
I present a view as a sheet that contains a TextField and a viewModel. The sheet uses .autocorrectionDisabled() on the TextField.
If I open the sheet and dismiss it without editing, the viewModel is released as expected. But if I edit the TextField and then dismiss the sheet, the viewModel is not deinitialized (it remains retained).
Test Outputs:
// # Present 1st time - Correct ✅
TestViewModel - init - 0x0000600000c12ee0
// Dismiss wihtout editing, deinitialized correctly
TestViewModel - deinit - 0x0000600000c12ee0
// # Present 2st time - Incorrect ❌
TestViewModel - init - 0x0000600000c006c0
// Edit and dismiss, no deinit here
// # Present 3rd time - Incorrect ❌
TestViewModel - init - 0x0000600000c113b0
// Enter text field to edit will deinit previous one
TestViewModel - deinit - 0x0000600000c006c0
// Dismiss, no deinit
// TestViewModel (0x0000600000c113b0) remains retained ⚠️
Using .autocorrectionDisabled(true) gives the same problem. Removing or commenting out .autocorrectionDisabled() fixes the issue, but I don't want autocorrection enabled.
Is this a known SwiftUI bug? Has anyone encountered it and found a workaround?
Sample code:
@main
struct TestApp: App {
@State private var isPresentingSheet: Bool = false
var body: some Scene {
WindowGroup {
VStack {
Button("Present Sheet") {
self.isPresentingSheet = true
}
}
.sheet(isPresented: $isPresentingSheet) {
TestTextInputView()
}
}
}
}
View (check the HERE line):
struct TestTextInputView: View {
@StateObject private var viewModel = TestTextInputViewModel()
@FocusState private var isFocused: Bool
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
Form {
TextField("Name", text: $viewModel.name)
.autocorrectionDisabled() // HERE: Comment it out will work without any issue.
.focused($isFocused)
.submitLabel(.done)
.onSubmit {
self.isFocused = false
}
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Cancel") { dismiss() }
}
}
}
}
}
View Model:
final class TestTextInputViewModel: ObservableObject {
@Published var name: String = ""
deinit {
print("TestViewModel - deinit - \(Unmanaged.passUnretained(self).toOpaque())")
}
init() {
print("TestViewModel - init - \(Unmanaged.passUnretained(self).toOpaque())")
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hello developers,
atm im developing a small app focused on hiking. A core pice of the app is a Map() from MapKit. I only want a few points of interest to be visible on the map (e.g. no stores, no clubs etc.).
My question now is what modifier includes mountain Peaks? I tried .rockClimbing, .nationalPark, .landmark, .skiing & .hiking. However none of them makes mountain Peaks visible on the map.
The complete code would be:
Map()
.mapStyle(.standard(pointsOfInterest: .including([.rockClimbing, .nationalPark, .landmark, .skiing, .hiking])))
Hello!
I’m building my Swift Student Challenge project in Swift Playgrounds, and I’ve run into an issue with app orientation.
Since this is a game, the layout and interactions only work correctly in landscape, but Playgrounds doesn’t offer the usual orientation settings you’d configure in Xcode.
Is there a recommended way to force a landscape-only experience in Swift Playgrounds using SwiftUI? Any workarounds or guidance would be greatly appreciated!
Thank you!
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags:
Swift Student Challenge
Swift Playground
Playground Support
SwiftUI
I have a SwiftUI app that needs to present a fullScreenCover when the user opens a deep link.
This screen must appear above anything currently shown — even if another fullScreenCover is already being presented.
In UIKit, I can achieve this by walking the view controller hierarchy, finding the top-most view controller, and presenting the new full-screen view from there.
What is the recommended way to reproduce this behavior in SwiftUI?
How can I ensure a fullScreenCover is always shown above the current presentation layer, regardless of the app’s UI state?
Topic:
UI Frameworks
SubTopic:
SwiftUI
Filed https://feedbackassistant.apple.com/feedback/21260457
When a SwiftUI app uses both a DocumentGroupLaunchScene and a TabView (no matter how trivial) in its Content view, it hangs on 26.1 (both simulator and device), with high CPU utilization in
-[UIView(CALayerDelegate) layoutSublayersOfLayer:]
and memory usage increasing rapidly. This did not happen in 26.0
Topic:
UI Frameworks
SubTopic:
SwiftUI
Structs are value types, and the SwiftUI gets reinitialized many times throughout its lifecycle. Whenever it gets reinitialized, would the reference that the delegator has of it still work if the View uses @State or @StateObject that hold a persistent reference to the views data?
protocol MyDelegate: AnyObject {
func didDoSomething()
}
class Delegator {
weak var delegate: MyDelegate?
func trigger() {
delegate?.didDoSomething()
}
}
struct ContentView: View, MyDelegate {
private let delegator = Delegator()
@State counter = 1
var body: some View {
VStack {
Text("\(counter)")
Button("Trigger") {
delegator.trigger()
}
}
}
func didDoSomething() {
counter += 1 //would this call update the counter in the view even if the view's instance is copied over to the delegator?
}
}
I'm trying to add a confirmationDialog to an app, so that the user can select an option from a menu that comes up from the bottom of the screen. This works perfectly for an iOS 18 simulator, but the behavior changes when the simulator is running iOS 26.1.
Is this the intended behavior of .confirmationDialog in iOS 26.1?
I’m trying to understand the expected behavior of TabView when using .tabViewStyle(.page) on iPadOS with a hardware keyboard.
When I place a TabView in page mode, swipe gestures correctly move between pages. However, left and right arrow keys do nothing by default, even when the view is made focusable. This feels a bit surprising, since paging with arrow keys seems like a natural keyboard interaction when a keyboard is attached.
Right now, to get arrow-key navigation working, I have to manually:
Make the view focusable
Listen for arrow key presses
Update the selection state manually
This works, but it feels a little tedious for something that seems like it could be built-in.
import SwiftUI
struct PageTabsExample: View {
@State private var selection = 0
private let pageCount = 3
var body: some View {
TabView(selection: $selection) {
Color.red.tag(0)
Color.blue.tag(1)
Color.green.tag(2)
}
.tabViewStyle(.page)
.indexViewStyle(.page)
.focusable(true)
.onKeyPress(.leftArrow) {
guard selection > 0 else { return .ignored }
selection -= 1
return .handled
}
.onKeyPress(.rightArrow) {
guard selection < pageCount - 1 else { return .ignored }
selection += 1
return .handled
}
}
}
My questions:
Is this lack of default keyboard paging for page-style TabView intentional on iPadOS with a hardware keyboard?
Is there a built-in way to enable arrow-key navigation for page-style TabView, or is manual handling the expected approach?
Does my approach above look like the “SwiftUI-correct” way to do this, or is there a better pattern for integrating keyboard navigation with paging?
For this kind of behavior, is it generally recommended to use .onKeyPress like I’m doing here, or would .keyboardShortcut be more appropriate (for example, wiring arrow keys to actions instead)?
Any guidance or clarification would be greatly appreciated. I just want to make sure I’m not missing a simpler or more idiomatic solution.
Thanks!
I'm creating an app and I want the user to see the PNG image with the background removed in the widget, but I want the background to be transparent. I've seen this done before in some apps' CarPlay widgets. How can I do this?
When adding buttons to a sheet, on tvOS the text is blurred in the buttons, making it illegible. Feedback: FB21228496
(used GPT to extract an example from my project for a test project to attach here)
// ButtonBlurTestView.swift
// Icarus
//
// Test view to reproduce blurred button issue on tvOS
//
import SwiftUI
struct ButtonBlurTestView: View {
@State private var showSheet = false
@State private var selectedTags: [Int] = []
@State private var newTagName: String = ""
// Hardcoded test data
private let testTags = [
TestTag(id: 1, label: "Action"),
TestTag(id: 2, label: "Comedy"),
TestTag(id: 3, label: "Drama"),
TestTag(id: 4, label: "Sci-Fi"),
TestTag(id: 5, label: "Thriller")
]
var body: some View {
NavigationStack {
VStack {
Text("Button Blur Test")
.font(.title)
.padding()
Button("Show Test Sheet") {
showSheet = true
}
.buttonStyle(.borderedProminent)
.padding()
Text("Tap the button above to open a sheet with buttons inside a Form.")
.font(.caption)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
.padding()
}
.navigationTitle("Blur Test")
.sheet(isPresented: $showSheet) {
TestSheetView(
selectedTags: $selectedTags,
newTagName: $newTagName,
testTags: testTags
)
}
}
}
}
struct TestSheetView: View {
@Environment(\.dismiss) private var dismiss
@Binding var selectedTags: [Int]
@Binding var newTagName: String
let testTags: [TestTag]
var body: some View {
NavigationStack {
VStack {
// Header
VStack {
Text("Testing")
.font(.title2)
.bold()
Text("Test TV Show")
.font(.subheadline)
.foregroundColor(.secondary)
}
.padding()
// Form with buttons
Form {
Section(header: Text("Summary")) {
Text("This is a test")
.font(.subheadline)
.foregroundColor(.secondary)
}
Section(header: Text("Tags")) {
tagsSelectionView
}
}
}
.navigationTitle("Add")
#if !os(tvOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") { dismiss() }
}
ToolbarItem(placement: .confirmationAction) {
Button("Add") { dismiss() }
}
}
}
}
private var tagsSelectionView: some View {
VStack(alignment: .leading) {
// Tag pills in a grid
let columns = [GridItem(.adaptive(minimum: 80), spacing: 8)]
LazyVGrid(columns: columns, alignment: .leading, spacing: 8) {
ForEach(testTags, id: \.id) { tag in
TagPill(
tag: tag,
selected: selectedTags.contains(tag.id)
) {
if selectedTags.contains(tag.id) {
selectedTags.removeAll { $0 == tag.id }
} else {
selectedTags.append(tag.id)
}
}
}
}
Divider()
// Add new tag button
HStack {
TextField("New tag name", text: $newTagName)
#if os(tvOS)
.textFieldStyle(PlainTextFieldStyle())
#else
.textFieldStyle(RoundedBorderTextFieldStyle())
#endif
Button("Add") {
// Test action
newTagName = ""
}
.disabled(newTagName.trimmingCharacters(in: .whitespaces).isEmpty)
}
}
}
}
// Tag Pill - matches the structure from original project
private struct TagPill: View {
let tag: TestTag
let selected: Bool
let action: () -> Void
var body: some View {
Button(action: action) {
Text(tag.label)
.font(.callout)
.lineLimit(1)
.padding(.horizontal, 12)
.padding(.vertical, 8)
.background(
Capsule()
.fill(selected ? Color.accentColor : Color.secondary.opacity(0.15))
)
.overlay(
Capsule()
.stroke(selected ? Color.accentColor : Color.secondary.opacity(0.35), lineWidth: 1)
)
.foregroundStyle(selected ? Color.white : Color.primary)
.contentShape(Capsule())
}
.buttonStyle(.plain)
#if os(tvOS)
.focusable(true)
#endif
}
}
struct TestTag {
let id: Int
let label: String
}
#Preview {
ButtonBlurTestView()
}
AI's would have me believe that the header of a TableColumn in Table() can be modified to be interactive simply by adding a header: closure with a Button however no provided code actually compiles or reflects any documentation I can find.
Is it possible to put something besides a Text object in the header?
Topic:
UI Frameworks
SubTopic:
SwiftUI
I am trying to implement a common UX/UI pattern: one view with rounded corners transitioning to a view that fills the screen (N.B. having the display's corner radius).
I got this to work if both corner radiuses are equal to that of the display (see first GIF).
However, I cannot seem to get it to work for arbitrary corner radiuses of the smaller view (i.e., the one that does not fill the screen).
I expected the be able to combine ContainerRelativeShape with .containerShape (see code), but this left me with a broken transition animation (see second GIF).
import SwiftUI
struct ContentView: View {
@Namespace private var animation
@State private var selectedIndex: Int?
var body: some View {
ZStack {
if let selectedIndex = selectedIndex {
ContainerRelativeShape()
.fill(Color(uiColor: .systemGray3))
.matchedGeometryEffect(id: "square-\(selectedIndex)", in: animation)
.ignoresSafeArea()
.onTapGesture {
withAnimation() {
self.selectedIndex = nil
}
}
.zIndex(1)
}
ScrollView {
VStack(spacing: 16) {
ForEach(0..<20, id: \.self) { index in
if selectedIndex != index {
ContainerRelativeShape() // But what if I want some other corner radius to start with?
.fill(Color(uiColor: .systemGray5))
.matchedGeometryEffect(id: "square-\(index)", in: animation)
.aspectRatio(1, contentMode: .fit)
.padding(.horizontal, 12)
.onTapGesture {
withAnimation() {
selectedIndex = index
}
}
// .containerShape(RoundedRectangle(cornerRadius: 20))
// I can add this to change the corner radius, but this breaks the transition of the corners
} else {
Color.clear
.aspectRatio(1, contentMode: .fit)
.padding(.horizontal, 12)
}
}
}
.padding(.vertical, 16)
}
}
}
}
#Preview {
ContentView()
}
What am I missing here? How can I get this to work? And where is the mistake in my reasoning?
Hi everyone,
I’m working on a screen that uses a single SwiftUI List composed of:
a top block (statistics, month picker, year selector, total, Entrata/Uscita picker).
a list of transactions grouped by day, each group inside its own Section.
each row is a fully custom card with rounded corners (RoundedCornerShape)
I’m correctly removing all separators using:
.listRowSeparator(.hidden)
.listSectionSeparator(.hidden)
.scrollContentBackground(.hidden)
.listStyle(.plain)
Each row is rendered like this:
TransazioneSwipeRowView(...)
.listRowInsets(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
.listRowBackground(Color.clear)
However, I still see thin horizontal lines appearing between:
the search bar and the top block
the top block and the start of the list
between rows inside the grouped section
sometimes at the bottom of a Section
These lines are NOT:
Divider()
system separators
backgrounds
row borders
They seem to be “ghost lines” automatically generated by SwiftUI’s List when multiple consecutive rows or sections are present.
Goal
I want to remove these lines completely while keeping:
native SwiftUI List
native scroll behavior
swipe-to-delete support
grouping by Section
custom card-like rows with rounded corners
transparent backgrounds
What I already tried
.plain, .grouped, .insetGrouped list styles
.listRowSeparator(.hidden) and .listSectionSeparator(.hidden)
.scrollContentBackground(.hidden)
clearing all backgrounds
adjusting/removing all padding and insets
Spacer(minLength: 0) experiments
rebuilding the layout using ScrollView + LazyVStack
(works perfectly — no lines — BUT loses native swipe-to-delete)
There are no Divider() calls anywhere, and no background colors producing borders.
Question
Is this a built-in behavior of SwiftUI’s List in .plain style when using multiple custom rows,
or is there an officially supported way to eliminate these lines entirely?
Is there a recommended combination of modifiers to achieve:
a List with grouped Sections
fully custom rows with rounded backgrounds
absolutely no horizontal separators, even in the empty spaces between sections?
Any guidance, documented workarounds, WWDC references, or official recommendations would be greatly appreciated.
Thanks in advance!
Hello everyone!
I found a weird behavior with the animation of Menucomponent on iOS 26.1
When the menu disappear the animation is very glitchy
You can find here a sample of code to reproduce it
@available(iOS 26.0, *)
struct MenuSample: View {
var body: some View {
GlassEffectContainer {
HStack {
Menu {
Button("Action 1") {}
Button("Action 2") {}
Button("Delete", role: .destructive) {}
} label: {
Image(systemName: "ellipsis")
.padding()
}
Button {} label: {
Image(systemName: "xmark")
.padding()
}
}
.glassEffect(.clear.interactive())
}
}
}
@available(iOS 26.0, *)
#Preview {
MenuSample()
.preferredColorScheme(.dark)
}
I did two videos:
iOS 26.0
iOS 26.1
Thanks for your help
I'm building a macOS app using SwiftUI, and I want to create a draggable floating webcam preview window
Right now, I have something like this:
import SwiftUI
import AVFoundation
struct WebcamPreviewView: View {
let captureSession: AVCaptureSession?
var body: some View {
ZStack {
if let session = captureSession {
CameraPreviewLayer(session: session)
.clipShape(RoundedRectangle(cornerRadius: 50))
.overlay(
RoundedRectangle(cornerRadius: 50)
.strokeBorder(Color.white.opacity(0.2), lineWidth: 2)
)
} else {
VStack(spacing: 8) {
Image(systemName: "video.slash.fill")
.font(.system(size: 40))
.foregroundColor(.white.opacity(0.6))
Text("No Camera")
.font(.caption)
.foregroundColor(.white.opacity(0.6))
}
}
}
.shadow(color: .black.opacity(0.3), radius: 10, x: 0, y: 5)
}
}
struct CameraPreviewLayer: NSViewRepresentable {
let session: AVCaptureSession
func makeNSView(context: Context) -> NSView {
let view = NSView()
view.wantsLayer = true
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.videoGravity = .resizeAspectFill
previewLayer.frame = view.bounds
view.layer = previewLayer
return view
}
func updateNSView(_ nsView: NSView, context: Context) {
if let previewLayer = nsView.layer as? AVCaptureVideoPreviewLayer {
previewLayer.frame = nsView.bounds
}
}
}
This is my SwiftUI side code to show the webcam, and I am trying to create it as a floating window which appears on top of all other apps windows etc. however, even when the webcam is clicked, it should not steal the focus from other apps, the other apps should be able to function properly as they already are.
import Cocoa
import SwiftUI
class WebcamPreviewWindow: NSPanel {
private static let defaultSize = CGSize(width: 200, height: 200)
private var initialClickLocation: NSPoint = .zero
init() {
let screenFrame = NSScreen.main?.visibleFrame ?? .zero
let origin = CGPoint(
x: screenFrame.maxX - Self.defaultSize.width - 20,
y: screenFrame.minY + 20
)
super.init(
contentRect: CGRect(origin: origin, size: Self.defaultSize),
styleMask: [.borderless],
backing: .buffered,
defer: false
)
isOpaque = false
backgroundColor = .clear
hasShadow = false
level = .screenSaver
collectionBehavior = [
.canJoinAllSpaces,
.fullScreenAuxiliary,
.stationary,
.ignoresCycle
]
ignoresMouseEvents = false
acceptsMouseMovedEvents = true
hidesOnDeactivate = false
becomesKeyOnlyIfNeeded = false
}
// MARK: - Focus Prevention
override var canBecomeKey: Bool { false }
override var canBecomeMain: Bool { false }
override var acceptsFirstResponder: Bool { false }
override func makeKey() {
}
override func mouseDown(with event: NSEvent) {
initialClickLocation = event.locationInWindow
}
override func mouseDragged(with event: NSEvent) {
let current = event.locationInWindow
let dx = current.x - initialClickLocation.x
let dy = current.y - initialClickLocation.y
let newOrigin = CGPoint(
x: frame.origin.x + dx,
y: frame.origin.y + dy
)
setFrameOrigin(newOrigin)
}
func show<Content: View>(with view: Content) {
let host = NSHostingView(rootView: view)
host.autoresizingMask = [.width, .height]
host.frame = contentLayoutRect
contentView = host
orderFrontRegardless()
}
func hide() {
orderOut(nil)
contentView = nil
}
}
This is my Appkit Side code make a floating window, however, when the webcam preview is clicked, it makes it as the focus app and I have to click anywhere else to loose the focus to be able to use the rest of the windows.