I have an app and a photo editing extension. I use a group container to share data between the two. That has not been a problem in the past. However, in the latest Sequoia Beta, when I try to write a file to that location, the " would like to access data from other apps" dialog appears.
That's not what I'm doing, and the fact that it comes up every single launch will freak out customers. How do I read and write data to my app's group container without getting this dialog to appear? Is there a different way I am supposed to share data between an extension and an app?
I filed Feedback FB14412342.
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.
Post
Replies
Boosts
Views
Activity
This is a question regarding the specification of ObservalObject.
The following code does not cause a compilation error when the deployment target is set to iOS 16, but it does cause the following error when set to iOS 15:
class Model: ObservableObject {
let player: AVPlayer
@Published var isPlaying = false
var playerObserver: NSKeyValueObservation?
init() {
self.player = AVPlayer()
self.playerObserver = self.player.observe(\.rate, options: [.new, .old]) { player, change in
NSLog("changed rate: \(String(describing: change.newValue))")
}
}
func setup() {
let name = "sample"
let url = Bundle.main.url(forResource: name, withExtension: "m4a")!
let playerItem = AVPlayerItem(url: url)
self.player.replaceCurrentItem(with: playerItem)
}
func play() {
self.player.play()
self.isPlaying = true
}
}
The following error occurs in iOS 15:
Cannot form key path to main actor-isolated property 'rate'
Call to main actor-isolated instance method 'play()' in a synchronous nonisolated context
Additionally, if the code is modified as follows, the error does not occur even in iOS 15. Specifically, adding @MainActor to the Model resolves the issue.
@MainActor
class Model: ObservableObject {
...
}
From this behavior, I guessed that ObservableObject is implicitly a MainActor in iOS 16 and later. Is this understanding correct?
Hi!
I am working on an app that requires displaying special characters and I have currently implemented it to just use Text() in swiftUI.
Unfortunately, it can't display the full height of the text.
Attached is one example of this happening.
I have attempted to do .linespacing() but that method doesn't work. .frame also doesn't seem to make a change. Does anyone have a solution to this?
Thanks!
I'm showing a Text View when a button with an image is long-pressed.
import SwiftUI
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
var isDark: Bool {
return colorScheme == .dark
}
@State private var showLabel = false
var body: some View {
Button(action: {
}) {
VStack {
ZStack {
Image(systemName: "swift")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 32)
.padding(.horizontal, 40)
.padding(.vertical, 6)
.background(.gray.opacity(0.2), in: RoundedRectangle(cornerRadius: 10))
.onTapGesture {
showLabel.toggle()
}
.onLongPressGesture(minimumDuration: 2) {
print("Long pressed...")
showLabel.toggle()
}
if showLabel {
Text("Help Content")
.font(.caption)
.foregroundStyle(!isDark ? .white : .black)
.padding(10)
.background(!isDark ? .black : .white, in: Rectangle())
.onTapGesture {
print("hey")
showLabel.toggle()
}
.offset(x: 120)
}
}
}
}
}
}
So a Text View will appear as shown in the image above. But its .onTapGesture is never called. I wonder why? Thanks.
Hello, so I created a custom TabBar using the .overlay modifier on TabView. However, when clicking/pressing on a TextField, the keyboard causes the TabBar to be pushed up in the view. From Reddit, I found that this is caused by using the .overlay modifier.
How should I go about fixing this issue or what is the standard way of implementing custom tab bars?
Thanks in advance!
-- Kohl J
Screenshot
TabView Code
struct RootView: View {
@State var selectedTab : Tabs = .home;
var body: some View {
TabView(selection: $selectedTab) {
HomeView(selectedTab: $selectedTab)
.tag(Tabs.home)
TaskListView(selectedTab: $selectedTab)
.tag(Tabs.taskList)
CreateTaskView(selectedTab: $selectedTab)
.tag(Tabs.create)
TrophiesView(selectedTab: $selectedTab)
.tag(Tabs.trophies)
SettingsView(selectedTab: $selectedTab)
.tag(Tabs.settings)
}
.overlay(alignment: .bottom) {
TabBar(selectedTab: $selectedTab)
.padding(.horizontal)
}
}
}
Custom TabBar Code
struct TabBar: View {
@Binding var selectedTab : Tabs
var body : some View {
HStack (alignment: .center) {
Button(action: {
// switch to home view
selectedTab = Tabs.home
}, label: {
TabBarButton(buttonText: "Home", imageName: "house.fill", size: 24, isActive: selectedTab == .home, hasTopBar: true)
})
Button(action: {
// switch to task list view
selectedTab = Tabs.taskList
}, label: {
TabBarButton(buttonText: "Task List", imageName: "list.bullet.clipboard.fill", size: 24, isActive: selectedTab == .taskList, hasTopBar: true)
})
Button(action: {
// switch to create view
selectedTab = Tabs.create
}, label: {
TabBarButton(buttonText: "Create", imageName: "plus.circle.fill", size: 32, isActive: selectedTab == .create, hasTopBar: false)
})
Button(action: {
// switch to trophies view
selectedTab = Tabs.trophies
}, label: {
TabBarButton(buttonText: "Trophies", imageName: "trophy.fill", size: 24, isActive: selectedTab == .trophies, hasTopBar: true)
})
Button(action: {
// switch to settings view
selectedTab = Tabs.settings
}, label: {
TabBarButton(buttonText: "Settings", imageName: "gearshape.fill", size: 24, isActive: selectedTab == .settings, hasTopBar: true)
})
}
.frame(height: 60)
}
}
I added gesture support to my app that supports iOS 16 and 17 and have never had issues with it.
However, when I compiled my app with Xcode 16 I immediately noticed a problem with the app when I ran it in the simulator. I couldn't scroll up or down. I figured out it’s because of my gesture support.
My gesture support is pretty simple.
let myDragGesture = DragGesture()
.onChanged { gesture in
self.offset = gesture.translation
}
.onEnded { _ in
if self.offset.width > threshold {
...some logic
} else if self.offset.width < -threshold {
...some other logic
}
logitUI.debug("drag gesture width was \(self.offset.width)")
self.offset = .zero
}
If I pass nil to .gesture instead of myDragGesture then scrolling starts working again.
Here’s some example output when I’m trying to scroll down. These messages do NOT appear when I run my app on an iOS 16/17 simulator with Xcode 15.
drag gesture width was 5.333328
drag gesture width was -15.333344
drag gesture width was -3.000000
drag gesture width was -24.333328
drag gesture width was -30.666656
I opened FB14205678 about this.
I have several views I want to animate in concert. I plan to use keyframe animation. I want to keep the .keyFrameAnimator modifier code small; I have a lot of ...Keyframes inside several KeyframeTracks. It seems like I should be able to isolate the body of the keyframes parameter into a func or var. Builders are such a pain, I can't grok the right way to refactor their bodies out.
I've tried to make a standalone @KeyframeTrackContentBuilder<MyValue> function but cannot figure out the right syntax/incantation to stuff it with KeyframeTracks.
My latest attempt is to create a func that returns a KeyframeTimeline, but that's been a deadend too.
let k: KeyframeTimeline<MyValue> = timeline(...)
CartoonCardView(color: .yellow)
.keyframeAnimator(
initialValue: k.value(time: 0)
) { content, value in
content
.rotationEffect(value.angle)
.scaleEffect(value.scale)
.offset(value.offset)
} keyframes: { _ in k }
The error on k in the last line is "No exact matches in call to static method 'buildExpression'" with the sub-error "Candidate requires that 'KeyframeTimeline' conform to 'KeyframeTrackContent' (requirement specified as 'K' : 'KeyframeTrackContent') (SwiftUICore.KeyframesBuilder)"
I'm trying to get a countdown timer to work, and the way I currently do it in my watchOS 10 app is a complicated load of nonsense to get two Strings that look like "1w 1d" and "12:34:56", i.e. a String that shows components like year, week and day, and another String showing hours, minutes and seconds.
The new Text formats seen here https://developer.apple.com/wwdc24/10144?time=645 look useful, but I can't get them to return the values I need.
If I use this:
let dateA = Date.now
let dateB = Date.advanced(by: /* value for 8 days, 12 hours, 34 minutes and 56 seconds */)
Text(dateA, format: .offset(to: dateB, allowedFields: [.year, .week, .day], maxFieldCount: 3))
I expect to see "1 week 1 day", but it always comes back as "8 days". I guess it's giving me the most concise result, but I don't want that. I'm not sure anyone would want that.
Imagine you have an event coming up in 3 days 6 hours, do you want to see "in 78 hours" or do you want "in 3 days and 6 hours"? Why must we make the user calculate the days and hours in their head when we have the ability to give them the right information?
While I'm on this, why does the resulting String have to have "in " at the beginning? I don't want that; it's not my use case, but it's forced on me.
I've raised this a hundred times with Apple. I just want to see a String that shows the difference between two dates in a format of my choosing, i.e. "1w 1d", but they never give me what I need, so I have to write extremely complex - and fragile - code that figures this stuff out, and I still can't get that to work properly.
Why can't we just have something like:
Text(from: dateA, to: dateB, format: "%yy %ww %dd") // for "1 year 2 weeks 3 days", show parts with a value > 0
Text(from: dateA, to: dateB, format: "%0yy %0ww %0dd") // for "0 years 2 weeks 3 days", show all parts regardless of value
Text(from: dateA, to: dateB, format: "%y %w %d") // for "1y 2w 3d", show parts with a value > 0
Text(from: dateA, to: dateB, format: "%0y %0w %0d") // for "0y 2w 3d", show all parts regardless of value
Hello, community and Apple engineers. I need your help.
Our app has the following issue: NavigationStack pushes a view twice if the NavigationStack is inside TabView and NavigationStack uses a navigation path of custom Hashable elements.
Our app works with issues in Xcode 18 Beta 13 + iOS 18.0. The same issue happened on previous beta versions of Xcode 18.
The issue isn’t represented in iOS 17.x and everything worked well before iOS 18.0 beta releases.
I was able to represent the same issue in a clear project with two simple views. I will paste the code below.
Several notes:
We use a centralised routing system in our app where all possible routes for navigation path are implemented in a View extension called withAppRouter().
We have a enum RouterDestination that contains all possible routes and is resolved in withAppRouter() extension.
We use Router class that contains @Published var path: [RouterDestination] = [] and this @Published property is bound to NavigationStack. In the real app, we need to have an access to this path property for programmatic navigation purposes.
Our app uses @ObservableObject / @StateObject approach.
import SwiftUI
struct ContentView: View {
@StateObject private var router = Router()
var body: some View {
TabView {
NavigationStack(path: $router.path) {
NavigationLink(value: RouterDestination.next, label: {
Label("Next", systemImage: "plus.circle.fill")
})
.withAppRouter()
}
}
}
}
enum RouterDestination: Hashable {
case next
}
struct SecondView: View {
var body: some View {
Text("Screen 2")
}
}
class Router: ObservableObject {
@Published var path: [RouterDestination] = []
}
extension View {
func withAppRouter() -> some View {
navigationDestination(for: RouterDestination.self) { destination in
switch destination {
case .next:
return SecondView()
}
}
}
}
Below you can see the GIF with the issue:
What I tried to do:
Use iOS 17+ @Observable approach. It didn’t help.
Using @State var path: [RouterDestination] = [] directly inside View seems to help. But it is not what we want as we need this property to be @Published and located inside Router class where we can get an access to it, and use for programmatic navigation if needed.
I ask Apple engineers to help with that, please, and if it is a bug of iOS 18 beta, then please fix it in the next versions of iOS 18.0
Hello,
I'm using the Picker component to enable the user to pick a payment method but the menu items are flipped
HI,
I'm trying to deeplink from my widget to a view in my app.
I'm using the "SwiftUI app lifecycle".
This the code I'm currently using:
var body: some Scene {
WindowGroup {
RootView()
.onContinueUserActivity("NextDeparturesWidgetConfigurationIntent") { userActivity in
guard let configuration: NextDeparturesWidgetConfigurationIntent = userActivity
.widgetConfigurationIntent(),
let stationEntity = configuration.stationEntity else { return }
NotificationCenter.default.post(name: .onOpenStation, object: stationEntity.id)
}
}
}
It is working fine when the app is already running (in the background).
However when the app is "cold starting" (ie. not in memory) onContinueUserActivity is never called.
I tried adding a UIApplicationDelegateAdaptor:
func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions
) -> UISceneConfiguration {
if let userActivity = options.userActivities.first {
let configuration: NextDeparturesWidgetConfigurationIntent? = userActivity.widgetConfigurationIntent()
// casting fails
}
return UISceneConfiguration(
name: nil,
sessionRole: connectingSceneSession.role
)
}
I can see that the activity is received but it is never casted to NextDeparturesWidgetConfigurationIntent.
What am I missing ?
I have a simple SwiftUI application that sends a URLRequest as shown in the code snippet below:
import SwiftUI
@main
struct GOGODemoApp: App {
var body: some Scene {
WindowGroup {
MyView()
}
}
}
struct MyView: View {
var body: some View {
Button("Click") {
sendHTTPRequest(to: "https://www.google.com") { code, err in
print("Finished, code: \(code ?? -1), err: \(String(describing: err))")
}
}
}
}
func sendHTTPRequest(to urlString: String, completion: @escaping (Int?, Error?) -> Void) {
guard let url = URL(string: urlString) else {
completion(nil, NSError(domain: "InvalidURL", code: 0, userInfo: nil))
return
}
let task = URLSession.shared.dataTask(with: url) { _, resp, error in
if let httpResponse = resp as? HTTPURLResponse {
completion(httpResponse.statusCode, error)
} else {
completion(-1, error)
}
}
task.resume()
}
However, Xcode prints the following warning messages:
nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C3] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C3] Connection has no local endpoint
Finished, code: 200, err: nil
What does the warning 'Connection has no local endpoint' mean?
Thank you for your assistance!
For MacOS I wrote a Terminal Command Line Tool to help me do number crunching calculations. No need for UI. This works great as-is, but there are opportunities to make the work more interesting by giving it some graphical representation like a heat map of the data. To that end I want the terminal to launch a SwiftUI code to open a window given an optional command line parameter that would display this visual representation of data in a new window. It would be nice to interact with that window visualization in some ways using SwiftUI.
I originally thought it'd just be as easy as creating a SwiftUI View file and then throwing what normally appears under @main into a launch function and then calling the launch function from my main.swift file:
import SwiftUI
struct SwiftUIView: View {
var body: some View {
Text("Hello, World!")
}
}
#Preview {
SwiftUIView()
}
func LaunchSwiftUIApp()
{
//@main
struct SwiftUIApp: App {
var body: some Scene {
WindowGroup {
SwiftUIView()
}
}
}
}
Of course this doesn't work.
I've already have the command line code just spit out various png files via command line so looking to make those visualization a little more interactive or readable/organized by coding some SwiftUI stuff around those current visualizations. Anyway.
Looking around this doesn't seem to be a thing people normally do. I'm not sure how to setup the Terminal Command Line Tool code that I wrote to optionally launch into SwiftUI code.
In SwiftUI, I have noticed that sometimes at the end of a keyboard dismiss animation, it leaves a white "inset" on the screen. The white inset would then disappear without any animation.
For more detailed demonstration, I have filed feedback FB13694633. Is there a way to work around this white inset for now? Thanks!
I am trying to change the highlight color of the tabs in SwiftUI, but when I applied .tint() to the TabView (which is the root view of my app), the entire app seems to be affected. What's more, the views under each seems to randomly switch between the default blue tint and the custom tint I configured.
Is there a way to only change the tab bar's tint color? Thanks!
I'm trying to implement multiple window support for my app, but the system restores the wrong scene when the app is relaunched. Here's my code:
import SwiftUI
@main
struct TestApp: App {
@Environment(\.openWindow) private var openWindow
var body: some Scene {
WindowGroup(id: "Navigator") {
Button {
openWindow(id: "Editor", value: "test")
} label: {
Text("Open Window")
}
}
WindowGroup(id: "Editor", for: String.self) { id in
Text(id.wrappedValue ?? "none")
}
}
}
If I run the app and tap the button, the Editor window opens. If I force quit and open the app again, the app still has two windows open but both are Navigator windows.
I've tried adding handlesExternalEvents to the Scene and advertising an activity with .userActivity(isActive:), neither changes this behaviour. Any advice?
Wasted about 3 hours on this yesterday.
I add a Text item in a field of a Form. Well and good. It wraps if needed, alights to the left a fixed amount no matter how much or how little text there is. All expected.
I added an image.
It alll went to hell after that as the text just sort of drew where it wanted to. It looked like the parent tile was now wider then the display area.
No amount of playing with Spacer(), padding, Frames. HStack alignments, Position fields, and so on did any good. as all I am trying to do a simple tile with a text block and image. And SwiftUI fights me every step of the way.
It's for a simple restaurant menu item tile. Name of item, price and image. If I drop the image, then it formats in a predictable fashion.
HStack{
VStack{
if let maindish = item["name"]{
Text("\(maindish)").foregroundColor(.primary).modifier(favoriteStyle()).fontWeight(.regular).font(.custom("Avenir",size:fontSize))
}
if let formattedPrice = item["formatted_price"]{
Text("\(formattedPrice)").foregroundColor(.secondary).modifier(favoriteStyle()).fontWeight(.bold).font(.custom("Avenir",size:fontSize))
}
}
Spacer()
if let imageURL = item["thumbnail_image"]{
if let url = URL(string:imageURL) {
drawImage(url:url, size:85.0).padding(0.0).padding(.trailing,75.00)
}
}
}
Currently, I am using UICollectionViewCompositionalLayout to achieve the following list layout with spacing:
We were thinking of trying out UICollectionLayoutListConfiguration due to its ability to support swipe actions.
We would like to specify the spacing between each item. However, I do not find a way to specify item spacing in UICollectionLayoutListConfiguration.
Does UICollectionLayoutListConfiguration not support item spacing, or have I missed something?
Thanks.
Currently, this is how I implement the drag and move operation:
collectionView.beginInteractiveMovementForItem
collectionView.updateInteractiveMovementTargetPosition
collectionView.endInteractiveMovement
The outcome looks like the following:
However, what I would like to achieve is the ability to customize the view of the "drop" location.
For instance, in the following example, a red line is drawn at the target drop location:
In this example, a transparent rectangle is drawn at the target drop location:
May I know how these apps achieve such an effect?
Thanks.
I'm encountering a crash in my SwiftUI app when it is opened via an AppIntent. The app runs perfectly when launched by tapping the app icon, but it crashes when opened from an intent.
Here is a simplified version of my code:
import AppIntents
import SwiftData
import SwiftUI
@main
struct GOGODemoApp: App {
@State
private var state: MyController = MyController()
var body: some Scene {
WindowGroup {
MyView()
//.environment(state) // ok
}
.environment(state) // failed to start app, crash with 'Dispatch queue: com.apple.main-thread'
}
}
struct MyView: View {
@Environment(MyController.self) var stateController
var body: some View {
Text("Hello")
}
}
@Observable
public class MyController {
}
struct OpenIntents: AppIntent {
static var title: LocalizedStringResource = "OpenIntents"
static var description = IntentDescription("Open App from intents.")
static var openAppWhenRun: Bool = true
@MainActor
func perform() async throws -> some IntentResult {
return .result()
}
}
Observations:
The app works fine when launched by tapping the app icon.
The app crashes when opened via an AppIntent.
The app works if I inject the environment in MyView instead of in WindowGroup.
Question:
Why does injecting the environment in WindowGroup cause the app to crash when opened from an intent, but works fine otherwise? What is the difference when injecting the environment directly in MyView?