Hi,
I have an existing AppKit-based Mac app that I have been working on for a few years. For a new feature, I wanted to have the app opened by a different app, so I setup the URL scheme under CFBundleURLTypes in my Info.plist, and adopted this delegate callback:
- (void)application: (NSApplication *)application openURLs:(nonnull NSArray<NSURL *> *)urls
Now when I invoke the URL from the 2nd app, it opens my app correctly, BUT this delegate method isn't called. What's interesting is that if I make a totally new app with a URL scheme and adopt this delegate method, it gets called without a problem!
SO what about my original project could be responsible for this 'opensURLs' method to not be called? I've been searching for a solution for a couple of days without any luck. The macOS app's target has a Deployment Target of 10.15 and I'm running this on macOS12.0 with Xcode 13.
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
There are two issues about SFSafariViewController.
After rotate from landscape to portrait,
The topAnchor is destroyed.
The specified bar tint color and control tint color are invalidated.(Returns to system color)
Regarding the second issue, I’ve found a temporary workaround.
Override the viewWillTransition(to:with:) and keep it empty. Don't call super.viewWillTransition(to:with:).
Since UIKit is not open source, I don’t know the exact cause, but I found something that could be the key to the issue. So, I reported it to Apple Feedback Assistant. You can check the details and the sample project in the GitHub repository below.
https://github.com/ueunli/SafariViewer
I'm testing using Group Activities and having no trouble iOS<->iOS or starting an activity on macOS and joining via iOS. However, when I start an activity and then try to join it from another macOS client, the starting side joins the session just fine, but the receiving side acts like I don't have the required app, even when it is already running.
I see the active SharePlay icon in the menu bar, and the Current Activity is shown, but instead of an "Open" button there is a "MyApp Required" string and a "View" button that goes to the App Store. (Where the app is not available yet, as expected, since I'm still working on it.) There is no GroupSession started on that Mac yet, obviously.
I'm looking for any hints to help debug what is going on. How does Group Activities find the app for the activity on macOS and how can I figure out why it isn't finding mine?
Thanks!
In one of my applications I use several List views with Sections. After upgrading to Sequoia I faced the issue, that after selecting an item, the List suddenly scrolls to a different position. Sometimes the selection even gets out of the view, but in every case a double click just went to the wrong item.
At one list I found out, that the issue could be solved after changing the data source. I used a computed property, what seems to be a stupid idea. After changing this it now works.
Unfortunately there is another List, where this didn't bring the solution. And unfortunately, I cannot reproduce the issue in a code example. One guess of mine is, that it could be related to the fact, that the rows have different heights (because in some are two lines of text and in some are three). And it seems to happen only in very long lists.
It worked perfectly in Sonoma.
Does anyone face the same issue?
Topic:
UI Frameworks
SubTopic:
SwiftUI
How do I draw a single line of text in a SwiftUI Canvas, scaled to fill a given rectangle?
Example:
Canvas { context, size in
let r = CGRect(origin: CGPointZero, size: size); // Whole canvas
let t = Text("Hello World");
context.draw(t, in: r);
}
Outside of Canvas I'd add .minimumScaleFactor(0) .lineLimit(1), and I guess set a large default font size, and I'd get the result I want.
But inside Canvas, .minimumScaleFactor and .lineLimit don't seem to be available; they return some View, not Text, which can't be used in context.draw. (Is there a trick to make that work?)
I have written the following to do this, but I think there must be an easier way to achieve this! Suggestions?
extension GraphicsContext {
mutating func draw_text_in_rect(string: String, rect: CGRect)
{
let text = Text(string) .font(.system(size: 25));
// The font size used here does matter, because e.g. letter spacing
// varies with the font size.
let resolved = resolve(text);
let text_size = resolved.measure(in: CGSize(width: CGFloat.infinity, height: CGFloat.infinity));
let text_aspect = text_size.width / text_size.height;
let fit_size = CGSize(width: min(rect.size.width, rect.size.height*text_aspect),
height: min(rect.size.height, rect.size.width/text_aspect));
let fit_rect = CGRect(x: rect.origin.x + (rect.size.width-fit_size.width)/2,
y: rect.origin.y + (rect.size.height-fit_size.height)/2,
width: fit_size.width,
height: fit_size.height);
let scale = fit_size.width / text_size.width;
// For debug:
// var p = Path();
// p.addRect(fit_rect);
// stroke(p, with: GraphicsContext.Shading.color(.red), lineWidth: 1);
translateBy(x: fit_rect.minX, y: fit_rect.minY);
scaleBy(x:scale, y:scale);
draw(resolved, at: CGPointZero, anchor: UnitPoint.topLeading);
transform = CGAffineTransformIdentity;
}
};
I can't shake the "I don't think I did this correctly" feeling about a change I'm making for Image Playground support.
When you create an image via an Image Playground sheet it returns a URL pointing to where the image is temporarily stored. Just like the Image Playground app I want the user to be able to decide to edit that image more.
The Image Playground sheet lets you pass in a source URL for an image to start with, which is perfect because I could pass in the URL of that temp image.
But the URL is NOT optional. So what do I populate it with when the user is starting from scratch?
A friendly AI told me to use URL(string: "")! but that crashes when it gets forced unwrapped.
URL(string: "about:blank")! seems to work in that it is ignored (and doesn't crash) when I have the user create the initial image (that shouldn't have a source image).
This feels super clunky to me. Am I overlooking something?
I'm working on a SwiftUI based application for MacOS. I have a TabView component with two child Tab components. These Tab components display a List, each derived from an array of elements.
While the application is running, clicking on the tabs in the TabView should switch between the views of different Lists. What I'm experiencing is that switching between the tabs causes a FAULT. With errors:
Row index 1 out of row range (numberOfRows: 1) for <SwiftUI.SwiftUIOutlineListView: 0x1299d2000>
Followed by:
(
0 CoreFoundation 0x000000019e096e80 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x000000019db7ecd8 objc_exception_throw + 88
2 AppKit 0x00000001a1c744e8 -[NSTableRowData _availableRowViewWhileUpdatingAtRow:] + 0
3 SwiftUI 0x00000001cd8953f4 $s7SwiftUI0A17UIOutlineListViewC11removeItems2at8inParent13withAnimationy10Foundation8IndexSetV_ypSgSo07NSTableeL7OptionsVtF + 1232
...
...
)
And finally:
FAULT: NSTableViewException: Row index 1 out of row range (numberOfRows: 1) for <SwiftUI.SwiftUIOutlineListView: 0x1299d2000>; (user info absent)
This error happens when switching between the two tabs, defined thusly:
@main
struct MyApp: App {
@State var rootDirectory: URL
@State var selectedItem: URL
@State var projectNavItems: [NavigationItem] = []
@State var jotNavItems: [NavigationItem] = []
@State var importerIsPresented: Bool = false
let fileManager = FileManager.default
init() {
rootDirectory = URL(string: FileManager.default.currentDirectoryPath)!
selectedItem = URL(string: FileManager.default.currentDirectoryPath)!.appendingPathComponent("README.md")
}
var body: some Scene {
WindowGroup {
NavigationSplitView {
TabView {
Tab("Projects", systemImage: "tray.and.arrow.down.fill") {
List(projectNavItems, selection: $selectedItem) {
// Changing this NavigationLink line to Text($0.title) makes no difference
NavigationLink($0.title, value: $0.id)
}
}
Tab("Jots", systemImage: "tray.and.arrow.up.fill") {
List(jotNavItems, selection: $selectedJot) {
// Can be written as Text($0.title) with no change in behavior
NavigationLink($0.title, value: $0.id)
}
}
}
} detail: {
Editor(for: selectedItem)
}
.fileImporter(
isPresented: $importerIsPresented,
allowedContentTypes: [UTType.folder],
allowsMultipleSelection: false
) { result in
// Code that gets a security scoped resource and populates the
// projectNavItems: [NavItem] and jotNavItems: [NavItem]
// arrays
}
}
.commands(content: {
CommandGroup (before: .newItem) {
Button("Open Journal...") {
importerIsPresented.toggle()
}
}
})
}
}
The error only happens when both Tab views are populated by a List. If the Tab view have different child components, say a List, and a ForEach of Text components, switching between the tabs doesn't produce this error. List views with Text child components also produce this error.
Here are screenshots of the running application
Once the user selects a directory, we see the first Tab > List component populated by contents from the projectNavItems array:
Clicking on the 'Jots' tab switches to the appropriate tab and correctly lists the items in the jotNavItems array, except there are additional lines, seemingly showing that there's an issue.
Clicking back on the 'Projects' tab switches back, but now the List shows only one of the items from the projectNavItems array.
Finally, clicking on 'Jots' again causes the errors to print in the console and interactivity with the tab components ceases. Last screenshot is representative of this state as the application FAULTS.
This seems like a bug in SwifUI, wondering what workarounds I might be able to implement.
I can provide the full backtrace, I cropped it for content length.
As SwiftUI adoption grows, developers face challenges in effectively measuring and optimizing SwiftUI app performance within automated tests.
Currently, the only viable approach to analyzing SwiftUI performance is through Profiling (Instruments), which, while powerful, lacks the ability to be incorporated into automated testing workflows. It would be incredibly valuable if XCTest could introduce new performance metrics specifically tailored for SwiftUI, allowing us to write tests against common performance bottlenecks.
Suggested Metrics:
View Body Evaluation Count – Tracks how often a SwiftUI body is recomputed to detect unnecessary re-renders.
Slow View Bodies – Flags SwiftUI views that take a significant amount of time to compute their body.
These metrics would help developers identify inefficiencies early, enforce performance best practices through CI/CD pipelines, and ensure a smooth user experience. I believe adding these performance metrics would be a game-changer for SwiftUI development.
Thank you for your time and consideration!
Description
I'm developing a tvOS application where I utilize a UISearchController embedded within a UISearchContainerViewController for search functionality. In a particular flow, a custom view controller contains a TVDigitEntryViewController as a child, with its modalPresentationStyle set to .blurOverFullScreen. The issue arises when a user initiates the PIN entry but decides to cancel and return to the search interface without entering a PIN. Upon returning, the search keyboard is no longer visible, and attempts to focus or interact with it are unsuccessful.
Steps to Reproduce
Initialize and present a UISearchContainerViewController that contains a UISearchController with a results view controller.
Within the search results, present a custom view controller containing TVDigitEntryViewController as a child, setting its modalPresentationStyle to .blurOverFullScreen.
Dismiss the custom view controller without entering a PIN (e.g., by pressing the Menu button on the remote).
Observe that upon returning to the search interface, the keyboard is missing, and focus interactions are unresponsive.
Observed Behavior
After dismissing the custom view controller with TVDigitEntryViewController, the search keyboard does not reappear, and the focus system seems to lose track of the search input field.
Expected Behavior
The search keyboard should remain visible and functional after dismissing the custom view controller, allowing users to continue their search without interruption.
Additional Context
I have reviewed the TVDigitEntryViewController documentation (developer.apple.com) and related discussions on the Apple Developer Forums but have not found a solution to this specific issue.
Questions
Has anyone encountered a similar issue or have insights into why the search keyboard becomes unresponsive after dismissing a .blurOverFullScreen modal with a child TVDigitEntryViewController?
Are there recommended practices to ensure the search keyboard remains active and focusable after such modal presentations?
Any guidance or suggestions would be greatly appreciated. Thank you!
I’m encountering an issue with SwiftUI navigation in iOS 18, where navigating to a DetailView causes unexpected duplication of navigation behavior when @Environment(.dismiss) is used.
Code Example: Here’s a simplified version of the code:
struct ContentView: View {
var body: some View {
NavigationStack {
NavigationLink("Go to Detail View", destination: DetailView())
.padding()
}
}
}
struct DetailView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
VStack {
let _ = print("DetailView") // This print statement is triggered twice in iOS 18
}
}
}
Issue:
In iOS 18, when @Environment(.dismiss) is used in DetailView, the print("DetailView") statement is triggered twice.
The same code works correctly in iOS 17 and earlier, where the print statement is only triggered once, as expected.
However, when I remove @Environment(.dismiss) from DetailView, the code works as intended in iOS 18, with the print statement being triggered only once and no duplication of navigation behavior.
Alternative Approach with .navigationDestination(for:): I also tested using .navigationDestination(for:) to handle navigation:
struct ContentView: View {
var body: some View {
NavigationStack {
NavigationLink("Go to Detail View", destination: DetailView())
.padding()
}
}
}
struct DetailView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
VStack {
let _ = print("DetailView") // This print statement is triggered twice in iOS 18
}
}
}
Even with this alternative approach, the issue persists in iOS 18, where the print statement is triggered twice.
What I've Tried:
I’ve confirmed that removing @Environment(.dismiss) solves the issue, and the print statement is triggered only once, and the navigation works as expected in iOS 18 without duplication.
The issue only occurs when @Environment(.dismiss) is in use, which seems to be tied to the navigation stack behavior. The code works correctly in iOS 17 and below, where the print statement is only called once.
Expected Behavior:
I expect the print("DetailView") statement to be called once when navigating to DetailView, and that the navigation happens only once without duplication. The presence of @Environment(.dismiss) should not cause the navigation to be triggered multiple times.
Questions:
Is this a known issue with iOS 18 and SwiftUI navigation? Specifically, is there a new behavior that interacts differently with @Environment(.dismiss)?
Has anyone else encountered this problem, and if so, what’s the recommended way to handle it in iOS 18?
Is there a workaround to ensure that the navigation doesn’t trigger more than once when using @Environment(.dismiss) in iOS 18?
Any help or insights would be greatly appreciated!
in ios it is not same as it in computer
there is text:"ยินดี
in computer is
but in ios it is
the fontsize is 16
I tried every font which is in ios and tried copy simsun in windows to ios and create CTFont
I draw it using UIGraphics drawString
Here is the reproducible codes:
struct JumpView: View {
var body: some View {
NavigationStack {
TabView {
Text("Jump")
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Done") {}
}
}
}
}
}
}
Run directly in real apple watch device in watchOS 10.0+ (do not debug connecting with Xcode).
When raise your wrist the ToolBar Button will jump weirdly.
I would like to report a memory leak issue in watchOS 11.2 that occurs when using .navigationTitle() inside a sheet. This behavior is reproducible both on the simulator and on a real device, but not on iOS. While this does not register as a leak in Instruments, the deinit of the DetailsViewModel is never called, and multiple instances of the view model accumulate in the Memory Graph Debugger. Commenting out .navigationTitle("Sheet View") resolves the issue, and deinit prints as expected. Using @MainActor on the DetailsViewModel does not fix the issue. Nor does switching to @StateObject and using ObservableObject resolve the memory retention.
This issue seems related to other SwiftUI memory leaks that have been reported:
https://developer.apple.com/forums/thread/738840
https://developer.apple.com/forums/thread/736110?login=true&page=1#769898022
https://developer.apple.com/forums/thread/737967?answerId=767599022#767599022
Feedback Number: FB16442048
struct MainView: View {
var body: some View {
NavigationStack {
NavigationLink("Details", value: 1)
.navigationDestination(for: Int.self) { _ in
DetailsView()
}
}
}
}
struct SheetObject: Identifiable {
let id = UUID()
let date: Date
let value: Int
}
@Observable
@MainActor
final class DetailsViewModel {
var sheetObject: SheetObject?
init() {
print("Init")
}
deinit {
print("Deinit")
}
func onAppear() async {
try? await Task.sleep(for: .seconds(2))
sheetObject = .init(date: .now, value: 1)
}
}
struct DetailsView: View {
@State private var viewModel = DetailsViewModel()
@Environment(\.dismiss) var dismiss
var body: some View {
Text("Detail View. Going to sheet, please wait...")
.task {
await viewModel.onAppear()
}
.sheet(item: $viewModel.sheetObject) { sheetObject in
SheetView(sheetObject: sheetObject)
.onDisappear {
dismiss()
}
}
}
}
struct SheetView: View {
let sheetObject: SheetObject
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationStack {
VStack {
Text(sheetObject.date.formatted())
Text(sheetObject.value.formatted())
Button("Dismiss") {
dismiss()
}
}
.navigationTitle("Sheet View") // This line causes a memory leak. Commenting out, you will see "Deinit" be printed.
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hi,
A class initialized as the initial value of an @State property is not released until the whole View disappears. Every subsequent instance deinitializes properly.
Am I missing something, or is this a known issue?
struct ContentView: View {
// 1 - init first SimpleClass instance
@State var simpleClass: SimpleClass? = SimpleClass(name: "First")
var body: some View {
VStack {
Text("Hello, world!")
}
.task {
try? await Task.sleep(for: .seconds(2))
// 2 - init second SimpleClass instance and set as new @State
// "First" should deinit
simpleClass = SimpleClass(name: "Second")
// 3 - "Second" deinit just fine
simpleClass = nil
}
}
}
class SimpleClass {
let name: String
init(name: String) {
print("init: \(name)")
self.name = name
}
deinit {
print("deinit: \(name)")
}
}
output:
init: First
init: Second
deinit: Second
Thanks
can't see what the problem is .. Im getting the error:
Type '()' cannot conform to 'View'
struct CalendarView: View {
@StateObject private var viewModel = CalendarViewModel()
@State private var selectedDate: CalendarDate?
@State private var showModal = false
var body: some View {
VStack {
Text("Calendar App")
.font(.largeTitle)
.padding()
GridStack(rows: 5, columns: 7) { row, col in
let index = row * 7 + col
if index < viewModel.calendarDates.count {
let calendarDate = viewModel.calendarDates[index]
Text("\(Calendar.current.component(.day, from: calendarDate.date))")
.frame(width: 40, height: 40)
.background(calendarDate.isSelected ? Color.blue : Color.clear)
.cornerRadius(10)
.foregroundColor(calendarDate.isSelected ? Color.white : Color.black)
.onLongPressGesture {
selectedDate = calendarDate
showModal = true
}
}
}
}
.background(Color.gray)
.sheet(isPresented: $showModal) {
if let date = selectedDate {
DateSelectionModal(selectedDate: date)
}
}
}
}
struct GridStack<Content: View>: View {
let rows: Int
let columns: Int
let content: (Int, Int) -> Content
var body: some View {
VStack {
ForEach(0..<rows) { row in
HStack {
ForEach(0..<columns) { column in
content(row, column)
}
}
}
}
}
}
#Preview {
CalendarView()
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
In Apple's Maps app, an annotation is made up of a circle shape or rounded rectangles with a glyph-image.
When selecting an annotation, the annotation animates into a balloon marker (see attached GIF).
How does Apple Maps solve this - from custom annotation to balloon marker with spring animation?
I switched my Maps implementation from SwiftUI to UIKit with a UIViewRepresentable to support annotation clustering - and it works beautifully.
But how to subclass an MKAnnotationView (or MKMarkerAnnotationView <- the balloon) to enable selection and animation as in Apple Maps?
MKMarkerAnnotationView only show balloon markers and I tried everything inside MKAnnotationView (CALayer, etc.)
I have a Form with a custom TextField which uses a custom Text().
When I use .alignmentGuide on the Text() it seems the origin reference point varies with the length of, but not by the length of, the TextField label String. This is a problem when in a Form. My workaround has been to not use a TextField label but enclose the each TextField in a LabeledContent and then I can set the width of the label and align off of that.
How does Form cause TextField to set it's width and why if using .alignmentGuide on Text() does the TextField label length even matter?
Topic:
UI Frameworks
SubTopic:
SwiftUI
I have an app which uses Scene
var body: some Scene {
WindowGroup {
RootView(root: appDelegate.root)
.edgesIgnoringSafeArea(.all)
.onOpenURL { url in
let stringUrl = url.absoluteString
if (stringUrl.starts(with: "http")) {
handleUniversalLink(url: stringUrl)
} else if (stringUrl.starts(with: "fb")) {
let _ = ApplicationDelegate.shared.application(
UIApplication.shared,
open: url,
sourceApplication: nil,
annotation: [UIApplication.OpenURLOptionsKey.annotation])
}
}
}
}
I need to detect when a user taps on status bar. And call some functions when he does it. Is it possible in Swift?
Topic:
UI Frameworks
SubTopic:
SwiftUI
I'm getting the following error Error Domain=com.google.GIDSignIn Code=-4. How do I find out what I'm missing with my setup of Google Cloud?
Topic:
UI Frameworks
SubTopic:
SwiftUI
In iOS 18 widget, button is broken when it's has an accented desaturated image as content, the button's AppIntent will not trigger perform function.
checkout the code below:
`
struct WidgetExtEntryView : View {
var entry: Provider.Entry
var body: some View {
VStack {
Text("count:")
Text("\(WidgetExtAppIntent.count)")
HStack {
// button can not be tapped
Button(intent: WidgetExtAppIntent(action: "+1")) {
VStack {
Image(systemName: "plus.square.fill").resizable()
.widgetAccentedRenderingMode(.accentedDesaturated) // <-- here
.frame(width: 50, height: 50)
Text("Broken")
}
}.tint(.red)
// button can be tapped
Button(intent: WidgetExtAppIntent(action: "+1")) {
VStack {
Image(systemName: "plus.square.fill").resizable()
.widgetAccentedRenderingMode(.fullColor) // <-- here
.frame(width: 50, height: 50)
Text("OK").frame(width: 50, alignment: .center)
}
}.tint(.green)
}
.minimumScaleFactor(0.5)
}
}
}
`
check out the full demo project: ButtonInWidgetBrokenIOS18