I loaded usdz of a room model. After putting it into RealityView, the entire model surrounded me. Even if there was a SwiftUI View in front of me, I couldn't interact with it with my fingers. How do I set it up so that SwiftUI responds to my finger tap gesture first?
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hi, I have a SwiftUI Map with a set of three annotations. These annotations move around, and I would like to animate their movement from one coordinate to another, but I'm not finding a way to do that.
I've tried using withAnimation { } when setting my array of Identifiable models that back the Annotations, and I've tried adding the .animation(.default, annotationModels) modifier to my Map object (where annotationModels is the array that backs my Annotations).
The animation modifier doesn't work on Annotation structs, and it doesn't work if I add the animation modifier within the Annotation's view either.
Does anyone have any suggestions on how I might be able to animate the coordinates of annotations using a SwiftUI Map? Does the problem have to do with the fact that I have an array of these annotations?
Hello.
I've seen some other posts about NavigationStack, but my variation seems a little different.
FYI, I have not migrated from ObservableObject to Observable yet. However, having a path in either seems to be a factor in this issue.
My code has no issues when built with Xcode 15.
When built with Xcode 16 I keep hitting scenarios where the .onAppear for my first tab gets called over and over again endlessly.
If I go to my second tab, which uses a NavStack with a path and then navigate anywhere my .onAppear for my FIRST tab gets call endlessly. I’ll sometimes see a “double push” to the stack. (Someone posted a video of this happening on Mastodon, which apparently I’m not allowed to link to here.) The second tab is accessing the path property via an @EnvironmentObject.
I can stop this endless loop by removing @Published from the property in my ObservableObject that holds my path.
But then if I go to my third tab, which does NOT use a path, the .onAppear for my FIRST tab again gets called endlessly.
So far on Mastodon I’ve seen three people encountering problems possibly related to storing a path in something being observed.
Feedback requires a sample project, which I am having trouble creating to show the problem.
Is there any approach or sample code available to use these APIs:
.chartScrollableAxes(.horizontal)
.chartScrollPosition(x: ...)
.chartScrollPosition(initialX: ...)
.chartScrollTargetBehavior(...)
.chartXVisibleDomain(length: ...)
Plus a gesture recognised or Pinch or Magnification to create a Swift Chart with an X axis that can be zoomed in or out with a pinch gesture? And when zoomed in at any level above 0, the chart can then be scrolled left to right along the X axis.
I've had success using .chartScrollableAxes with .chartXSelection in parallel, so would also like to keep the ability to select X values too.
Hello!
I'm building a Countdown Timer for the Dynamic Island using a Live Activity.
I have two issues for which I can't find any solution:
We want to display the time in the "X minutes" format, like in this example. I went through the forum but all the answers were wrong, because they were using a Text(:format) which never updates in the live activity, or a Text(:timerInterval) which we can't format.
I want the Live Activity to end once the timer gets to zero. I found this staleDate parameter that I thought would helped, but is actually only adding loaders on my design once the date is reached. I tried to implement a solution like the answer of this post, but the if (context.isStale) {...} part is never being rendered. It also looks like the stale sate gets activated only when the app is focus again.
I tried several fixes, went through a lot of forum and posts, but I can't find any solution.
Thanks!
Hi,
I have the below code and don't know why the text doesn't show fro swipe buttons just the icons show ?
Kind Regards
import SwiftUI
struct NewView: View {
var body: some View {
NavigationStack {
List {
ForEach(1...7, id: \.self) { number in
VStack {
Text("Item \(number)")
.padding()
}
.swipeActions(edge: .trailing) {
Button(role: .destructive) {
withAnimation {
deletePatient2()
}
} label: {
Label("Delete", systemImage: "trash.fill")
}
Button {
deletePatient2()
// toDoToEdit = item
} label: {
Label("Edit", systemImage: "pencil")
}
.tint(.orange)
}
}
}
}
.listStyle(.plain)
}
func deletePatient2() {
}
}
#Preview {
NewView()
}
The cursor is moved by the app in a Text area. iPadOS allows touch screen cursor movement to cut, copy, paste and insert text. When text is highlighted via handle controls, and cut requested, the app fails with cursor out of bounds. The app cursor was not moved in sync with IOS. It is obvious IOS does not sync with the app cursor position and the update of the endIndex.
I found a regression in Apple Vision OS 2.0 beta 3 (22N5277g).
Previously, it was possible to trigger the .onDelete swipe gesture on a List/ForEach with a virtual mouse (i.e. remote desktop), however this is no longer possible (a finger pinch still works).
Sample code to reproduce the issue:
//
// ContentView.swift
// TextInputTest
//
import SwiftUI
struct ListElement: Identifiable {
let id = UUID()
let content: String
}
struct ContentView: View {
@State var list = [
ListElement(content: "a"),
ListElement(content: "b"),
ListElement(content: "c")
]
var body: some View {
List {
ForEach(list) { element in
Text(element.content)
}
.onDelete { _ in
// No-op.
}
}
}
}
Hello everyone,
I wanted to double check with the UI Framework team to see if there's a mistake in my code or if there's some sort of regression.
My goal is to have a user input text without any automatic modification of said text, namely remove auto-capitalization and auto-correct.
//
// ContentView.swift
// TextInputTest
//
import SwiftUI
struct ContentView: View {
@State var text: String = "Enter some text here!"
var body: some View {
VStack {
TextEditor(text: $text)
.autocorrectionDisabled(true)
.textInputAutocapitalization(.never)
.font(Font.custom("SF Mono", size: 30))
.monospaced()
.padding(20)
}
.padding()
}
}
However, when typing the following: "This is a sentence" followed by a few spaces, a dot will automatically be inserted, making the string become: "This is a sentence.".
Reproduced on: VisionOS 2.0 beta 3 (22N5277g)
Dear all,
I am experiencing some problems with the Drag Gesture in VisionOS. Typically, this gesture involves the user pinching an entity or, more commonly, a window, and moving/dragging it around. However, this is not always the case for entities (3D models) placed in the environment. It appears that the user can both pinch and drag and/or move the entity with their bare hands.
In the latter case, the onChange cycle doesn't always end if the user keeps their hands near the object, causing it to keep moving even if that is not what the user intends. This also occurs when the user is no longer hovering over that entity. Larger entities, more so than those in the demo "TransformingRealityKitEntitiesUsingGestures," close to the user seem to become attached to their hands, causing the gesture to continue indefinitely. Entities often move to unintended positions.
I believe that these two different behaviors within the same gesture container are intrinsically different: one involves pinching and dragging, while the other involves enabling hands physics, and it should be easy to distinguish between the two.
How can we correctly address this situation?
Thank you for your assistance
ToolbarItem in group is not conforming to view for some reason, here's my code:
var body: some View {
NavigationStack {
Form {
TextField("Company Name", text: $companyName)
TextField("Role", text: $role)
TextField("Location", text: $location)
TextField("Yearly Salary", value: $yearlySalary, format: .currency(code: "USD"))
.keyboardType(.decimalPad)
}
.navigationTitle("Add Application")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("back") {
dismiss()
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
let appdata = ApplicationData(
companyName: companyName,
role: role,
location: location,
yearlySalary: yearlySalary,
dateApplied: dateApplied,
notes: notes)
// Save the application data
dismiss()
}
}
}
}
}
The error reads: Static method 'buildExpression' requires that 'ToolbarItem<(), Button>' conform to 'View'
I'm trying to change it up but I can't get past this error for some reason
I have backend API caller file that retrieves and displays unwrapped JSON data via URLRequest(). All the data is printed to my console when I build the project but it's not being displayed in the actual UI of my iOS simulator.
I have a class in my ContentView that updates the UI and filters the extracted fields shown here below:
class NotionCall: ObservableObject {
@Published var extractedContent: [BlockBody.Block] = []
func makeAPIRequest() {
makeRequest { results in
let extractedData = results.map { block -> BlockBody.Block in
var extractedBlock = block
extractedBlock.ExtractedFields = block.paragraph?.textFields.compactMap { textField in
textField.PlainText ?? textField.RichText ?? textField.content //iterate over PlainText, RichText, and Content fields and return the non nill values
} ?? [] //validate objects even if they are nil
return extractedBlock
}
DispatchQueue.main.async {
self.extractedContent = extractedData
}
}
}
}
@StateObject var NotionCaller = NotionCall() //manage lifecycle of instance
And then below here is my SwiftUI structure that contains List(NotionCaller.extractedContent) { block in ForEach(block.ExtractedFields, id: \.self) { field in Text(field) meant to display the extracted data to the UI:
var body: some View {
NavigationStack {
ZStack {
List(NotionCaller.extractedContent) { block in
ForEach(block.ExtractedFields, id: \.self) { field in
Text(field)
}
}
ZStack {
Color(hex: "#f9f9f9")
.ignoresSafeArea()
VStack {
TextField(" Search keywords", text: $searchKeywords) //change font later
.frame(height: 48)
.overlay(RoundedRectangle(cornerRadius: 30).strokeBorder(style: StrokeStyle()))
.foregroundColor(.white)
.background(.white)
.cornerRadius(30)
.padding()
.scaledToFit()
.frame(maxHeight: .infinity, alignment: .top)
}
VStack {
Spacer()
Divider()
.padding()
HStack {
Button(action: { //add functionality later
}) {
Image("menuButton")
.frame(alignment: .bottom)
.padding(.horizontal, 42)
Spacer()
}
HStack {
Button(action: { //add functionality later
}) {
Image("notificationButton")
.frame(alignment: .leading)
.padding(.leading, 30)
Spacer()
}
}
HStack {
Button(action: {
}) {
Image("notionImportButton")
.frame( alignment: .trailing)
.padding(.horizontal)
.padding(.horizontal)
}
}
}
.onAppear {
NotionCaller.makeAPIRequest()
}
}
}
}
}
}
}
Hi everyone,
I’m having an issue with SwiftUI where my entire Section becomes clickable, instead of just the “Edit profile” button. Here’s my code:
VStack(alignment: .center) {
KFImage(authManager.user?.photoURL)
.resizable()
.scaledToFill()
.frame(width: 80, height: 80)
.clipShape(Circle())
Text(authManager.user?.displayName ?? "")
.font(.system(.title, design: .rounded))
Text(authManager.user?.email ?? "")
.font(.subheadline)
.foregroundColor(.gray)
NavigationLink {
EditProfileView()
} label: {
Text("Edit profile")
.frame(minWidth: 0, maxWidth: .infinity)
.font(.system(size: 18))
.padding(10)
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(25)
}
.padding(.top, 5)
}
.frame(maxWidth: .infinity, alignment: .center)
}
I want only the button to be clickable. How can I fix this?
Thanks!
Link to issue: https://imgur.com/a/iO9aNSM
Task:
A child view should show depending on a boolean flag the corresponding view. The flag is calculated from a model which is given by parent view.
Problem:
The flag is false in init, which is correct. However in body it's true, which is incorrect. Why value in body isn't consistent to init? Is there a race condition? The child view's is rendered thrice, that's another issue, but flag is in init and body as described before.
Parent view looks like this:
struct ParentView: View {
private var groupedItems: [GroupedItems] = []
init(items: [Item]) {
Dictionary(grouping: items) { $0.category.name }
.forEach {
let groupedItems = GroupedItems(categoryName: $0.key, items: $0.value)
self.groupedItems.append(groupedItems)
}
}
var body: some View {
ChildView(groupedItems)
}
}
Child view looks like this:
struct ChildView: View {
@State private var showItems: Bool
init(_ groupedItems: GroupedItems) {
self._showItems = State(initialValue: !groupedItems.completed)
}
var body: some View {
if showItems {
AView()
} else {
BView()
}
}
}
Model looks like this:
@Model
final class Item: Identifiable {
@Attribute(.unique) public var id: String
public var name: String
public var completed = false
}
struct GroupedItems {
var categoryName: String
var items: [Item]
var completed: Bool {
items.filter { !$0.completed }.isEmpty
}
}
brand new newbie developer to xcode. so im doing an api call and getting back data from a mysql database. in the xcode preview window im getting data, but i cant figure out how to tie it to the screen when going into the simulator. i have screen 1 that i want to click a button to go to screen 2 that displays the data. screen one (home screen) comes up okay. cant quite figure out what im doing wrong here. im thinking its either a class issue or something to do with view or something. not sure. ive tried looking at so many different videos and i cant seem to find my answer. Any help would be appreciated. thank you
View Controller:
import UIKit
//import SwiftUI
let URL_TOURNAMENT_FETCH = "https://www.thesoftball.com/t2g_mobile_app/mobile_api.php"
class ViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
}
@IBAction func onEmailButtonPressed(_ sender: Any)
{
UIApplication.shared.open(URL(string: "mailto:[email]")! as URL, options: [:],completionHandler: nil)
}
/*
@IBAction func FetchTournButton(_ sender: Any) {
UIApplication.shared.open(URL(string: "https://www.thesoftball.com/t2g_mobile_app/mobile_api.php")! as URL, options: [:],completionHandler: nil)
}
*/
@IBAction func ViewTournamentButton(_ sender: Any)
{
// the following is a popup
let alertController = UIAlertController(title: "Welcome to My First App", message: "Hello World", preferredStyle: UIAlertController.Style.alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
present(alertController, animated: true, completion: nil)
}
@IBAction func account_button_pressed(_ sender: Any)
{
UIApplication.shared.open(URL(string: "https://www.thesoftball.com")! as URL, options: [:],completionHandler: nil)
}
/*
struct viewDidLoadModifier: viewDidLoadModifier
{
@State private var didLoad = false
private let action: (() -> void)?
init(perform action)
{
}
}
*/
}
ContentView (preview works in this)
import SwiftUI
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
NavigationView{
List{
ForEach(viewModel.courses,id: \.self) { tournament in
HStack {
Image("")
.frame(width: 5, height: 120)
.background(Color.orange)
VStack {
Text(tournament.name).bold()
Text(tournament.dates)
Text(tournament.datee)
Text(tournament.location)
// Text(course.location)
// Text(course.message)
// .bold()
}
}
.padding(0)
}
}
.navigationTitle("Tournaments")
// .onAppear { viewModel.fetch()}
.onAppear(perform: viewModel.fetch)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I recently compiled my macOS App with Swift 6 in Xcode 16 (was using Swift 5 previously) and noticed that AppKit Integration doesn't appear to be working as before. All my instances of NSHostingView which allow me to add a SwiftUI View to an AppKit NSWindow view controller no longer respond to mouse input anymore. All my NSHostingView instances display but refuse to accept any user interaction. Has anyone else noticed this and is there a workaround to get NSHostingView to once again be able to accept user/mouse events with Swift 6?
I am making application where I use navigation link to navigate from bottom menu to other views, and there is a problem when I change view a few times because views start stacking and when I set navigationBarBackButtonHidden(false) I can see on left side a lot of back button. This generate big problem because after changing views I got warning Abnormal number of gesture recognizer dependencies: 100. System performance may be affected. Please investigate reducing gesture recognizers and/or their dependencies. And after some more changes everything from screen is pushed down back button. Is there any solution to close previous view from we came?
There is code:
//
// BottomMenu.swift
// SpaceManager
//
// Created by Kuba Kromomołowski on 04/05/2024.
//
import SwiftUI
import Firebase
import FirebaseAuth
struct BottomMenu: View {
@StateObject var logManager = MainViewModel()
@StateObject var mvm = MenuViewModel()
@State var condition1: Bool = true
@State var condition2: Bool = false
@State var condition3: Bool = false
// @StateObject private var cameraViewModel = CameraViewModel()
var body: some View {
HStack{
Group{
//.navigationBarBackButtonHidden(true)
Spacer()
BtnMenu(btnText: "Dodaj",
btnIcon: "plus.app.fill",
destinationView:AnyView(LoggedMainView()),
isActive: condition1
)
Spacer()
BtnMenu(btnText: "Szukaj",
btnIcon: "magnifyingglass",
destinationView:AnyView(SearchView()),
isActive: condition2
)
Spacer()
BtnMenu(btnText: "Profil",
btnIcon: "person.crop.circle.fill",
destinationView:AnyView(ProfileView()),
isActive: condition3
)
Spacer()
}.padding(.bottom, 30)
.font(.system(size: 20))
}
}
}
#Preview {
BottomMenu()
}
//
// BtnMenu.swift
// SpaceManager
//
// Created by Kuba Kromomołowski on 04/05/2024.
//
import SwiftUI
struct BtnMenu: View {
var btnText: String
var btnIcon: String
var destinationView: AnyView
@State var isActive: Bool = true
var body: some View {
NavigationLink{
destinationView
} label: {
ZStack {
Text("\(Image(systemName: btnIcon)) \(btnText)")
}
}.disabled(isActive)
}
}
I am trying to configure scenes to capture a redirect URL after a successful login attempt. I am using OAuth code flow. This is the code I have so far:
ios_app.swift
import SwiftUI
@main
struct ios_appApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
let persistenceController = PersistenceController.shared
@StateObject private var authState = AuthState()
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.environmentObject(authState)
}
}
}
AppDelegate.swift
import UIKit
import AWSMobileClient
import GoogleSignIn
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("AppDelegate: didFinishLaunchingWithOptions")
AWSMobileClient.default().initialize { (userState, error) in
if let userState = userState {
print("UserState: \(userState)")
} else if let error = error {
print("Error initializing AWSMobileClient: \(error.localizedDescription)")
}
}
GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
if let error = error {
print("Error restoring previous Google Sign-In: \(error.localizedDescription)")
}
}
return true
}
}
SceneDelegate.swift
import UIKit
import SwiftUI
import GoogleSignIn
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
print("SceneDelegate: scene willConnectTo")
guard let windowScene = (scene as? UIWindowScene) else {
print("SceneDelegate: Invalid windowScene")
return
}
let window = UIWindow(windowScene: windowScene)
let contentView = ContentView().environmentObject(AuthState())
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
print("SceneDelegate: window initialized and visible")
}
func sceneDidDisconnect(_ scene: UIScene) {
print("SceneDelegate: sceneDidDisconnect")
}
func sceneDidBecomeActive(_ scene: UIScene) {
print("SceneDelegate: sceneDidBecomeActive")
}
func sceneWillResignActive(_ scene: UIScene) {
print("SceneDelegate: sceneWillResignActive")
}
func sceneWillEnterForeground(_ scene: UIScene) {
print("SceneDelegate: sceneWillEnterForeground")
}
func sceneDidEnterBackground(_ scene: UIScene) {
print("SceneDelegate: sceneDidEnterBackground")
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else {
print("SceneDelegate: No URL found in URLContexts")
return
}
print("SceneDelegate: openURLContexts with URL: \(url)")
if GIDSignIn.sharedInstance.handle(url) {
print("SceneDelegate: Google Sign-In handled URL")
return
}
if url.scheme == "myurlscheme" || (url.scheme == "https" && url.host == "mydomain.com" && url.path == "/mobile-auth-callback") {
print("SceneDelegate: Handling auth response for URL: \(url)")
AuthService.shared.handleOAuthCallback(url: url)
} else {
print("SceneDelegate: URL scheme not handled: \(url.scheme ?? "No scheme")")
}
}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
print("SceneDelegate: continue userActivity")
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
if let url = userActivity.webpageURL {
handleUniversalLink(url: url)
}
}
}
private func handleUniversalLink(url: URL) {
print("SceneDelegate: Handling universal link: \(url)")
if url.path.contains("/mobile-auth-callback") {
let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems
let code = queryItems?.first(where: { $0.name == "code" })?.value
if let code = code {
print("SceneDelegate: Received code: \(code)")
AuthService.shared.exchangeCodeForToken(code: code)
} else {
print("SceneDelegate: No code found, handling email/password callback")
AuthService.shared.handleEmailPasswordCallback(url: url)
}
}
}
}
Also introduced this configuration in Info.plist:
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>ios-app.SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
...Other parameters
</dict>
</plist>
I am using the simulator to launch my app and can see AppDelegate related logs but I am not seeing any SceneDelegate logs (I suppose because it is not being initialized nor called).
I have tried restarting the computer/Xcode, clean and rebuild the application but none of the things I tested work.
Is there any part of my code wrong? Any other idea here?
I am in the process of adding my company's brand font to our SwiftUI app. I am able to implement the font using the provided public APIs so that text styles / dynamic type and the font weight modifier in SwiftUI work correctly.
However we are unable to implement custom font in such a way that text styles / dynamic type, the font weight modifier, and the bold text accessibility setting all work at the same time. Am I missing an implementation detail so that all these features work correctly?
Font Setup
The font files were modified to better support SwiftUI:
The font style name metadata was modified to match the name the .fontWeight(...) modifier expects. This was done with Typelight.
The font weight value (100/200/300) was modified so that the underlying weight value matches the value the .fontWeight(...) modifier expects. See "Using custom fonts with SwiftUI" by Matthew Flint.
The font files were imported via the Info.plist.
Examples
Font Weight Comparison
San Fransisco:
Text("#100")
.font(.largeTitle)
.fontWeight(.ultraLight)
Overpass by Name:
Text("#100")
.font(.custom("Overpass-UltraLight", size: 34, relativeTo: .largeTitle))
Overpass by Weight:
Text("#100")
.fontWeight(.ultraLight)
.font(.custom("Overpass", size: 34, relativeTo: .largeTitle))
Legibility Weight Test
When using the .fontWeight(...) modifier, the custom font does not change weights when the bold text accessibility setting is enabled. Dynamic type size works as expected.
Normal legibility weight:
Bold legibility weight:
Dynamic Type Size:
Use UIFont
Using UIFont to load the custom font files and initializing a Font with the UIFont breaks dynamic type:
Bold type also does not work:
Custom Modifier
Creating a custom modifier allows us to support dynamic type and manually handle bold text. However it creates a conflicting API to SwiftUI's .fontWeight(...) modifier.
struct FontModifier: ViewModifier {
enum UseCase {
case paragraph
case headline
}
enum Weight {
case light
case regular
case heavy
}
@Environment(\.legibilityWeight) var legibilityWeight
var useCase: UseCase
var weight: Weight
init(_ useCase: UseCase, _ weight: Weight) {
self.useCase = useCase
self.weight = weight
}
var resolvedHeadlineWeight: String {
let resolvedLegibilityWeight = legibilityWeight ?? .regular
switch weight {
case .light:
switch resolvedLegibilityWeight {
case .regular:
return "Light"
case .bold:
return "Semibold"
@unknown default:
return "Light"
}
case .regular:
switch resolvedLegibilityWeight {
case .regular:
return "Regular"
case .bold:
return "Bold"
@unknown default:
return "Regular"
}
case .heavy:
switch resolvedLegibilityWeight {
case .regular:
return "Heavy"
case .bold:
return "Black"
@unknown default:
return "Heavy"
}
}
}
var resolvedParagraphWeight: Font.Weight {
switch weight {
case .light:
return .light
case .regular:
return .regular
case .heavy:
return .heavy
}
}
var resolvedFont: Font {
switch useCase {
case .paragraph:
return .system(.largeTitle).weight(resolvedParagraphWeight)
case .headline:
return .custom("Overpass-\(resolvedHeadlineWeight)", size: 34, relativeTo: .largeTitle)
}
}
func body(content: Content) -> some View {
content
.font(resolvedFont)
}
}
GridRow {
Text("Aa")
.modifier(FontModifier(.paragraph, .regular))
Text("Aa")
.modifier(FontModifier(.paragraph, .heavy))
Text("Aa")
.modifier(FontModifier(.headline, .regular))
Text("Aa")
.modifier(FontModifier(.headline, .heavy))
}
Font Environment Value
The font environment value does not contain font weight information when the fontWeight(...) modifier is used.:
struct DumpFontTest: View {
@Environment(\.font) var font
var body: some View {
Text("San Fransisco")
.onAppear {
print("------------")
dump(font)
}
}
}
I'm developing an app where users can select items to add to a screen, similar to creating a Canva presentation or choosing blocks in Minecraft. However, I'm encountering an issue with energy usage. When users click the arrows to browse different items, the energy use spikes significantly. Although it returns to normal after a while, continuous clicking causes the energy use to skyrocket. The images I'm using are 500x500 pixels. Ideally, I would like to avoid caching all the images, as the app might have up to 500 items and caching them all would consume too much memory. I have tried numerous way to avoid this but I just can’t seem to make it work. Would anyone know how to avoid such problem?
I have included a picture of the energy use when just opened, and one after like 10 seconds of continuously clicking on an arrow to see more items. Also a picture of how the app looks.
struct ContentView: View {
struct babyBackground {
var littleImage = ""
}
@State var firstSet: [babyBackground] = [
babyBackground(littleImage: "circle"),
babyBackground(littleImage: "square"),
babyBackground(littleImage: "triangle"),
babyBackground(littleImage: "anotherShape"),
babyBackground(littleImage: "circle"),
babyBackground(littleImage: "square"),
babyBackground(littleImage: "triangle"),
babyBackground(littleImage: "anotherShape")
]
@State var secondSet: [babyBackground] = [
babyBackground(littleImage: "circle"),
babyBackground(littleImage: "square"),
babyBackground(littleImage: "triangle"),
babyBackground(littleImage: "anotherShape"),
babyBackground(littleImage: "circle"),
babyBackground(littleImage: "square"),
babyBackground(littleImage: "triangle"),
babyBackground(littleImage: "anotherShape"),
babyBackground(littleImage: "circle")
]
@State var thirdSet: [babyBackground] = [
babyBackground(littleImage: "circle"),
babyBackground(littleImage: "square"),
babyBackground(littleImage: "triangle"),
]
let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 4)
func createBackgroundGridView(for backgrounds: [babyBackground], columns: [GridItem] ) -> some View {
LazyVGrid(columns: columns, spacing: 10) {
ForEach(0..<backgrounds.count, id: \.self) { index in
Button(action: {
}, label: {
if let path = Bundle.main.path(forResource: backgrounds[index].littleImage, ofType: "png"), let uiImage = UIImage(contentsOfFile: path) {
Image(uiImage: uiImage)
.resizable()
.frame(width: 126, height: 96)
}
})
}
}
.padding()
}
@State var indexOn = 0
var body: some View {
HStack{
Button(action: {
indexOn = (indexOn == 0) ? 2 : indexOn - 1
}) {
Label("", systemImage: "arrowtriangle.left.fill")
.font(.system(size: 50))
}
Spacer()
ScrollView {
switch indexOn {
case 0: createBackgroundGridView(for: firstSet, columns: columns)
case 1: createBackgroundGridView(for: secondSet, columns: columns)
case 2: createBackgroundGridView(for: thirdSet, columns: columns)
case 3: createBackgroundGridView(for: thirdSet, columns: columns)
default: createBackgroundGridView(for: firstSet, columns: columns)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
Spacer()
Button(action: {
indexOn = (indexOn == 2) ? 0 : indexOn + 1
}) {
Label("", systemImage: "arrowtriangle.right.fill")
.font(.system(size: 50))
}
}
}
}
Energy Use when app starts:
Energy use after clicking for about 10 seconds:
App UI: