Hi,
I have an existing Mac app on the App Store with a couple of widgets as part of the app. I want to now add a new widget to the WidgetBundle. When I build the updated app with Xcode, and then run the updated app, the widgets list doesn't seem to get updated in Notification Center or in the WidgetKit Simulator.
I do have the App Store version installed in the /Applications folder as well, so there might be some conflict. What's the trick to getting the widgets list to run the debug version?
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
In the header for UIViewController, the method dismissViewControllerAnimated is declared like this:
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion NS_SWIFT_DISABLE_ASYNC API_AVAILABLE(ios(5.0));
NS_SWIFT_DISABLE_ASYNC means that there's no async version exposed like there would normally be of a method that exposes a completion handler. Why is this? And is it unwise / unsafe for me to make my own async version of it using a continuation?
My use case is that I want a method that will sequentially dismiss all view controllers presented by a root view controller. So I could have this extension on UIViewController:
extension UIViewController {
func dismissAsync(animated: Bool) async {
await withCheckedContinuation { continuation in
self.dismiss(animated: animated) {
continuation.resume()
}
}
}
func dismissPresentedViewControllers() async {
while self.topPresentedViewController != self {
await self.topPresentedViewController.dismissAsync(animated: true)
}
}
var topPresentedViewController: UIViewController {
var result = self
while result.presentedViewController != nil {
result = result.presentedViewController!
}
return result
}
Here is a simple main.swift file of a macOS app:
import SwiftUI
struct ContentView: View {
@State private var selectedItem = 0
@FocusState private var isListFocused: Bool
var body: some View {
List(0..<40, id: \.self, selection: $selectedItem) { index in
Text("\(index)")
.padding()
.focusable()
}
.focused($isListFocused)
.onAppear {
isListFocused = true
}
}
}
func createAppWindow() {
let window = NSWindow(
contentRect: .zero,
styleMask: [.titled],
backing: .buffered,
defer: false
)
window.contentViewController = NSHostingController(rootView: ContentView())
window.setContentSize(NSSize(width: 759, height: 300))
window.center()
window.makeKeyAndOrderFront(nil)
}
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
createAppWindow()
}
}
let delegate = AppDelegate()
NSApplication.shared.delegate = delegate
NSApplication.shared.run()
Try to move the focus with a keyboard slowly as shown on the GIF attached and you'll see that the focus items don't sit in a List's view.
Below is a basic test app to resemble an actual app I am working on to hopefully better describe an issue I am having with tab view. It seems only in split screen when I am triggering something onAppear that would cause another view to update, or another view updates on its own, the focus gets pulled to that newly updated view instead of staying on the view you are currently on. This seems to only happen with views that are listed in the more tab. In any other orientation other than 50/50 split this does not happen. Any help would be appreciated.
struct ContentView: View {
@State var selectedTab = 0
var body: some View {
NavigationStack {
NavigationLink(value: 0) {
Text("ENTER")
}.navigationDestination(for: Int.self) { num in
TabsView(selectedTab: $selectedTab)
}
}
}
}
struct TabsView: View {
@Binding var selectedTab: Int
@State var yikes: Int = 0
var body: some View {
if #available(iOS 18.0, *) {
TabView(selection: $selectedTab) {
MyFlightsView(yikes: $yikes)
.tabItem {
Label("My Flights", systemImage: "airplane.circle")
}.tag(0)
FlightplanView()
.tabItem {
Label("Flight Plan", systemImage: "doc.plaintext")
}.tag(1)
PreFlightView()
.tabItem {
Label("Pre Flight", systemImage: "airplane.departure")
}.tag(2)
CruiseView(yikes: $yikes)
.tabItem {
Label("Cruise", systemImage: "airplane")
}.tag(3)
PostFlightView()
.tabItem {
Label("Post Flight", systemImage: "airplane.arrival")
}.tag(4)
MoreView()
.tabItem {
Label("More", systemImage: "ellipsis")
}.tag(5)
NotificationsView()
.tabItem {
Label("Notifications", systemImage: "bell")
}.tag(6)
}.tabViewStyle(.sidebarAdaptable)
}
}
}
I released an app for iPhone (and it's could be downloaded for iPad also), and now I developered another app for iPad version with the same code and logic but I modified the layout to fit bigger screen and make better user experience and appearance.
Howevert the app review rejected my release due to the duplicate content, how can I solve it?
Topic:
UI Frameworks
SubTopic:
General
I am running into an issue where two distinct bool bindings are both being toggled when I toggle only one of them. My component looks like
VStack {
Checkbox(label: "Checkbox 1", isOn: $stateVar1)
Checkbox(label: "Checkbox 2", isOn: $stateVar2)
}
where my CheckBox component looks like
struct Checkbox: View {
let label: String
@Binding var isOn: Bool
var body: some View {
Button {
isOn.toggle()
} label: {
HStack {
Image(systemName: isOn ? "checkmark.square" : "square")
Text(label)
}
.foregroundStyle(.black)
}
}
}
If I click on one checkbox, both of them get toggled. However, if I simply remove the checkboxes from the VStack, then I am able to toggle them both independently. I believe this is a bug with bool Bindings, but if anyone can point out why I am mistaken that would be much appreciated :)
Topic:
UI Frameworks
SubTopic:
SwiftUI
I'm implementing a Map with user location customization in SwiftUI using iOS 17+ MapKit APIs. When using the selection parameter with Map, the default blue dot user location becomes tappable but shows an empty annotation view. However, using UserAnnotation makes the location marker non-interactive.
My code structure:
import SwiftUI
import MapKit
struct UserAnnotationSample: View {
@State private var position: MapCameraPosition = .userLocation(fallback: .automatic)
@State private var selectedItem: MapSelection<MKMapItem>?
var body: some View {
Map(position: $position, selection: $selectedItem) {
// UserAnnotation()
}
.mapControls {
MapUserLocationButton()
}
}
}
Key questions:
How can I replace the empty annotation view with a custom avatar when tapping the user location?
Is there a way to make UserAnnotation interactive with selection?
Should I use tag modifier for custom annotations? What's the proper way to associate selections?
I have a NSViewController as the root view and have a switui view embedded in it via NSHostingView.
override func loadView() {
self.view = NSHostingView(rootView: SwiftUiView())
}
}
In the SwiftUiView, I have a TextField and an NSTextView embedded using NSViewRepresentable, along with a few buttons. There is also a menu:
Menu {
ForEach(menuItems), id: \.self) { item in
Button {
buttonClicked()
} label: {
Text(item)
}
}
} label: {
Image("DropDown")
.contentShape(Rectangle())
.frame(maxWidth: .infinity)
.frame(maxHeight: .infinity)
}
The NSTextView and TextField work fine, and I can type in them until I click on the menu or show an alert. After that, I can no longer place my cursor in the text fields. I am able to select the text but not type in it. When I click on the NSTextView or TextField, nothing happens.
At first, I thought it was just a cursor visibility issue and tried typing, but I received an alert sound. I've been trying to fix this for a couple of days and haven't found any related posts. Any help would be greatly appreciated.
Hi,
I have few questions regarding the widgets.
I would like to know whether widget and app extensions are same ? This link(https://developer.apple.com/app-extensions/) says widget is type of app extension but I am not quite sure as few link in web says they are different. so need to confirm here :)
Can a widget share same bundle id as the main app ? so basically can we use the same provisioning profile as the main app?
If we use the same bundle id and provisioning profile, will there be any issue during the app store submission process.?
Our Apple TV provides UIImages with renderingMode forced to .alwaysTemplate (the images are also configured with "Render As" to "Template image" in the Asset catalog) to UIActions as UIMenuElement when building a UICollectionView UIContextMenuConfiguration.
Problem: these images are not displayed with vibrancy effect by the system.
The issue does not occur with system images (SVG from SF Catalog).
Here is a screenshot showing the issue with custom images ("Trailer" and "Remove from favourites"):
I don't know the underlying implementation of the context menu items image but UIImageView already implements the tintColorDidChange() method and the vibrancy should work if the UIImage is rendered as template.
According to my tests, the vibrancy is correctly applied when using Symbols sets instead of Images sets but I understand that custom images rendered as template should support it as-well, shouldn't they?
When I toggle a panel like navigationsidebar, I get a message in the console. I guess it's not a big issue, but is there a way to fix this message? because it appears in every project.
Unable to open mach-O at path: /AppleInternal/Library/BuildRoots/d187757d-b9a3-11ef-83e5-aabfac210453/Library/Caches/com.apple.xbs/Binaries/RenderBox/install/TempContent/Root/System/Library/PrivateFrameworks/RenderBox.framework/Versions/A/Resources/default.metallib Error:2
Hello everyone. Can someone please help me. I am completely lost and have exhausted everything I know to do. I have a Navigation View with a list inside of it. For some reason, there is a gray background behind my list. I'm assuming this is due to some type of padding with the Navigation View but I can't seem to be able to adjust the background or change it to clear. I have attached an image of what I'm mentioning to hopefully better explain. You will see the green bar at the top. that is the background of another view behind this view. I want to either fully cover the screen with the gray background or remove it completely.
Topic:
UI Frameworks
SubTopic:
SwiftUI
TLDR: Applying a clipShape in a hoverEffect closure is preventing taps from getting through to buttons nested within an ornament.
I need to make a custom ornament menu, similar to the stock ornament available via TabView but with some visual tweaks. It displays icons, and then expands to display a label as the user hovers. Example:
I've put together a piece of sample code, following guidance from WWDC docs:
VStack {
}
.ornament(attachmentAnchor: .scene(.leading)) {
VStack {
ForEach(0...7, id:\.self) { index in
Button(action: {
print(index) // <---- This will not print
}) {
HStack {
Text("\(index)")
Text(" button")
}
}
}
}
.padding(12)
.glassBackgroundEffect()
.hoverEffect { effect, isActive, proxy in
effect
.clipShape(RoundedRectangle(cornerRadius: 36)
.size(width: isActive ? proxy.size.width : 72, height: proxy.size.height, anchor: .leading)
)
}
}
}
The buttons in this code cannot be interacted with, as the print statement never executes. What am I missing here? I've managed to get some weird behavior, sometimes a specific clipShape (like a circle) will allow a tap on a single button, but not others.
I have a SwiftUI View I've introduced to a UIKit app, using UIHostingController. The UIView instance that contains the SwiftUI view is animated using auto layout constraints. In this code block, when a view controller's viewDidAppear method I'm creating the hosting controller and adding its view as a subview of this view controller's view, in addition to doing the Container View Controller dance.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let hostingViewController = UIHostingController(rootView: TestView())
hostingViewController.view.translatesAutoresizingMaskIntoConstraints = false
addChild(hostingViewController)
view.addSubview(hostingViewController.view)
let centerXConstraint = hostingViewController.view.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let topConstraint = hostingViewController.view.topAnchor.constraint(equalTo: view.topAnchor)
widthConstraint = hostingViewController.view.widthAnchor.constraint(equalToConstant: 361)
heightConstraint = hostingViewController.view.heightAnchor.constraint(equalToConstant: 342)
NSLayoutConstraint.activate([centerXConstraint, topConstraint, widthConstraint, heightConstraint])
hostingViewController.didMove(toParent: self)
self.hostingViewController = hostingViewController
}
I add a button to the UI which will scale the UIHostingViewController by adjusting its height and width constraints. When it's tapped, this action method runs.
@IBAction func animate(_ sender: Any) {
widthConstraint.constant = 120.3
heightConstraint.constant = 114.0
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}
The problem is, the SwiftUI view's contents "jump" at the start of the animation to the final height, then animate into place. I see this both using UIView.animate the UIKit way, or creating a SwiftUI animation and calling `UIView.
What else do I need to add to make this animate smoothly?
I have an app that run Monte Carlo simulations. I run thousands of simulations in the app and a simulation runs can take on the order of 30 seconds to a minute to complete. I would like to have a progress view that tracks the number of simulation runs. How can I implement this in swiftui?
The behavior of the Button in ScrollView differs depending on how the View is displayed modally.
When the View is displayed as a .fullScreenCover, if the button is touched and scrolled without releasing the finger, the touch event is canceled and the action of the Button is not called.
On the other hand, if the View is displayed as a .sheet, the touch event is not canceled even if the view is scrolled without lifting the finger, and the action is called when the finger is released.
In order to prevent accidental interaction, I feel that the behavior of .fullScreenCover is better, as it cancels the event immediately when scrolling. Can I change the behavior of .sheet?
Demo movie is here:
https://x.com/kenmaz/status/1896498312737611891
Sample code
import SwiftUI
@main
struct SampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var showSheet = false
@State private var showFullScreen = false
var body: some View {
VStack(spacing: 16) {
Button("Sheet") {
showSheet.toggle()
}
Button("Full screen") {
showFullScreen.toggle()
}
}
.sheet(isPresented: $showSheet) {
SecondView()
}
.fullScreenCover(isPresented: $showFullScreen) {
SecondView()
}
.font(.title)
}
}
struct SecondView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
ScrollView {
Button("Dismiss") {
dismiss()
}
.buttonStyle(MyButtonStyle())
.padding(.top, 128)
.font(.title)
}
}
}
private struct MyButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration
.label
.foregroundStyle(.red)
.background(configuration.isPressed ? .gray : .clear)
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
I want to keep the sidebar fixed in NavigationSplitView. I don’t want the user to be able to open or close the sidebar. I removed the toggle button, but I still couldn’t make the sidebar stay fixed. It can still be closed using Cmd + Alt + S or by dragging.
What I want is just to disable the resize feature of the sidebar. Isn’t it possible with SwiftUI?
NavigationSplitView is kind of blackhole :)
LeftSidebarView()
.environmentObject(detailView)
.toolbar(removing: .sidebarToggle)
.navigationSplitViewColumnWidth(240)
TLDR: What rules ensure you won't have sporadic run-time crashes when using ViewThatFits?
My app crashes - luckily reproducible. But the code appeared syntacticly and logically correct.
Simplified excerpt:
https://github.com/alanrick/Experiment3
The crash is caused by ViewThatFits being overwhelmed by concurrent changes in other views, exacerbated by animation effects. In the original code the problem was even worse because I'd gone overboard and used ViewThatFits in sub-views making the whole thing too dynamic.
My first rule is:
Do not use nested ViewThatFits.
But this alone is not sufficient. What other rules can I apply to ensure I won't have hard-to-detect run-time crashes when using ViewThatFits?
Topic:
UI Frameworks
SubTopic:
SwiftUI
I have a scrollview displaying a sequence of circles, which a user should be able to scroll through to select an item. When the user stops scrolling and the animation comes to rest the circle selected should display screen-centered.
I had hoped to achieve this using .scrollPosition(id: selectedItem, anchor: .center) but it appears that the anchor argument is ignored when scrolled manually. (BTW - I searched but didn't locate this aspect in the Apple documentation so I'm not confident that this observation is really correct).
https://youtu.be/TpXDTuL5yPQ
The video shows the user-scrolling behaviour, and also the snap-to-anchor that I would like to achieve, but I would like this WITHOUT forcing a button press.
I could juggle the container size and size of the circles so that they naturally fit centered into the screen, but I would prefer a more elegant solution.
How can I force the scrolling to come to rest such that the circle glides to rest in the center of the screen/container?
struct ItemChooser: View {
@State var selectedItem: Int?
var body: some View {
VStack {
Text("You have picked: \(selectedItem ?? 0)")
ScrollHorizontalItemChooser(selectedItem: $selectedItem)
}
}
}
#Preview {
ItemChooser(selectedItem: 1)
}
struct ScrollHorizontalItemChooser: View {
@Binding var selectedItem: Int?
@State var scrollAlignment: UnitPoint? = .center
let ballSize: CGFloat = 150
let items = Array(1...6)
@State var scrollPosition: ScrollPosition = ScrollPosition()
var body: some View {
VStack {
squareUpButton
ScrollView(.horizontal) {
HStack(spacing: 10) {
showBalls
}
.scrollTargetLayout()
}
.scrollPosition(id: $selectedItem, anchor: scrollAlignment )
.overlay{ crosshairs } }
}
var crosshairs: some View {
Image(systemName: "scope").scaleEffect(3.0).opacity(0.3)
}
@ViewBuilder
var showBalls: some View {
let screenWidth: CGFloat = UIScreen.main.bounds.width
var emptySpace: CGFloat {screenWidth / 2 - ballSize / 2 - 10}
Spacer(minLength: emptySpace)
ForEach(items, id: \.self) { item in
poolBall( item)
.id(item)
}
Spacer(minLength: emptySpace)
}
@ViewBuilder
private func poolBall(_ item: Int) -> some View {
Text("Item \(item)")
.background {
Circle()
.foregroundColor(Color.green)
.frame(width: ballSize, height: ballSize)
}
.frame(width: ballSize, height: ballSize)
}
@ViewBuilder
var squareUpButton: some View {
var tempSelected: Int? = nil
Button("Square up with Anchor") {
tempSelected = selectedItem
selectedItem = 0
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
selectedItem = tempSelected ?? 0
}
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hey,
Anyone knows of a possible way to present a PasteButton in a .confirmationDialog on iOS?
when I try adding it, it's ignored and not displayed with the rest of the buttons
struct MyView: View {
@State var flag: Bool = false
var body: some View {
Text("Some Text")
.confirmationDialog("Dialog", isPresented: $flag) {
Group {
Button("A") {}
Button("B") {}
PasteButton(payloadType: Data.self) { data in
}
}
}
}
}