Post

Replies

Boosts

Views

Activity

Can SwiftUI View Receive a Call When Window Will Close?
I have an NSStatusBar application. This is my first in SwiftUI. And I need to know when the window is closed so that I can disable some of menu commands. I can use NSWindowDelegate with AppDelegate as follows. import SwiftUI @main struct SomeApp: App { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @StateObject private var menuViewModel = MenuViewModel() var body: some Scene { WindowGroup { ContentView() .environmentObject(menuViewModel) } } } class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { private var menuViewModel = MenuViewModel() func applicationDidFinishLaunching(_ notification: Notification) { if let window = NSApplication.shared.windows.first { window.setIsVisible(false) window.delegate = self } } func windowWillClose(_ notification: Notification) { menuViewModel.windowClosed = true } } When the window will close, MenuViewModel (ObservableObject) will receive a call, which I want my ContentView to receive. But, so far, it won't. import SwiftUI struct ContentView: View { var body: some View { ZStack { ... ... } .onReceive(statusBarViewModel.$windowClosed) { result in // never called... } } } Can a SwiftUI View receive a call somehow when its window closes? Muchos thankos.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
3
1
553
Jun ’25
onReceive(_:perform:) on Frontmost Window Only?
I have a simple document-based application for macOS. struct ContentView: View { @Binding var document: TextDocument var body: some View { .onReceive(NotificationCenter.default.publisher(for: .notificationTextWillAppendSomeTextt), perform: { _ in }) VStack { TextEditor(text: $document.text) } } } extension Notification.Name { static let notificationTextWillAppendSomeTextt = Notification.Name("TextWillAppendSomeText") } Suppose that my application currently has three tabs. If I call a menu command through post(name:object:) this menu command call will affect all three of them. This stackoverflow topic talks about it, too. So how could I tell which window should get a call and others don't? Thanks.
3
0
94
May ’25
Image Miniaturization Issue
I have three toolbar buttons with images from Assets.xcassets. Initially, I didn't use @1x, @2x, @3x sizes. I just put one size (72 x 72) for all of them. It was never a problem till a few days ago. The reviewer has reported numerous issues, which all seem to originate from miniaturized toolbar images. They have given me a screenshot from an iPad. Now, each of the three to the left has shrunken to 4 x 4, according to them. Some lines of code are the following. import SwiftUI struct ContentView: View { var body: some View { NavigationStack { ZStack { VStack { ... ... ... } .background(.brown) .navigationBarTitleDisplayMode(.inline) .navigationBarItems( leading: HStack(content: { Button { } label: { Image("ToolbarImage1") .resizable() .foregroundColor(.red) .aspectRatio(contentMode: .fit) .frame(width: 28) } Button { } label: { Image("ToolbarImage2") .resizable() .foregroundColor(.cyan) .aspectRatio(contentMode: .fit) .frame(width: 28) } Button { } label: { Image("ToolbarImage3") .resizable() .foregroundColor(.gray) .aspectRatio(contentMode: .fit) .frame(width: 28) } }), trailing: HStack(content: { Button { } label: { Text("X") .font(.body) .fontWeight(.semibold) .foregroundStyle(colorScheme == .light ? .white : .black) .frame(width: 28, height: 28) .background { Circle() .fill(!disableGroupMenu ? .green : .green.opacity(0.6)) } } Button { withAnimation(.easeInOut(duration: 0.2)) { showCopyMenu.toggle() manageMenu() } } label: { Text("Y") .font(.body) .fontWeight(.semibold) .foregroundStyle(colorScheme == .light ? .white : .black) .frame(width: 28, height: 28) .background { Circle() .fill(!disableCopyMenu ? .indigo: .indigo.opacity(0.6)) } } }) ) .toolbar { ToolbarItem(placement: .principal) { Text("App name") .bold() .foregroundColor(.white) } } } } } } I don't see this minituralization issue on any of my actual devices (iPhone XR, iPhone 14, iPad 9th gen.) on top of various simulator models including iPad A16 with iOS 26. This is my first iOS submission after iOS 26 was released. I don't know if it has something to do with iOS 26. The reviewer hasn't told me about their iPad model or the iOS version. I have the same app for macOS, which was submitted after macOS 26 was released. And they haven't reported the miniaturization issue after 4 or 5 software updates. If you have any idea as to what's causing it, please let me know. I have submitted a new binary with @3x as a resort. I doubt the issue has been resolved. Thanks. Initally, I've used Xcode 16.4 to built the app. I have tried building it with Xcode 26. And I don't see the minituralization issue on any of the simulator models (iPad mini, iPad A16...).
Topic: UI Frameworks SubTopic: SwiftUI
3
0
120
Oct ’25
Practical Use of Combine's Subject
I'm trying to understand how Combine works. The following is my sample code. import UIKit import Combine class ViewController: UIViewController { // MARK: - Variables var cancellable: AnyCancellable? // MARK: - IBAction @IBAction func buttonTapped(_ sender: UIButton) { currentValueSubject.send(20) } // MARK: - Life cycle var currentValueSubject = CurrentValueSubject<Int, Never>(1) override func viewDidLoad() { super.viewDidLoad() let cancellable = currentValueSubject .sink { value in print("New value: \(value)") } currentValueSubject.send(5) currentValueSubject.send(10) //currentValueSubject.send(completion: .finished) currentValueSubject.send(15) //cancellable.cancel() } } If I run it with the iPhone simulator, I get New value: 1 New value: 5 New value: 10 New value: 15 If I tap the button, the app won't get a new value. I suppose that's because the subscription is cancelled at the end of viewDidLoad? If so, why does it get cancelled? I don't quite see a practical side of Combine's Subject. When is it useful? Thanks.
2
0
1.2k
Aug ’21
Picker with Unexpected Results
I'm playing with Picker and have come up with some unexpected results. As shown below, I have three pickers in a form. struct PickColorView: View { @State var numberIndex: Int = 4 @State var textSizeIndex: Int = 0 var body: some View { NavigationView { Form { Picker(selection: $numberIndex, label: Text("Numbers")) { ForEach((0...20), id: \.self) { Text("\($0)") } }.onChange(of: numberIndex) { newIndex in print("Index: \(newIndex)") } Picker(selection: $textSizeIndex, label: Text("textSizeTitle")) { ForEach([14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60], id: \.self) { textSize in Text("\(textSize)") } }.onChange(of: textSizeIndex) { newIndex in print("Index: \(newIndex)") } } .navigationBarTitle("Settings") .navigationBarHidden(false) } .navigationViewStyle(StackNavigationViewStyle()) } } Well, if I run it, the top picker shows its initial selection (4) while the other doesn't. I wonder why? The following is a screenshot. (Please ignore the top picker appearing in the screenshot). If I go ahead and select one with the bottom picker, I end up with an actual value instead of the index. So if I select 18 (Please see the screenshot below.), I expect to get 2 with the onChange thing. But I get 18, instead. So how can I receive the index? Muchos thankos.
2
0
465
Jan ’22
Where and How to Create FileManager as a Singleton?
When I write code with UIKIt or Cocoa, I usually create and use FileManager.default in AppDelegate or a base view controller. In Cocoa, for example, I would write something like the following. import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { let defaultFileManager = FileManager.default func applicationDidFinishLaunching(_ aNotification: Notification) { } func applicationWillTerminate(_ aNotification: Notification) { NSApp.terminate(nil) } } import Cocoa class HomeViewController: NSViewController { let appDelegate = (NSApp.delegate as! AppDelegate) override func viewDidLoad() { super.viewDidLoad() if appDelegate.defaultFileManager.fileExists(atPath: some file path) { } } } So my question is where I can create FileManager.default so that I use it under different Views in SwiftUI? Muchos thankos.
2
0
615
Feb ’22
Getting an Updated Value Through @EnvironmentObject
I have a simple project as follows. import SwiftUI class GameSettings: ObservableObject { @Published var score: Int = 100 } struct ContentView: View { @StateObject var settings = GameSettings() var body: some View { GeometryReader { geo in ZStack { HStack(spacing: 0.0) { RightView().environmentObject(GameSettings()) .frame(width: geo.size.width / 2.0, height: geo.size.height) Spacer() } VStack { HStack { Spacer() Button { print("\(settings.score)") } label: { Text("Print") .font(.largeTitle) }.padding(.trailing, 40.0) } Spacer() } } } } } struct RightView: View { @EnvironmentObject var settings: GameSettings var body: some View { ZStack { Color.red Button { settings.score += 100 } label: { Text("Change") .font(.largeTitle) } }.environmentObject(settings) } } So the score is supposed to increase by 100 if I tap the button over the red area. And I want to print the latest value by tapping the Print button at the top-right corner. But it will remain at 100. What am I doing wrong? And can I achieve my goal without using an @ObservedObject variable? Thanks.
2
0
508
Mar ’22
Horizontally-Aligned TextField Wrap?
I have a @State variable with an array of strings with which to create instances of TextField. So far, I have the following lines of code. import SwiftUI struct ContentView: View { @State private var names: [String] = ["Jim Thorton", "Susan Murphy", "Tom O'Donnell", "Nancy Smith"] var body: some View { HStack { ForEach($names, id: \.self) { $name in TextField("", text: $name) .fixedSize() .padding(.horizontal, 20.0) .background(Color.orange.opacity(0.2)) } } } } I wonder if there is a simple way of aligning instances of TextField horizontally such that one that exceeds the screen width will go to the next line like the following picture? Thanks.
2
0
1.7k
Apr ’22
NSItemProvider & DropDelegate - Shrinking Preview Picture
I have downloaded a sample project at raywenderlich.com (https://www.raywenderlich.com/22408716-drag-and-drop-editable-lists-tutorial-for-swiftui). I am working on a project involving DropDelegate. And I have a question with this project to make my point. In reference to the picture shown below, if I grab, drag and move Count Sheep, its preview picture will shrink. How could I prevent the preview picture from shrinking its size? struct ContentView: View { @EnvironmentObject private var todoList: TodoList @State private var isShowingAddTodoView = false @State private var editMode: EditMode = .inactive @State private var focusId: Int? func addTodo() { isShowingAddTodoView = true } var body: some View { NavigationView { VStack { FocusTodoView(focusId: focusId) .padding() .onDrop( of: [TodoItem.typeIdentifier], delegate: TodoDropDelegate(focusId: $focusId)) ScrollView { ActiveTodoView() CompletedTodoView() .disabled(editMode.isEditing) .onDrop(of: [TodoItem.typeIdentifier], isTargeted: nil) { itemProviders in for itemProvider in itemProviders { itemProvider.loadObject(ofClass: TodoItem.self) { todoItem, _ in guard let todoItem = todoItem as? TodoItem else { return } DispatchQueue.main.async { todoList.updateTodo(withId: todoItem.id, isCompleted: true) } } } return true } } .applyPlainListAppearance() .navigationBarTitle("Drag Todo") .toolbar { ToolbarItemGroup(placement: .navigationBarTrailing) { EditButton() Button(action: addTodo) { Image(systemName: "plus") } .disabled(editMode.isEditing) } } .environment(\.editMode, $editMode) .sheet(isPresented: $isShowingAddTodoView) { AddTodoView() } } } .navigationViewStyle(StackNavigationViewStyle()) } } I wish I had a simpler sample. That's the only sample I have been able to find. Anyway, I've been asking Google all day about "SwiftUI DropDelegate preview" with no luck. Thanks.
2
0
726
Aug ’22
Sorting Array of Dictionaries with Exceptions?
I have an array of dictionaries. And I need to sort this array in an ascending order. someArray = someArray.sorted { lValue, rValue in lValue.categoryName < rValue.categoryName } So one of the dictionaries is categoryName. Now, I have a case where the category name of an array element is something specific, say 'price,' then that element must be listed at the end as an exception to the rule above. Is that possible? Thanks.
2
0
709
Sep ’22
Saving Camera-Captured Picture to Photo with AVCaptureSession
How do you save a picture from the capture-screen with AVCaptureSession to Photo? My capture-screen looks like a square as show below. Yet I've ended up with an 1080 × 1920 image as shown below. I have an iPhone XR, and I always end up with 1080 × 1920 images. How come the aspect ration never changes? My code has the following lines import UIKit import AVFoundation class CaptureViewController: UIViewController, AVCapturePhotoCaptureDelegate { var captureSession: AVCaptureSession! var cameraDevices: AVCaptureDevice! var imagePhotoOutput: AVCapturePhotoOutput! enum CameraCase { case front case back } // MARK: - IBAction @IBAction func takePictureTapped(_ sender: UIButton) { snapPicture() } // MARK: - Life cycle override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) prepareCamera(cameraCase: .back) } // MARK: - Camera func prepareCamera(cameraCase: CameraCase) { /* removing existing layers */ if let sublayers = self.view.layer.sublayers { for sublayer in sublayers { if sublayer.isKind(of: AVCaptureVideoPreviewLayer.self) { sublayer.removeFromSuperlayer() } } } /* creating a capture session */ captureSession = AVCaptureSession() guard let device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: cameraCase == .front ? .front : .back).devices.first else { return } let videoInput = try? AVCaptureDeviceInput(device: device) if captureSession.canAddInput(videoInput!) { captureSession.addInput(videoInput!) imagePhotoOutput = AVCapturePhotoOutput() // setting output destination captureSession.addOutput(imagePhotoOutput) // adding photo output to session } /* creating a capture layer */ let previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: captureSession) previewLayer.frame = CGRect(x: 0.0, y: 200.0, width: view.frame.width, height: view.frame.height - 500.0) previewLayer.videoGravity = AVLayerVideoGravity.resize /* adding video capture layer to the view layer */ self.view.layer.addSublayer(previewLayer) /* starting capture session */ DispatchQueue.global(qos: .background).async { self.captureSession.startRunning() } } func snapPicture() { let settingsForMonitoring = AVCapturePhotoSettings() imagePhotoOutput?.capturePhoto(with: settingsForMonitoring, delegate: self as AVCapturePhotoCaptureDelegate) } // MARK: - Delegate methods func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { if error == nil { guard let imageData = photo.fileDataRepresentation() else { print("Error while generating image from photo capture data."); return } if let image = UIImage(data: imageData) { saveImage(image) } } } // MARK: - Saving an image to Photo Library func saveImage(_ image: UIImage) { UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError: contextInfo:)), nil) } @objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) { if let error = error { print("An error has occurred: \(error.localizedDescription)") } else { print("Saved...") } } } Thanks.
2
0
1.6k
Dec ’22
Drawing a Pie without Path?
Drawing a pie isn't difficult if I do it with Path. import SwiftUI struct ContentView8: View { var body: some View { PieSlice(start: .degrees(-90), end: .degrees(120)) .fill(.pink) } } struct PieSlice: Shape { let start: Angle let end: Angle func path(in rect: CGRect) -> Path { var path = Path() let center = CGPoint(x: rect.midX, y: rect.midY) path.move(to: center) path.addArc(center: center, radius: rect.midX, startAngle: start, endAngle: end, clockwise: false) return path } } Actually, I want to animate this pie such that it will gradually deploy starting at -90 degrees. In the code above, I suppose I cannot animate the pie because the PieSlice guy isn't a View. Or can I? If I can't, is there an alternative way of drawing a pie so that I can animate it? Thanks a million. Señor Tomato Source Hostage Negotiator at Tomato Source Association of North America
2
0
605
Jul ’23
Sorting CoreData Records by Creation Date
I have followed a tutorial written by Hacking with Swift ( https://www.hackingwithswift.com/books/ios-swiftui/how-to-combine-core-data-and-swiftui) about Core Data in SwiftUI. The Entity name is Student. And it has two properties: name (String), id (UUID). And the following is my code. import SwiftUI struct CoreView: View { @Environment(\.managedObjectContext) var managedObject @FetchRequest(sortDescriptors: []) var students: FetchedResults<Student> var body: some View { VStack { List(students) { student in Text(student.name ?? "Unknown") } Button { let firstNames = ["Gary", "Harry", "Elane", "Ray", "Nancy", "Jim", "Susan"] let lastNames = ["Johns", "McNamara", "Potter", "Thompson", "Hampton"] if let selectedFirstName = firstNames.randomElement(), let selectedLastName = lastNames.randomElement() { let newStudent = Student(context: managedObject) newStudent.id = UUID() newStudent.name = "\(selectedFirstName) \(selectedLastName)" try? managedObject.save() } } label: { Text("Add") } } } } struct CoreView_Previews: PreviewProvider { static var previews: some View { CoreView() .environmentObject(DataController()) } } If I list all records and then add a new student to the list, the app will insert the last addition at a random row. I wonder if I can order these records by the creation date? Muchos thankos
2
0
1.3k
Jul ’23