I'm playing around with using an app to automate some of my personal work flows, and one of the things I wanted to do was to be able to drag a .webloc file onto my app icon in the dock, to launch it.
I've got public.data set up as a document type for it in Xcode, which translated to
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Default</string>
<key>LSItemContentTypes</key>
<array>
<string>public.data</string>
</array>
</dict>
</array>
in the Info.plist for it, which seems correct. When I drag a .webloc file onto the Dock icon, it appears to be willing to accept it, but nothing seems to happen.
In the app, I've got an AppDelegate.swift file which has
extension Notification.Name {
static let receivedURLsNotification = Notification.Name("ReceivedURLsNotification")
}
class AppDelegate: NSObject, NSApplicationDelegate {
func application(_ application: NSApplication, open urls: [URL]) {
guard !urls.isEmpty else { return }
NotificationCenter.default.post(name: .receivedURLsNotification, object: nil, userInfo: ["URLs": urls])
}
}
(I copied it almost verbatim from a Medium post.)
In the app swift file, I have
@main
struct LoggerApp: App, DropDelegate {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
I set a breakpoint on application(_:NSApplication, open:[URL]), and did my drag, and the breakpoint never triggered.
I added the application(didFinishLaunching(_:Notification) method, and that does get invoked when the app launches, so the app delegate does seem to be working. That seems to indicate the problem is somewhere else?
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
Hi!
SiriTipView(intent:) shows the first phrase for my App Shortcut, but unlike ShortcutsLink(), does not use the localized applicationName. Hence the phrase shown does not work π¬
Is this a known limitation, any workarounds?
I have implemented a Live Activity with Dynamic Island support for my charging app. Currently, the Dynamic Island expands when tapped, but I want to disable this interaction completely. Here's my current implementation:
**dynamicIsland: { context in
DynamicIsland {
// Expanded Regions
DynamicIslandExpandedRegion(.leading) {
// Leading expanded content
}
DynamicIslandExpandedRegion(.trailing) {
// Trailing expanded content
}
DynamicIslandExpandedRegion(.bottom) {
// Bottom expanded content
}
} compactLeading: {
// Compact leading view content
} compactTrailing: {
// Compact trailing view content
} minimal: {
// Minimal view content
}
.keylineTint(Color.clear)
}**
In the code below, changes to the destination value aren't captured by ViewA if:
ViewB is navigated to by changing the destination property of ViewModel.
ViewA is embedded in a NavigationLink or another navigationDestination.
For example, the return button in ViewB doesn't work when accessed from ContentWithinNavigationLink, but it works from ContentDirect.
I've also noticed that the code works if I move the presentingViewB property to the ViewModel class. However, in real code, that significantly increases the complexity of ViewModel, as I have more than ten destinations to handle. Each bound with different shapes of data. I'd prefer to store an enum value in ViewModel, listen to it in ViewA, and then convert it to boolean flags and properties in ViewAβjust for iOS 16 compatibility. For iOS 17 and above, the enum works perfectly with navigationDestination(item:destination:).
class ViewModel: ObservableObject {
@Published var destination = ""
func gotoB() {
destination = "ViewB"
}
func reset() {
destination = ""
}
}
struct ContentWithinNavigationLink: View {
var body: some View {
NavigationStack {
NavigationLink {
ViewA()
} label: {
Text("Goto A")
}
}
}
}
struct ContentDirect: View {
var body: some View {
NavigationStack {
ViewA()
}
}
}
struct ViewA: View {
@State private var presentingViewB = false
@StateObject private var viewModel = ViewModel()
var body: some View {
Button {
viewModel.gotoB()
} label: {
Text("goto ViewB")
}
.navigationDestination(isPresented: $presentingViewB) {
ViewB().environmentObject(viewModel)
}
.onChange(of: viewModel.destination) { newValue in
if newValue == "ViewB" {
presentingViewB = true
} else {
presentingViewB = false
}
}
}
}
struct ViewB: View {
@EnvironmentObject var viewModel: ViewModel
var body: some View {
Button {
viewModel.reset()
} label: {
Text("Return")
}
.navigationBarBackButtonHidden()
}
}
The reason of using code like
Button {
viewModel.gotoB()
} label: {
Text("goto ViewB")
}
in ViewA is because in real code the Button is actually several subviews where the navigation-triggering code is deeply nested.
I want to use a Map to show current location and heading, but the map first show, it just wont work. And when I switch off and switch on again, it works. codes below:
BackgroundMapView.swift
import SwiftUI
import MapKit
struct BackgroundMapView: View {
var scope: Namespace.ID?
private var cameraPosition: MapCameraPosition = .userLocation(
followsHeading: true,
fallback: .automatic
)
private var locations: [Location]
init(_ scope: Namespace.ID? = nil, locations: [Location]) {
self.scope = scope
self.locations = locations
}
var body: some View {
Map(
initialPosition: cameraPosition,
scope: scope
) {
MapPolyline(coordinates: locations.map({ $0.coordinate.toGCJ02 }))
.stroke(
.red,
lineWidth: 3
)
}
.mapControlVisibility(.hidden)
}
}
#Preview {
MainView()
}
HomeVIew.swift
import SwiftUI
struct HomeView: View {
@StateObject private var locationManager = LocationManager()
@State private var isMapEnabled = UserDefaults.isHomeMapEnabled {
didSet {
UserDefaults.isHomeMapEnabled = isMapEnabled
}
}
@Namespace private var mapScope
var body: some View {
if isMapEnabled {
BackgroundMapView(mapScope, locations: locationManager.locations)
.mapScope(mapScope)
}
}
}
Hello,
I seem to be unable to change TabView's background color (not the bar, but the background of the entire TabView), no matter what I try.
What I am looking for:
To make the TabView's background clear.
My code:
TabView(selection: $activeScreen) {
Screen1()
.tabItem {
Label("Menu", systemImage: "list.dash")
}
}
Screen1 is defined as:
struct Screen1: View {
var body: some View {
VStack {
Text("Hello")
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
What I have tried, based on suggestions online:
Changing UITabBarAppearance in init(), and .onAppear()
TabView().background(.clear)
In all cases, the TabView's background remains either white or black, depending on the device's theme. I can change the background behind it by placing it in a ZStack, but that is not what I am looking for, I want the background itself to be clear.
The only way that TabView will honor .background(.clear) is if I add the following:
.tabViewStyle(.page)
.indexViewStyle(.page(backgroundDisplayMode: .always))
But this changes the style of the TabView, which is not the desired behavior.
Any help would be greatly appreciated, thank you!
I am working on a sticker app and I am building a custom sticker app in SwiftUI. I have created a custom UIViewRepresentable to allow a MSStickerView to be displayed in SwiftUI. I have local *.gif files in my project and I am loading them into the MSStickerView successfully, however when they are loaded in my iMessage sticker extension the stickers are not animating by default. When I tap on the MSStickerView the gif begins to animate, I'm not sure what else I can do to get this working properly in my app. Some sample code below:
public struct CustomStickerView: UIViewRepresentable {
var sticker: CustomSticker
public init(sticker: CustomSticker) {
self.sticker = sticker
}
public func makeUIView(context: Context) -> MSStickerView {
let v = MSStickerView()
if sticker.fileType == .gif {
v.startAnimating()
}
return v
}
public func updateUIView(_ uiView: MSStickerView, context: Context) {
uiView.sticker = sticker.sticker
}
}
// CustomSticker
public var sticker: MSSticker? {
guard let imagePath = Bundle.main.path(forResource: name, ofType: ".\(fileType.rawValue)") else {
print("Failed to get sticker - \(name).\(fileType.rawValue)")
return nil
}
let path = URL(fileURLWithPath: imagePath)
return try? MSSticker(contentsOfFileURL: path, localizedDescription: name)
}
Hello,
I am working on an iOS app that has interactive components that react to the device accelerometer. The app works in landscape left and right only, and I need some way to identify if the screen is left or right to get the acceleration direction correct. Basically, accelerating to the device's "left" means you actually need to move the elements on screen to the left or right depending on screen direction.
One solution I tried is using UIDeviceOrientation. This works in most cases, but when screen lock is on, it gives an update about the device orientation when the screen itself didn't tilt.
Is there some other way to get the screen orientation that accurately reflects the screen orientation and not just device orientation?
Thank you.
How do I scroll to a row and select it when it is part of collapsed rows in Table
ScrollViewReader { scrollViewProxy in
Table([node], children: \.children, selection: $selectedNodeID) {
TableColumn("Key") { Text($0.key) }
TableColumn("Value") { Text($0.val) }
}
.onChange(of: selectedNodeID) { _, newValue in
withAnimation {
scrollViewProxy.scrollTo(newValue)
}
}
}
The code above works well for the rows that are expanded or at the root level. However, for the rows that are not yet expanded the code above does nothing. How can I update the code so that it scrolls to a row that has not materialized yet.
Info:
This is a macOS app
I am on macOS 15.1.1 with Xcode 16.1 and the minimum target of the app is macOS 15
First post here!
Is there a way to reduce the number of haptic feedback for double tap on primary button?
Context: Double tap is awesome. Two haptic actuations are given to the gesture to let the user know that the gesture is "received" then a third haptic feedback is given shortly after to signal the primary button is tapped. Is there a way to disable the third haptic feedback. In other words make primary action "silent"?
I have tested a number of apps that supports double tap, it seems to me that the triple tap is a system level default, and it cannot be changed.
Any help would be greatly appreciated.
I have the following lines of code where I show a bunch of checkboxes, each of which can toggle between on and off with a tap.
import SwiftUI
struct ContentView: View {
@State private var viewModel = ContentViewModel()
var body: some View {
VStack(alignment: .leading) {
List {
ForEach(viewModel.models, id: \.id) { model in
CheckButtonView(id: model.id, text: model.name, isOn: model.isOn) { id, bool in
updateDate(id: id, bool: bool)
}
}
}
}
}
func updateDate(id: String, bool: Bool) {
for i in 0..<viewModel.models.count {
let oldModel = viewModel.models[i]
if oldModel.id == id {
let newModel = Content(id: oldModel.id, name: oldModel.name, isOn: bool)
viewModel.models.remove(at: i)
viewModel.models.insert(newModel, at: i)
break
}
}
var count = 0
for i in 0..<viewModel.models.count {
let model = viewModel.models[i]
if model.isOn {
count += 1
}
}
}
}
struct CheckButtonView: View {
let id: String
let text: String
@State var isOn: Bool
var callBack: (String, Bool) -> Void
var body: some View {
HStack {
Button {
isOn.toggle()
callBack(id, isOn)
} label: {
Image(systemName: isOn ? "checkmark.square.fill" : "square")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 18)
.tint(!isOn ? .black : .blue)
}
Text(text)
.font(.subheadline)
Spacer()
}
.frame(maxWidth: .infinity)
}
}
struct Content {
let id: String
let name: String
let isOn: Bool
}
class ContentViewModel: ObservableObject {
@Published var models = [Content]()
@Published var canChange = true
init() {
models = [
Content(id: UUID().uuidString, name: "Jim", isOn: false),
Content(id: UUID().uuidString, name: "Jenny", isOn: false),
Content(id: UUID().uuidString, name: "Nancy", isOn: false),
Content(id: UUID().uuidString, name: "Natalie", isOn: false)
]
}
}
According to the picture above, I have two checkboxes that are turned on. Now, what I want to do is let the user turn on as many as two checkboxes only. Can someone think of a good way of doing that? Thanks.
When using a NavigationSplitView within a NavigationStack, the NavigationSplitView does not work as expected on iOS 18 (it worked previously). Items do not show their associated detail views when selected.
See the following minimum reproducible example:
import SwiftUI
struct ContentView: View {
@State var selectedItem: String? = nil
@State var navigationState: NavigationState? = nil
var body: some View {
NavigationStack {
List(selection: self.$selectedItem) {
NavigationLink("Item 1", value: "item")
}
.navigationDestination(item: self.$selectedItem) { value in
ChildView()
}
}
}
}
enum NavigationState: Hashable {
case general
case secondary
}
struct ChildView: View {
@State var navigationState: NavigationState? = nil
var body: some View {
NavigationSplitView {
List(selection: self.$navigationState) {
NavigationLink(value: NavigationState.general) {
Text("Basic info")
}
NavigationLink(value: NavigationState.secondary) {
Text("Secondary info")
}
}
} detail: {
if self.navigationState == nil {
Text("Nothing")
} else {
Text("Details")
}
}
}
}
I'd like to use ScrollViewReader, but on a list of static text that has formatting such as font colors and bold text. Essentially, my list has a bunch of:
Text("some text ") + Text(" and more text").fontWeight(.bold).foregroundStyle(boldColor)
Switching to AttributedString would be a pain, and I'm not so sure ScrollViewReader is working correctly. It seems like there are a lot of bugs reports about it. Plus, do we really need a separate string format, just to have proper formatting? Really?
Is there another version I'm missing? One that can scroll to anchor points that I could set?
Hi!
When my device is set to English, both search and the Shortcuts up automatically show multiple shortcuts parametrised for each value of the AppEnum - which is what I expected. When my device is set to German, I get only the basic AppShortcut without the (optional) parameter.
I am using an AppEnum (see below) for the parametrised phrases and localise the phrases into German with an AppShortcuts String Catalog added to my project.
Everything else seems to work, I can use my AppShortcut in the Shortcuts app and invoke it via Siri in both English and German.
The Shortcuts app displays the values correctly using the localized strings.
Any ideas?
import AppIntents
class ApolloShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: GetIntent(),
phrases: [
"Get data from \(.applicationName)",
"Get data from \(.applicationName) for \(\.$day)",
"Get data from \(.applicationName) for the \(\.$day)"
],
shortTitle: "Get Data",
systemImageName: "wand.and.sparkles")
}
}
enum ForecastDays: String, AppEnum {
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Day"
static var caseDisplayRepresentations: [Self : DisplayRepresentation] = [
.today: DisplayRepresentation(title: LocalizedStringResource("today", table: "Days")),
.tomorrow: DisplayRepresentation(title: LocalizedStringResource("tomorrow", table: "Days")),
.dayAfterTomorrow: DisplayRepresentation(title: LocalizedStringResource("dayAfterTomorrow", table: "Days"))
]
case today
case tomorrow
case dayAfterTomorrow
var displayName: String {
String(localized: .init(rawValue), table: "Days")
}
}
How can I make this appear inside the NavigationSplitView toolbar?
It doubles up with the close button and takes up space...
App Main view
import SwiftUI
@main
struct WritingApp: App
{
var body: some Scene
{
DocumentGroup(newDocument: WritingAppDocument())
{ file in
StoryView(document: file.$document)
}
}
}
Story view
import SwiftUI
struct StoryView: View
{
@Binding var document: WritingAppDocument
@State private var isShowingSheet = false
@FocusState private var isFocused: Bool
var body: some View
{
NavigationSplitView
{
Text("Sidebar")
}
detail:
{
HStack
{
Text("Detail View")
}
.toolbar
{
ToolbarItem
{
Button("Book", systemImage: "book")
{
}
}
ToolbarItem
{
Button("Circle", systemImage: "circle")
{
}
}
}
}
}
}
DeviceActivityReport presents statistics for a device: https://developer.apple.com/documentation/deviceactivity/deviceactivityreport
The problem: DeviceActivityReport can present statistics with a delay for a parent device (when DeviceActivityReport is presenting, the DeviceActivityReportExtension is called to process the statistics). One possible solution is to call DeviceActivityReport periodically throughout the day in a child device. However, the app will not be available all day. Is there any way to run DeviceActivityReport in the background?
I have tried the following approach, but it didnβt work (DeviceActivityReportExtension didnt call):
let hostingController: UIHostingController? = .init(rootView: DeviceActivityReport(context, filter: filter))
hostingController?.view.frame = .init(origin: .zero, size: .init(width: 100, height: 100))
hostingController?.beginAppearanceTransition(true, animated: false)
hostingController?.loadView()
hostingController?.viewDidLoad()
try? await Task.sleep(for: .seconds(0.5))
hostingController?.viewWillAppear(true)
hostingController?.viewWillLayoutSubviews()
try? await Task.sleep(for: .seconds(0.5))
hostingController?.viewDidAppear(true)
try? await Task.sleep(for: .seconds(0.5))
hostingController?.didMove(toParent: rootVC)
try? await Task.sleep(for: .seconds(0.5))
hostingController?.viewWillLayoutSubviews()
hostingController?.viewDidLayoutSubviews()
hostingController?.view.layoutIfNeeded()
hostingController?.view.layoutSubviews()
hostingController?.endAppearanceTransition()
Is there any way to run DeviceActivityReport in the background? (when app is not visible/closed). The main problem is call DeviceActivityReport
Hi,
I am a new SwiftUI app developer and developing my first application. In the process of designing not very GUI rich app, I noticed my app crashed whenever I switched orientation (testing on multiple iPhone devices).
After going through all kind of logs and errors, performance enhancements nothing worked.
Then I started rolling back all GUI related features 1 by 1 and tested (I am sure there are better approaches, but excuse me I am novice in app development :) ).
Even though it's time consuming, I could pin point the cause of the fatal error and app crash, it's due to multiple .shadow modifiers I used on NavigationLink inside a ForEach look (to be precise I used it like following,
.shadow(radius: 15)
.shadow(radius: 20)
.shadow(radius: 20)
.shadow(radius: 20)
.shadow(radius: 20)
Note, there are only 7 items in List and it uses the Hero View (like app store's Today section) for child views.
Once I got rid of shadow modifies or used only 1 app works fine and doesn't crash.
Lesson learnt...
P.S.
It's so ironic that so performance tuned devices couldn't handle this basic GUI stuff.
why do I need to set the font of an image of an SF symbol to get the effect to work? This should be a bug, it's bad behavior. Xcode 16.1 iOS 18.1, so frustrating.
for example: this works
Image(systemName: "arrow.trianglehead.2.clockwise.rotate.90.circle.fill")
.symbolEffect(.rotate, options: .repeat(.continuous), value: isActive)
.font(.largeTitle)
.onAppear() {
isActive = true
}
but this does not animate, which makes no sense
Image(systemName: "arrow.trianglehead.2.clockwise.rotate.90.circle.fill")
.symbolEffect(.rotate, options: .repeat(.continuous), value: isActive)
.onAppear() {
isActive = true
}
its the same if you use a simple setup and different font size, and whether font is before or after the symbol effect
Image(systemName: "arrow.trianglehead.2.clockwise.rotate.90.circle.fill")
.font(.headline) // only works if this line is here
.symbolEffect(.rotate, options: .repeat(.continuous))
Hello everyone! I've encountered an issue related to SwiftUI and StoreKit. Please take a look at the SwiftUI code snippet below:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationStack {
List {
NavigationLink {
Page1()
} label: {
Text("Go to Page 1")
}
}
}
}
}
struct Page1: View {
@Environment(\.dismiss) private var dismiss
@State private var string: String = ""
var body: some View {
List {
NavigationLink {
List {
Page2(string: $string)
.simpleValue(4)
}
} label: {
Text("Tap this button will freeze the app")
}
}
.navigationTitle("Page 1")
}
}
struct Page2: View {
@Binding var string: String?
init(string: Binding<String>) {
self._string = Binding(string)
}
var body: some View {
Text("Page 2")
}
}
extension EnvironmentValues {
@Entry var simpleValue: Int = 3
}
extension View {
func simpleValue(_ value: Int) -> some View {
self.environment(\.simpleValue, value)
}
}
This view runs normally until the following symbol is referenced anywhere in the project:
import StoreKit
extension View {
func notEvenUsed() -> some View {
self.manageSubscriptionsSheet(isPresented: .constant(false))
}
}
It seems that once the project links the View.manageSubscriptionsSheet(isPresented:) method, regardless of whether it's actually used, it causes the above SwiftUI view to freeze.
Steps to Reproduce:
Clone the repository: https://github.com/gongzhang/StrangeFreeze
Open it in Xcode 16 and run on iOS 17-18.1
Navigate to the second page and tap the button, causing the app to freeze.
Remove manageSubscriptionsSheet(...), then everything will work fine
How to reproduce: create blank Xcode project run on physical iPhone(mine 14 pro) not simulator, updated iOS18.1.1 most up to date, on Xcode 16.1 make a text field enter any value in it in console:
Can't find or decode reasons
Failed to get or decode unavailable reasons
This is happening in my other projects as well and I don't know a fix for it is this just an Xcode bug random log noise? It makes clicking the text field lag sometimes on initial tap.