I'm adding Admob ads to my app, and Admob needs to know the width of the view, so I'm using GeometryReader for that. To prevent GeometryReader from grabbing screen space, I've wrapped the main view in GeometryReader { }. I then use geometry.size.width in my call to the adView.
This all works fine. I have two main screens where I show ads, and they both work, until I rotate the device. Then the app crashes!
If I comment out the GeometryReader code and pass a fixed value to the ad view, I can rotate the device with no fear of a crash.
My question is: Do I have to accept that GeometryReader will crash the app when it's rotated, or is there another, stable way to get view dimensions?
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
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.
I have an observable object which is a model a view.
I also have a Tip (from TipKit) with @Parameter and a rule.
The source of truth for the state is in the observable object, however the Tip needs to be updated when state changes. So how do I bind between the two?
The way I was thinking was to sink updates from objectWillChange and check if Tips parameter needs to be updated or add didSet if it a @Published property. But I am not sure this is the best practice.
Schematic example:
class MyModel: ObservableObject {
struct TapSubmitTip: Tip {
@Parameter static var isSubmitButtonEnabled: Bool = false
var title: Text {
Text("Tap \"Submit\" to confirm your selection.")
}
var rules: [Rule] {
#Rule(Self.$isSubmitButtonEnabled) {
$0 == true
}
}
}
let tapSubmitTip = TapSubmitTip()
var objectWillChangeCancallable: AnyCancellable!
// Used by the view to enable or disable the button
var isSubmitButtonEnabled: Bool {
// Some logic to determine if button should be enabled.
}
init() {
objectWillChangeCancallable = objectWillChange.sink { [weak self] void in
guard let self else { return }
if isSubmitButtonEnabled {
TapSubmitTip.isSubmitButtonEnabled = true
}
}
}
...
// Call objectWillChange or update published properties as needed.
...
}
I have a widget with a dynamic property. I'm able to provide the options to the widget edit ui and the user can make their selection .. which filters what data gets shown in the widget.
My use case is when the user goes back to the main app and deletes the option that is currently selected. Currently, the widget keeps that selection. How can I get the widget to clear that selection and show the defaultResult() from the EntityQuery?
I want to understand the utility of using AsyncStream when iOS 17 introduced @Observable macro where we can directly observe changes in the value of any variable in the model(& observation tracking can happen even outside SwiftUI view). So if I am observing a continuous stream of values, such as download progress of a file using AsyncStream in a SwiftUI view, the same can be observed in the same SwiftUI view using onChange(of:initial) of download progress (stored as a property in model object). I am looking for benefits, drawbacks, & limitations of both approaches.
Specifically, my question is with regards to AVCam sample code by Apple where they observe few states as follows. This is done in CameraModel class which is attached to SwiftUI view.
// MARK: - Internal state observations
// Set up camera's state observations.
private func observeState() {
Task {
// Await new thumbnails that the media library generates when saving a file.
for await thumbnail in mediaLibrary.thumbnails.compactMap({ $0 }) {
self.thumbnail = thumbnail
}
}
Task {
// Await new capture activity values from the capture service.
for await activity in await captureService.$captureActivity.values {
if activity.willCapture {
// Flash the screen to indicate capture is starting.
flashScreen()
} else {
// Forward the activity to the UI.
captureActivity = activity
}
}
}
Task {
// Await updates to the capabilities that the capture service advertises.
for await capabilities in await captureService.$captureCapabilities.values {
isHDRVideoSupported = capabilities.isHDRSupported
cameraState.isVideoHDRSupported = capabilities.isHDRSupported
}
}
Task {
// Await updates to a person's interaction with the Camera Control HUD.
for await isShowingFullscreenControls in await captureService.$isShowingFullscreenControls.values {
withAnimation {
// Prefer showing a minimized UI when capture controls enter a fullscreen appearance.
prefersMinimizedUI = isShowingFullscreenControls
}
}
}
}
If we see the structure CaptureCapabilities, it is a small structure with two Bool members. These changes could have been directly observed by a SwiftUI view. I wonder if there is a specific advantage or reason to use AsyncStream here & continuously iterate over changes in a for loop.
/// A structure that represents the capture capabilities of `CaptureService` in
/// its current configuration.
struct CaptureCapabilities {
let isLivePhotoCaptureSupported: Bool
let isHDRSupported: Bool
init(isLivePhotoCaptureSupported: Bool = false,
isHDRSupported: Bool = false) {
self.isLivePhotoCaptureSupported = isLivePhotoCaptureSupported
self.isHDRSupported = isHDRSupported
}
static let unknown = CaptureCapabilities()
}
I'm trying to configure the share sheet.
My project uses techniques from the Apple Sample project called CoreDataCloudKitShare which is found here:
https://developer.apple.com/documentation/coredata/sharing_core_data_objects_between_icloud_users#
In this sample code there's a "PersistenceController" which is an NSPersistentCloudKitContainer.
In the "PersistenceController+SharingUtilities" file there are some extensions, and one of them is this:
func configure(share: CKShare, with photo: Photo? = nil) {
share[CKShare.SystemFieldKey.title] = "A cool photo"
}
This text "A cool photo" seems to be the only bespoke configuration of the share sheet within this project.
I want to have more options to control the share sheet, does anyone know how this might be achieved? Thank you!
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hello Apple Developer Community,
I am encountering an issue with app icon rendering after updating an app on devices running iOS 18 or newer. Below are the details:
Issue Summary:
When updating an app from a previous version (with separate light and dark mode icons) to the latest version (where both modes use the same icon), the icon changes are not reflected consistently across all system menus.
Steps to Reproduce:
Set the device mode to Dark Mode.
Install the previous app version (with different icons for light and dark modes).
Update the app to the latest version (where both modes use the same icon).
Change the device mode to Light Mode.
Switch back to Dark Mode.
Expected Behavior:
The app icon should remain consistent across all system menus (Home Screen, Spotlight search, etc.) when switching between Light and Dark Modes.
Observed Behavior:
The app icon displays correctly on the Home Screen but inconsistencies appear in other menus, such as Spotlight search or when toggling between modes.
For instance, in Dark Mode, the icon may revert to the previous black-colored logo or display incorrectly compared to the updated design.
Additional Notes:
The asset catalog is configured correctly, with identical icons set for both light and dark modes in the latest app version.
Incrementing the build number was implemented during the update.
A manual device restart resolves the issue on some devices, but not consistently.
Questions for the Community:
Has anyone else experienced similar app icon caching or rendering issues in iOS 18 or later?
Are there known workarounds or specific configurations to ensure consistent icon rendering across all system menus?
Could this be related to iOS 18's icon caching or appearance handling mechanisms?
Your insights and suggestions would be greatly appreciated. Thank you for your time!
Dear Senior Developer,
I come to you at a time where I am lost.
Over the last 2-3 months, I have noticed a series of crashes occuring on my app. This all started randomly and has now been a regular occurence. Usually, I would receive some detail as it relates to some class or view that is causing this error but now the only details I have is it relates to a UiViewController dealloc even though I am using SwiftUI.
Below I have attached the stack trace from firebase crash analytics. I have spent months on this and I am asking for the help of someone much more senior and knowledable to assist me in this regard.
Thanks again for your help and I await your response. I am also willing to share my screen LIVE to help you help me identify this issue.
manny.GoblinTools_issue_bfd18ee65a92b459d4ecef3475a9ec34_crash_session_032166c28b8c4764b13a6fdca636d2d6_DNE_0_v2_stacktrace.txt
I encountered a strange behavior that reminded me of when .sheet() modifiers didn't inherit environment objects. Unless I'm missing something very obvious, it seems to me that TableColumn may expose the same issue. At least on macOS, because the very same code does not crash on iOS.
I'm posting this here before reporting a SwiftUI bug.
Below is a gist for a playground:
https://gist.github.com/keeshux/4a963cdebb1b577b87b08660ce9d3364
I also observe inconsistent behavior when building with Xcode 16.1 or 15.4, specifically:
https://github.com/passepartoutvpn/passepartout/issues/872#issuecomment-2477687967
The workaround I resorted to is re-propagating the environment from the parent:
https://github.com/passepartoutvpn/passepartout/pull/873/files#diff-c662c4607f2adfd0d4e2c2a225e0351ba9c21dbdd5fc68f23bc1ce28a20bce4dR45
The dividing lines of List Section overlap, which is uncomfortable to look at.
Look at the line under "Incomplete"
May I inquire about the differences between the two ways of view under the hood in SwiftUI?
class MyViewModel: ObservableObject {
@Published var state: Any
init(state: Any) {
self.state = state
}
}
struct MyView: View {
@StateObject var viewModel: MyViewModel
var body: some View {
// ...
}
}
struct CustomView: View {
let navigationPath: NavigationPath
@StateObject var viewModel: MyViewModel
var body: some View {
Button("Go to My View") {
navigationPath.append(makeMyView())
}
}
}
// Option 1: A viewModel is initialized outside view's initialization
func makeMyView(state: Any) -> some View {
let viewModel = MyViewModel(state: state)
MyView(viewModel: viewModel)
}
// Option 2: A viewModel is initialized inside view's initialization
func makeMyView(state: Any) -> some View {
MyView(viewModel: MyViewModel(state: state))
}
For option 1, the view model will be initialized whenever custom view is re-rendered by changes whereas the view model is only initialized once when the view is re-rendered for option 2.
So what happens here?
I have a problem if i share photos as uiimage use code "UIImage.makeImage" this code run on iOS 15, 16 normally but if i share on iOS 17,18 to instagram story have error "Something went wrong". This case only error on Instagram story but Instagram post it's normal. Can anyone help me ? is it bug on instagram?
I have an app that uses UITextView for some text editing. I have some custom operations I can do on the text that I want to be able to undo, and I'm representing those operations in a way that plugs into NSUndoManager nicely. For example, if I have a button that appends an emoji to the text, it looks something like this:
func addEmoji() {
let inserting = NSAttributedString(string: "😀")
self.textStorage.append(inserting)
let len = inserting.length
let range = NSRange(location: self.textStorage.length - len, length: len)
self.undoManager?.registerUndo(withTarget: self, handler: { view in
view.textStorage.deleteCharacters(in: range)
}
}
My goal is something like this:
Type some text
Press the emoji button to add the emoji
Trigger undo (via gesture or keyboard shortcut) and the emoji is removed
Trigger undo again and the typing from step 1 is reversed
If I just type and then trigger undo, the typing is reversed as you'd expect. And if I just add the emoji and trigger undo, the emoji is removed. But if I do the sequence above, step 3 works but step 4 doesn't. The emoji is removed but the typing isn't reversed.
Notably, if step 3 only changes attributes of the text, like applying a strikethrough to a selection, then the full undo chain works. I can type, apply strikethrough, undo strikethrough, and undo typing.
It's almost as if changing the text invalidates the undo manager's previous operations?
How do I insert my own changes into UITextView's NSUndoManager without invalidating its chain of other operations?
If I have a Catalyst app with a WKWebView and I select text, I can drag forward to extend the selection, but I can't reduce the length of the selected range by dragging backwards. I've reproduced this in a trivial sample app.
Is there some property I need to set somewhere?
I've filed this as FB15645411.
Hey everyone,
TL;DR
How do I enable a draggable TableView to drop Audio Files into Apple Music / Rekordbox / Finder?
Intro / skip me
I've been dabbling into Swift / SwiftUI for a few weeks now, after roughly a decade of web development.
So far I've been able to piece together many things, but this time I'm stuck for hours with no success using Forums / ChatGPT / Perplexity / Trial and Error.
The struggle
Sometimes the target doesn't accept the dropping at all
sometimes the file data is failed to be read
when the drop succeeds, then only as a stream in apple music
My lack of understanding / where exactly I'm stuck
I think the right way is to use UTType.fileUrl but this is not accepted by other applications.
I don't understand low-level aspects well enough to do things right.
The code
I'm just going to dump everything here, it includes failed / commented out attempts and might give you an Idea of what I'm trying to achieve.
//
// Tracks.swift
// Tuna Family
//
// Created by Jan Wirth on 12/12/24.
//
import SwiftySandboxFileAccess
import Files
import SwiftUI
import TunaApi
struct LegacyTracks: View {
@State var tracks: TunaApi.LoadTracksQuery.Data?
func fetchData() {
print("fetching data")
Network.shared.apollo.fetch(query: TunaApi.LoadTracksQuery()) { result in
switch result {
case .success(let graphQLResult):
self.tracks = graphQLResult.data
case .failure(let error):
print("Failure! Error: \(error)")
}
}
}
@State private var selection = Set<String>()
var body: some View {
Text("Tracks").onAppear{
fetchData()
}
if let tracks = tracks?.track {
Table(of: LoadTracksQuery.Data.Track.self, selection: $selection) {
TableColumn("Title", value: \.title)
} rows : {
ForEach(tracks) { track in
TableRow(track)
.draggable(track)
// .draggable((try? File(path: track.dropped_source?.path ?? "").url) ?? test_audio.url) // This causes a compile-time error
// .draggable(test_audio.url)
// .draggable(DraggableTrack(url: test_audio.url))
// .itemProvider {
// let provider = NSItemProvider()
// if let path = self.dropped_source?.path {
// if let f = try? File(path: path) {
// print("Transferring", f.url)
//
//
// }
// }
//
// provider.register(track)
// return provider
// } // This does not
}
}
.contextMenu(forSelectionType: String.self) { items in
// ...
Button("yoooo") {}
} primaryAction: { items in
print(items)
// This is executed when the row is double clicked
}
} else {
Text("Loading")
}
// }
}
}
//extension Files.File: Transferable {
// public static var transferRepresentation: some TransferRepresentation {
// FileRepresentation(exportedContentType: .audio) { url in
// SentTransferredFile( self.)
// }
// }
//}
struct DraggableTrack: Transferable {
var url: URL
public static var transferRepresentation: some TransferRepresentation {
FileRepresentation (exportedContentType: .fileURL) { item in
SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true)
}
// FileRepresentation(contentType: .init(filenameExtension: "m4a")) {
// print("file", $0)
// print("Transferring fallback", test_audio.url)
// return SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true)
// }
// importing: { received in
// // let copy = try Self.(source: received.file)
// return Self.init(url: received.file)
// }
// ProxyRepresentation(exporting: \.url.absoluteString)
}
}
extension LoadTracksQuery.Data.Track: @retroactive Identifiable {
}
import UniformTypeIdentifiers
extension LoadTracksQuery.Data.Track: @retroactive Transferable {
// static func getKind() -> UTType {
// var kind: UTType = UTType.item
// if let path = self.dropped_source?.path {
// if let f = try? File(path: path) {
// print("Transferring", f.url)
// if (f.extension == "m4a") {
// kind = UTType.mpeg4Audio
// }
// if (f.extension == "mp3") {
// kind = UTType.mp3
// }
// if (f.extension == "flac") {
// kind = UTType.flac
// }
// if (f.extension == "wav") {
// kind = UTType.wav
// }
//
// }
// }
// return kind
// }
public static var transferRepresentation: some TransferRepresentation {
ProxyRepresentation {
$0.dropped_source?.path ?? ""
}
FileRepresentation(exportedContentType: .fileURL) { <#Transferable#> in
SentTransferredFile(<#T##file: URL##URL#>, allowAccessingOriginalFile: <#T##Bool#>)
}
// FileRepresentation(contentType: .fileURL) {
// print("file", $0)
// if let path = $0.dropped_source?.path {
// if let f = try? File(path: path) {
// print("Transferring", f.url)
// return SentTransferredFile(f.url, allowAccessingOriginalFile: true)
// }
// }
// print("Transferring fallback", test_audio.url)
// return SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true)
// }
// importing: { received in
// // let copy = try Self.(source: received.file)
// return Self.init(_fieldData: received.file)
// }
// ProxyRepresentation(exporting: \.title)
}
}
When working with SwiftUI TabView and ScrollView at root level with scrollPosition(id:anchor:), after tapping on Tab item the ScrollView scrolls to the top, but the scroll position ID does not get updated.
struct ContentView: View {
@State var positionID: Int?
var body: some View {
TabView {
Tab("Test", systemImage: "house") {
ScrollView(.vertical) {
LazyVStack(pinnedViews: [.sectionHeaders]) {
ForEach(0 ... 100, id: \.self) { index in
Text("\(index)")
}
}
.scrollTargetLayout()
}
.scrollPosition(id: $positionID, anchor: .top)
.onChange(of: positionID) { _, newValue in
print(newValue)
}
}
}
}
}
FB15964820
Is there a way to implement controls for background audio using ActivityKit like in the Apple Music application? I didn't found anything in your documentation about handling actions like this except deep links, but they're not suitable for this use case
I'm building an app that lets users create charts with custom values and while testing, I came up with this bug that happens when the view width forces the legend to have more than 1 line. Due to Swift trying to align the different labels vertically, it's forcing the first line to overflow.
Here's the code to generate this:
import SwiftUI
import Charts
struct DonutView: View {
var countries:[(country:String, count:Int)] = [
(country: "Africa", count: 54),
(country: "Asia", count: 48),
(country: "Europe", count: 44),
(country: "North America", count: 23),
(country: "Oceania", count: 14),
(country: "South America", count: 12),
]
var body: some View {
Chart {
ForEach(0..<countries.count, id:\.self) { idx in
SectorMark(
angle: .value(countries[idx].country, countries[idx].count),
innerRadius: .ratio(0.5)
)
.foregroundStyle(by: .value("label", countries[idx].country))
}
}
.frame(width: 310, height: 270)
.border(.blue, width: 1)
}
}
Has anyone seen this? Is there a solution?
I know about building custom legends, but SwiftUI has no wrapping HStack nor VStack, and the app allows users to change the legend position from the bottom to the top or sides. If I were to go this way, I'd have to write a very large chunk of code to bypass what seems to be a bug.
DESCRIPTION OF PROBLEM
When my Document-based macOS SwiftUI app starts up, it always presents a document picker. I would like it to open any documents that were open when the app last quit, and if none were open, open an "Untitled" document. I understand that there is a setting in System Settings-> Desktop & Dock ("Close windows when quitting an application") that will cause windows to reopen when it is turned off, but I'd like to give users a chance to opt-in for reopening docs even when that is turned on, since it is difficult to find, on by default, and might not be the desired behavior for all apps. I don't see any way to get a list of currently open documents to persist them at shutdown.
And even if that's considered a bad idea, I'd at least like a way to prevent the Document picker from being shown at startup and instead create an Untitled document if no documents were open.
Ideally, I'd like a way to provide this functionality in SwiftUI that doesn't require macOS 15 or later
STEPS TO REPRODUCE
Create a SwiftUI macOS document application in Xcode using the provided template, Give it any name you want
Run it, create a new ".exampletext" document, save it.
Quit the app with the document open.
Re-run the app, document picker is shown.
Cancel the document picker and quit the app with no windows shown.
Re-run the app, document picker is shown.
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?