When displaying a view using a navigation Split View as a sheet, the toolbar button will disappear if you leave the app and resume it.
import SwiftUI
struct Folder: Hashable, Identifiable {
let id = UUID()
let name: String
}
struct ContentView: View {
@State private var showingSettings = false
var body: some View {
VStack {
Button {
showingSettings.toggle()
} label: {
Text("Settings")
}
}
.sheet(isPresented: $showingSettings, content: {
SettingsView()
})
.padding()
}
}
struct SettingsView: View {
@Environment(\.dismiss) private var dismiss
@State private var selectedFolder: Folder? = nil
private var folders = [Folder(name: "Recents"), Folder(name: "Deleted"), Folder(name: "Custom")]
var body: some View {
NavigationSplitView {
SidebarView(selectedFolder: $selectedFolder, folders: folders)
} detail: {
VStack {
if let folder = selectedFolder {
Text(folder.name)
}
else {
Text("No selection")
}
}
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button {
dismiss()
} label: {
Text("Cancel")
}
}
ToolbarItem(placement: .confirmationAction) {
Button {
dismiss()
} label: {
Text("Save")
}
}
}
}
}
}
struct SidebarView: View {
@Binding var selectedFolder: Folder?
var folders: [Folder]
var body: some View {
List(selection: $selectedFolder) {
ForEach(folders) { folder in
NavigationLink(value: folder) {
Text(folder.name)
}
}
}
}
}
Steps to reproduce the issue:
Launch the attached project on an iPad or iPad simulator
Tap the Settings button
Select one item in the sidebar
Use the app switcher to open an other app or just leave the app
Bring back the app
Result:
Both Cancel and Save buttons are gone.
Note:
This will not occur if no item is selected in the sidebar.
FB12991687
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
I think I'm misunderstanding something here, maybe someone could point me in the right direction.
In System Settings, "Correct spelling automatically" is DISABLED, along with all the other options that ruin what you're typing.
In TextEdit, it continues to highlight spelling and grammar mistakes, so does Mail, Safari and others.
Yet SwiftUI made apps, don't.
I can right-click, enable "Check Spelling while typing", but after typing a few characters, words, it becomes disabled again.
I've busted through the view hierarchy to get the hosted NSTextView and overridden "isContinuousSpellCheckingEnabled" but something frequently reverts this to false.
Is my only option to have a large TextEditor with spell checking (but not auto correction) to create my own version of TextEditor by hosting the NSTextView myself. That's a lot of work for something which seems wrong, when I'm hoping that I'm simply missing something here.
Xcode 15.2 on macOS 13.5.
Hello SwiftUI devs, I would like to remove the "More" button that appears in the top left of the screen whenever the selected tab of a tab view is in 5th position and beyond. It ruins the layout.
struct ContentView: View {
private let tabs = (1...10).map { "\($0)" }
@State private var selectedTab: String = "5"
var body: some View {
TabView(selection: $selectedTab) {
ForEach(tabs, id: \.self) { tab in
Text("Tab \(tab)")
.tabItem {
Label("Tab \(tab)", systemImage: "star")
}
.toolbar(.hidden, for: .tabBar)
}
}
}
}
At first glance, one easy fix would be to rearrange the tabs list in the ForEach loop, putting the selected tab at the first position. This does the trick BUT we lose the states of the views, which is out of the question in my use-case.
Getting rid of the tab view and handling the logic with a simple Switch paired with a state restoration mechanism using SceneStorage or SwiftData is probably possible but sounds like a white elephant compared to finding a solution to remove that "More" button.
Thank you
The following WatchOs App example is very short, but already not functioning as it is expected, when using Digital Crown (full code):
import SwiftUI
struct ContentView: View {
let array = ["One","Two","Three","Four"]
@State var selection = "One"
var body: some View {
Picker("Array", selection: $selection) {
ForEach(array, id: \.self) {
Text($0)
}
}
}
}
The following 2 errors are thrown, when using Digital Crown for scrolling:
ScrollView contentOffset binding has been read; this will cause grossly inefficient view performance as the ScrollView's content will be updated whenever its contentOffset changes. Read the contentOffset binding in a view that is not parented between the creator of the binding and the ScrollView to avoid this.
Error: Error Domain=NSOSStatusErrorDomain Code=-536870187 "(null)"
Any help appreciated. Thanks a lot.
Environment:
iOS Version: 17.2
iOS Simulator Version: 17.2
Xcode Version: 15.2
Device: iPhone 15 Pro Max
App Target Version: iOS 17.2
Preconditions:
App with Live Activity feature is installed.
Device/Simulator is running iOS 17.2.
Steps to Reproduce:
Start the app and initiate a Live Activity with text styled as .timer.
Lock the device screen or switch to the lock screen view in the iOS Simulator.
Observe the Live Activity on the lock screen, noting the text style.
Unlock the device. This time noting the .timer changed its style.
The text style of the Live Activity remains consistent both on the lock screen and after unlocking the device, maintaining its .timer style throughout its lifecycle.
Frequency:
Occurs every time the steps are reproduced.
I am trying to use a ShareLink to share multiple transferrable, and I cannot work out which of the initialisers to use - none seem to work.
Assuming I have a transferable that takes some data and processes it asynchronously:
struct MyTransferable: some Transferable {
let renderer: Renderer
static var transferRepresentation: some TransferRepresentation {
DataRepresentation(exportedContentType: .png) { transferable in
let image = try await transferable.render.render()
return image
}
}
}
In SwiftUI, I want to share N of these transferables. For example:
struct MyView: View {
private var transferables: [any Transferable] {
[MyTransferable(), MyTransferable()]
}
var body: some View {
ShareLink("Renders", items: transferables)
}
}
But the compiler doesn't like this - it complains with "No exact matches in call to initializer".
Is this possible? I feel like it should be?
Hi! While working on my Swift Student Challenge submission it seems that I found a race condition (TOCTOU) bug in SwiftUI when using sheets, and I'm not sure if this is expected behaviour or not.
Here's an example code:
import SwiftUI
struct ContentView: View {
@State var myVar: Int?
@State private var presentSheet: Bool = false
var body: some View {
VStack {
// Uncommenting the following Text() view will "fix" the bug (kind of, see a better workaround below).
// Text("The value is \(myVar == nil ? "nil" : "not nil")")
Button {
myVar = nil
} label: {
Text("Set value to nil.")
}
Button {
myVar = 1
presentSheet.toggle()
} label: {
Text("Set value to 1 and open sheet.")
}
}
.sheet(isPresented: $presentSheet, content: {
if myVar == nil {
Text("The value is nil")
.onAppear {
print(myVar) // prints Optional(1)
}
} else {
Text("The value is not nil")
}
})
}
}
When opening the app and pressing the open sheet button, the sheet shows "The value is nil", even though the button sets myVar to 1 before the presentSheet Bool is toggled.
Thankfully, as a workaround to this bug, I found out you can change the sheet's view to this:
.sheet(isPresented: $presentSheet, content: {
if myVar == nil {
Text("The value is nil")
.onAppear {
if myVar != nil {
print("Resetting View (TOCTOU found)")
let mySwap = myVar
myVar = nil
myVar = mySwap
}
}
} else {
Text("The value is not nil")
}
})
This triggers a view refresh by setting the variable to nil and then to its non-nil value again if the TOCTOU is found.
Do you think this is expected behaivor? Should I report a bug for this? This bug also affects .fullScreenCover() and .popover().
I have a an exercise of taking a shuffled display of words and dragging and dropping them into the correct sequence to form a sentence.
I'm currently using .onDrag and .onDrop with a dropDelegate to perform these actions. However, in order the drag operation to start happening, the user needs to click the item for 1-2 seconds and then the drag can be performed. I would like to remove the need to long press the item before the drag or at least decrease the delay between clicking and dragging.
Has anyone found a work around for solution for this problem? I found one post where the person said the removed the magnification feature to help streamline the drag. I assume they are referring to the item you click being magnified and previewed during the drag operation of .onDrag. I cannot seem to find out how to remove that feature though or if it is even possible.
Here is a small snippet of my item with the .onDrag
func DragArea()->some View {
VStack(spacing: 40){
ForEach(shuffledRows, id: \.self){row in
HStack(spacing:45){
ForEach(row){item in
Text(item.value)
.font(.system(size: 28))
.padding(.vertical, 7)
.padding(.horizontal, item.padding)
.background{
RoundedRectangle(cornerRadius: 6, style: .continuous)
.stroke(.black, lineWidth: 3)
}
.onDrag{
return .init(contentsOf: URL(string: item.id))!
}
.opacity(item.isShowing ? 0 : 1)
.background{
RoundedRectangle(cornerRadius: 6, style: .continuous)
.fill(item.isShowing ? .gray.opacity(0.25) : .clear)
}
}
}//.frame(width: UIScreen.main.bounds.size.width - 200)
}
}
}
First of all, I tried MobileVLCKit but there is too much delay
Then I wrote a UDPManager class and I am writing my codes below. I would be very happy if anyone has information and wants to direct me.
Broadcast code
ffmpeg -f avfoundation -video_size 1280x720 -framerate 30 -i "0" -c:v libx264 -preset medium -tune zerolatency -f mpegts "udp://127.0.0.1:6000?pkt_size=1316"
Live View Code (almost 0 delay)
ffplay -fflags nobuffer -flags low_delay -probesize 32 -analyzeduration 1 -strict experimental -framedrop -f mpegts -vf setpts=0 udp://127.0.0.1:6000
OR
mpv udp://127.0.0.1:6000 --no-cache --untimed --no-demuxer-thread --vd-lavc-threads=1
UDPManager
import Foundation
import AVFoundation
import CoreMedia
import VideoDecoder
import SwiftUI
import Network
import Combine
import CocoaAsyncSocket
import VideoToolbox
class UDPManager: NSObject, ObservableObject, GCDAsyncUdpSocketDelegate {
private let host: String
private let port: UInt16
private var socket: GCDAsyncUdpSocket?
@Published var videoOutput: CMSampleBuffer?
init(host: String, port: UInt16) {
self.host = host
self.port = port
}
func connectUDP() {
do {
socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: .global())
//try socket?.connect(toHost: host, onPort: port)
try socket?.bind(toPort: port)
try socket?.enableBroadcast(true)
try socket?.enableReusePort(true)
try socket?.beginReceiving()
} catch {
print("UDP soketi oluşturma hatası: \(error)")
}
}
func closeUDP() {
socket?.close()
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didConnectToAddress address: Data) {
print("UDP Bağlandı.")
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didNotConnect error: Error?) {
print("UDP soketi bağlantı hatası: \(error?.localizedDescription ?? "Bilinmeyen hata")")
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
if !data.isEmpty {
DispatchQueue.main.async {
self.videoOutput = self.createSampleBuffer(from: data)
}
}
}
func createSampleBuffer(from data: Data) -> CMSampleBuffer? {
var blockBuffer: CMBlockBuffer?
var status = CMBlockBufferCreateWithMemoryBlock(
allocator: kCFAllocatorDefault,
memoryBlock: UnsafeMutableRawPointer(mutating: (data as NSData).bytes),
blockLength: data.count,
blockAllocator: kCFAllocatorNull,
customBlockSource: nil,
offsetToData: 0,
dataLength: data.count,
flags: 0,
blockBufferOut: &blockBuffer)
if status != noErr {
return nil
}
var sampleBuffer: CMSampleBuffer?
let sampleSizeArray = [data.count]
status = CMSampleBufferCreateReady(
allocator: kCFAllocatorDefault,
dataBuffer: blockBuffer,
formatDescription: nil,
sampleCount: 1,
sampleTimingEntryCount: 0,
sampleTimingArray: nil,
sampleSizeEntryCount: 1,
sampleSizeArray: sampleSizeArray,
sampleBufferOut: &sampleBuffer)
if status != noErr {
return nil
}
return sampleBuffer
}
}
I didn't know how to convert the data object to video, so I searched and found this code and wanted to try it
func createSampleBuffer(from data: Data) -> CMSampleBuffer? {
var blockBuffer: CMBlockBuffer?
var status = CMBlockBufferCreateWithMemoryBlock(
allocator: kCFAllocatorDefault,
memoryBlock: UnsafeMutableRawPointer(mutating: (data as NSData).bytes),
blockLength: data.count,
blockAllocator: kCFAllocatorNull,
customBlockSource: nil,
offsetToData: 0,
dataLength: data.count,
flags: 0,
blockBufferOut: &blockBuffer)
if status != noErr {
return nil
}
var sampleBuffer: CMSampleBuffer?
let sampleSizeArray = [data.count]
status = CMSampleBufferCreateReady(
allocator: kCFAllocatorDefault,
dataBuffer: blockBuffer,
formatDescription: nil,
sampleCount: 1,
sampleTimingEntryCount: 0,
sampleTimingArray: nil,
sampleSizeEntryCount: 1,
sampleSizeArray: sampleSizeArray,
sampleBufferOut: &sampleBuffer)
if status != noErr {
return nil
}
return sampleBuffer
}
And I tried to make CMSampleBuffer a player but it just shows a white screen and doesn't work
struct SampleBufferPlayerView: UIViewRepresentable {
typealias UIViewType = UIView
var sampleBuffer: CMSampleBuffer
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: .zero)
let displayLayer = AVSampleBufferDisplayLayer()
displayLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(displayLayer)
context.coordinator.displayLayer = displayLayer
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
context.coordinator.sampleBuffer = sampleBuffer
context.coordinator.updateSampleBuffer()
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator {
var displayLayer: AVSampleBufferDisplayLayer?
var sampleBuffer: CMSampleBuffer?
func updateSampleBuffer() {
guard let displayLayer = displayLayer, let sampleBuffer = sampleBuffer else { return }
if displayLayer.isReadyForMoreMediaData {
displayLayer.enqueue(sampleBuffer)
} else {
displayLayer.requestMediaDataWhenReady(on: .main) {
if displayLayer.isReadyForMoreMediaData {
displayLayer.enqueue(sampleBuffer)
print("isReadyForMoreMediaData")
}
}
}
}
}
}
And I tried to use it but I couldn't figure it out, can anyone help me?
struct ContentView: View {
// udp://@127.0.0.1:6000
@ObservedObject var udpManager = UDPManager(host: "127.0.0.1", port: 6000)
var body: some View {
VStack {
if let buffer = udpManager.videoOutput{
SampleBufferDisplayLayerView(sampleBuffer: buffer)
.frame(width: 300, height: 200)
}
}
.onAppear(perform: {
udpManager.connectUDP()
})
}
}
Hi everyone,
I'm currently facing an issue with AVAudioPlayer in my SwiftUI project. Despite ensuring that the sound file "buttonsound.mp3" is properly added to the project's resources (I dragged and dropped it into Xcode), the application is still unable to locate the file when attempting to play it.
Here's the simplified version of the code I'm using:
import SwiftUI
import AVFoundation
struct ContentView: View {
var body: some View {
VStack {
Button("Play sound") {
playSound(named: "buttonsound", ofType: "mp3")
}
}
}
}
func playSound(named name: String, ofType type: String) {
guard let soundURL = Bundle.main.url(forResource: name, withExtension: type) else {
print("Sound file not found")
return
}
do {
let audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch let error {
print("Error playing sound: \(error.localizedDescription)")
}
}
Hello, I can't seem to set any breakpoint in didSet for all properties inside Observable.
Is this a bug?
XcodeVersion 15.2
(15C500b)
Thanks!
I am trying to build a text editor that shrinks to its content size. The closest I have been able to get has been to add the .scrollDisabled(true) and .fixedSize(horizontal: false, vertical: true) modifiers.
This almost achieves what I need. There are two problems though:
long single line text gets cut off at the end
creating line breaks causes the text editor to grow vertically as expected (uncovering the cut off text in point 1 above). However, when you delete the line breaks, the TextEditor does not shrink again.
I have had a radar open for some time: FB13292506. Hopefully opening a thread here will get more visibility.
And here is some sample code to easily reproduce the issue:
import SwiftUI
struct ContentView: View {
@State var text = "[This is some long text that will be cut off at the end of the text editor]"
var body: some View {
TextEditor(text: $text)
.scrollDisabled(true)
.fixedSize(horizontal: false, vertical: true)
}
}
#Preview {
ContentView()
}
Here is a gif of the behavior:
I've submitted this as FB13628591 but I figure a forum post never hurts ;)
I’ve discovered an issue with keyboard presentation when using .searchable in SwiftUI in iOS 17.4 beta 3, shown in this video (https://imgur.com/1hmM5u0) running this sample code.
struct Animal: Identifiable {
var id: String {
return name
}
let name: String
}
struct ContentView: View {
let animals: [Animal] = [.init(name: "Dog"), .init(name: "Cat"), .init(name: "Turtle")]
@State var presentedAnimal: Animal? = nil
@State var searchText: String = ""
var body: some View {
NavigationStack {
List {
ForEach(animals) { item in
Button(item.name) {
self.presentedAnimal = item
}
}
}
.sheet(item: $presentedAnimal) { item in
Text(item.name)
}
.searchable(text: $searchText)
}
}
}
As of iOS 17.4, the behavior of the above code is that if you tap one of the list buttons to present a sheet while the keyboard is still presented, the keyboard will dismiss then represent once the sheet is presented. In the video, I tap the “Cat” button while the search keyboard is still presented. This is confusing, because the keyboard actually belongs to the presenting .searchable view, not the presented sheet. In all previous versions, the keyboard would dismiss and stay that way. That is the correct behavior.
I’ve noticed this erroneously presented keyboard does not respond to calls to resignFirstResponder:
let resign = #selector(UIResponder.resignFirstResponder)
UIApplication.shared.sendAction(resign, to: nil, from: nil, for: nil)
Background
I have a SwiftUI app that uses OSLog and the new Logger framework. In my SwiftUI views, I would like to use something like Self._logChanges() to help debug issues.
After some trial and error, I can see the messages appear in the System console log for the app I am debugging using the com.apple.SwiftUI subsystem.
Problem
I'd like to see those same messages directly in Xcode's console window so I can filter them as needed. How do I do that?
Thanks! -Patrick
I have a view, and in this view I bind Axis class values — lowerBound which is a regular property and at – computed one which comes from protocol HasPositionProtocol associated with Axis.
struct AxisPropertiesView<Axis>: View
where Axis: StyledAxisProtocol,
Axis: HasPositionProtocol,
Axis: Observable
{
@Bindable var axis: Axis
var body: some View {
HStack {
TextField("", text: $axis.shortName)
.frame(width: 40)
TextField("",
value: $axis.lowerBound,
format: .number)
.frame(width: 45)
//Problem is here:
Slider(value: $axis.at,
in: axis.bounds)
...
Unfortunately I got en error Failed to produce diagnostic for expression; ... for whole View.
But if I remove Slider from View, error disappeared.
What could cause this strange behaviour?
Value of .at comes from:
public extension HasPositionProtocol {
///Absolut position on Axis
var at: Double {
get {
switch position {
case .max:
return bounds.upperBound
case .min:
return bounds.lowerBound
case .number(let number):
return number
}
}
set {
switch newValue {
case bounds.lowerBound:
position = .min
case bounds.upperBound:
position = .max
default:
position = .number(newValue)
}
}
}
}
Using a button that is placed in the bottom ornament to set focus on a text field will not display the keyboard properly while a button embedded in the view will behave as expected.
To demonstrate the issue, simply run the attached project on Vision Pro with visionOS 1.1 and tap the Toggle 2 button in the bottom ornament. You’ll see that the field does have focus but the keyboard is now visible.
Run the same test with Toggle 1 and the field will get focus and the keyboard will show as expected.
import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView: View {
@State private var text = ""
@State private var showKeyboard = false
@FocusState private var focusedField: FocusField?
private enum FocusField: Hashable {
case username
case password
}
var body: some View {
VStack {
TextField("Test", text: $text)
.focused($focusedField, equals: .username)
Text("Entered Text: \(text)")
.padding()
Button("Toggle 1") { // This button will work and show the keyboard
if focusedField != nil {
focusedField = nil
} else {
focusedField = .username
}
}
Spacer()
}
.padding()
.toolbar {
ToolbarItem(placement: .bottomOrnament) {
Button("Toggle 2") { // This button will set focus properly but not show the keyboard
if focusedField != nil {
focusedField = nil
} else {
focusedField = .username
}
}
}
}
}
}
Is there a way to work around this?
FB13641609
Our app was just rejected by Apple because they say the subscription management sheet never loads. It just spins indefinitely.
We're using StoreKit's manageSubscriptionsSheet view modifier to present the sheet, and it's always worked for us when testing in SandBox.
Has anyone else had this problem?
Given that it's Apple's own code that got us rejected, what's our path forward?
Xcode 15.2, iOS 17.2
I have a piece of code that displays videos. It has been working for at least 6 months. Suddenly only the first video played. The following videos would only play audio with the video being frozen at the first frame. I noticed that SwiftUI would start to instantiate multiple instances of my player observable class instead of just one.
After chasing the problem for most of a day I found that if I completely removed every piece of code referencing AuthenticationServices then everything would work fine again.
Even if I add the following piece of code which is not used or called in any way. Then SwiftUI will start to act weird.
func configure(_ request: ASAuthorizationAppleIDRequest) {
request.requestedScopes = [.fullName, .email]
}
If I comment out request.requestedScopes = [.fullName, .email] everything works fine.
The SignInWithApple is configured and works fine if I enable the code.
Any suggestions on how to solve or any work arounds would be highly appreciated.
i tried using webview to render a website (https://pub-app-stg.intellifms.com/auth/sign-in)
and for some reason it stays blank white.
other site works normally, with app transport security.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>https://pub-app-stg.intellifms.com/auth/sign-in</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</dict>
the code goes as simple as this
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
let request = URLRequest(url: url)
uiView.load(request)
}
}
struct ContentView: View {
var body: some View {
WebView(url: URL(string: "https://pub-app-stg.intellifms.com/auth/sign-in")!)
}
}
I cant find the reason why it wont, the website connection is secure, it has proper certifications and it just would work.
im starting to thinks theres a problem with the certificate because its using a public certificate.
I can't get a 3D model to spin inside a swiftUI 2D view..
I had for example:
Model3D(named: "Cupcake")
.rotationEffect(Angle(degrees: rotationAngle))
But I'm unsure where to implement something like
rotationAngle += 5
(I'm used to Unity and would put that in Update())