Post

Replies

Boosts

Views

Activity

Reply to Attempting to add scrubbing to UISlider
OK, it's better. What is the problem, precisely ? What do you get ? What did you expect ? Please show screenshots. Here are my screenshots showing it is working, but thumb can move out of slider, which is probably not expected: You can force the thumb inside slider by making the following change: override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect { let thumbDiameter = CGFloat(defaultDiameter * value) let origin = CGPoint(x: (currentLocation?.x ?? bounds.width / 2) - thumbDiameter / 2, y: 0 /*(currentLocation?.y ?? thumbDiameter / 2) - thumbDiameter / 2*/) // <<-- CHANGED return CGRect(origin: origin, size: CGSize(width: thumbDiameter, height: thumbDiameter)) }
Topic: UI Frameworks SubTopic: UIKit Tags:
Aug ’24
Reply to Attempting to add scrubbing to UISlider
Could you explain what you mean and expect exactly by 'scrubbing' ? This line does not compile (UIColor has no circle attribute) let thumbImage = UIColor.red.circle(CGSize(width: thumbDiameter, height: thumbDiameter)) Is there a line missing ? Or did you define an extension (if so, please provide it). I change the thumbImage to some systemImage. It compiles, but screen remains empty. So I added a background to SizeSlider and I get it on screen. But just a coloured rect, not a slider. Could you show what you get ? I completed code as follows, and now thumb (and slider) increase size. But thumb can get out of slider, is not saved at the end of school… Looks like there are missing parts in your code. extension UIImage { static func from(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1 return UIGraphicsImageRenderer(size: size, format: format).image { context in color.setFill() context.fill(CGRect(origin: .zero, size: size)) } } } class SizeSliderView: UISlider { private var previousLocation: CGPoint? private var currentLocation: CGPoint? private var translation: CGFloat = 0 private var scrubbingSpeed: CGFloat = 1 private var defaultDiameter: Float init(startValue: Float = 0, defaultDiameter: Float = 500) { self.defaultDiameter = defaultDiameter super.init(frame: .zero) value = clamp(value: startValue, min: minimumValue, max: maximumValue) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func draw(_ rect: CGRect) { super.draw(rect) clear() createThumbImageView() addTarget(self, action: #selector(valueChanged(_:)), for: .valueChanged) } // Clear elements private func clear() { tintColor = .clear maximumTrackTintColor = .clear backgroundColor = .clear thumbTintColor = .clear } // Call when value is changed @objc private func valueChanged(_ sender: SizeSliderView) { CATransaction.begin() CATransaction.setDisableActions(true) CATransaction.commit() createThumbImageView() } // Create thumb image with thumb diameter dependent on thumb value private func createThumbImageView() { let thumbDiameter = CGFloat(defaultDiameter * value) // let thumbImage = UIColor.red.circle(CGSize(width: thumbDiameter, height: thumbDiameter)) let thumbImage = UIImage.from(color: .blue, size: CGSize(width: thumbDiameter, height: thumbDiameter)) setThumbImage(thumbImage, for: .normal) setThumbImage(thumbImage, for: .highlighted) setThumbImage(thumbImage, for: .application) setThumbImage(thumbImage, for: .disabled) setThumbImage(thumbImage, for: .focused) setThumbImage(thumbImage, for: .reserved) setThumbImage(thumbImage, for: .selected) } // Return true so touches are tracked override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { let location = touch.location(in: self) // Ensure that start location is on thumb let thumbDiameter = CGFloat(defaultDiameter * value) print(location, bounds, thumbDiameter) if location.x < bounds.width / 2 - thumbDiameter / 2 || location.x > bounds.width / 2 + thumbDiameter / 2 || location.y < 0 || location.y > thumbDiameter { return false } previousLocation = location super.beginTracking(touch, with: event) return true } // Track based on moving slider override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { guard isTracking else { return false } guard let previousLocation = previousLocation else { return false } // Reference // location: location of touch relative to device // delta location: change in touch location WITH scrubbing // adjusted location: location of touch to slider bounds (WITH scrubbing) // translation: location of slider relative to device let location = touch.location(in: self) currentLocation = location scrubbingSpeed = getScrubbingSpeed(for: location.y - 50) let deltaLocation = (location.x - previousLocation.x) * scrubbingSpeed var adjustedLocation = deltaLocation + previousLocation.x - translation if adjustedLocation < 0 { translation += adjustedLocation adjustedLocation = deltaLocation + previousLocation.x - translation } else if adjustedLocation > bounds.width { translation += adjustedLocation - bounds.width adjustedLocation = deltaLocation + previousLocation.x - translation } self.previousLocation = CGPoint(x: deltaLocation + previousLocation.x, y: location.y) let newValue = Float(adjustedLocation / bounds.width) * (maximumValue - minimumValue) + minimumValue setValue(newValue, animated: false) sendActions(for: .valueChanged) return true } // Reset start and current location override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { self.currentLocation = nil self.translation = 0 super.touchesEnded(touches, with: event) } // Thumb location follows current location and resets in middle override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect { let thumbDiameter = CGFloat(defaultDiameter * value) let origin = CGPoint(x: (currentLocation?.x ?? bounds.width / 2) - thumbDiameter / 2, y: (currentLocation?.y ?? thumbDiameter / 2) - thumbDiameter / 2) return CGRect(origin: origin, size: CGSize(width: thumbDiameter, height: thumbDiameter)) } private func getScrubbingSpeed(for value: CGFloat) -> CGFloat { switch value { case 0: return 1 case 0...50: return 0.5 case 50...100: return 0.25 case 100...: return 0.1 default: return 1 } } private func clamp(value: Float, min: Float, max: Float) -> Float { if value < min { return min } else if value > max { return max } else { return value } } } //UIView representative: struct SizeSlider: UIViewRepresentable { private var startValue: Float private var defaultDiameter: Float init(startValue: Float, defaultDiameter: Float) { self.startValue = startValue self.defaultDiameter = defaultDiameter } func makeUIView(context: Context) -> SizeSliderView { let view = SizeSliderView(startValue: startValue, defaultDiameter: defaultDiameter) view.minimumValue = 0.1 view.maximumValue = 1 return view } func updateUIView(_ uiView: SizeSliderView, context: Context) { } } struct ContentView: View { var body: some View { SizeSlider(startValue: 0.20, defaultDiameter: 100) .frame(width: 400) .background(.red). // Just to see something .opacity(0.1) } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Aug ’24
Reply to Will a Major Update from Flutter to SwiftUI Affect App Store Review Approval?
Will the review process reject the update due to the significant changes in the app? Not at all. Apps do evolve significantly in new releases, either functionally or technically. They don't mind as long that you comply with guidelines. You don't even have to mention the change from Flutter. In fact it would probably be seen as a positive move as more future proof and guaranteed multi platforms.
Aug ’24
Reply to Stack feature not working as per plan.
And now with progress bar overlaying: struct ContentView: View { let barHeight: CGFloat = 30 let barColor = Color.gray let duration: Double = 10 let icon = "globe" @State private var progress: CGFloat = 0 var body: some View { ZStack(alignment: .leading) { // VStack { // Background bar RoundedRectangle(cornerRadius: 10) // .fill(Color.gray.opacity(0.3)) // .frame(height: barHeight) // Set height to the specified barHeight // Progress bar // GeometryReader { geometry in RoundedRectangle(cornerRadius: 10) .fill(barColor.opacity(0.5)) // To see through .frame(width: CGFloat(progress) * UIScreen.main.bounds.width, height: barHeight) // .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight) .animation(.linear(duration: 10), value: progress) // } // .cornerRadius(10) // That's redundant // Icon and label HStack { Rectangle() // to avoid frame moving when animation starts) .fill(.clear) .frame(width: UIScreen.main.bounds.width * 0.05, height: barHeight) Image(systemName: icon) .foregroundColor(.black) .font(.system(size: 28)) // Increased size .padding(.leading, 8) .onTapGesture { progress = 1 // Added to see progress } Spacer() Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress))) .foregroundColor(.black) .bold() .font(.system(size: 24)) // Increased size .padding(.trailing, 8) } .frame(width: UIScreen.main.bounds.width/* * 0.9*/, height: barHeight) // Changed to avoid frame moving when animation starts .zIndex(1) // Ensure the HStack is on top Spacer() // ADDED THIS } .padding(.horizontal) } } We get this during progress: May be we could use overlay, but did not try.
Topic: Programming Languages SubTopic: Swift Tags:
Aug ’24
Reply to Stack feature not working as per plan.
What is ProgressiveBar ? Is it RoundedRectangle(cornerRadius: 10) What do you mean by above or on top. Please show what you get and what you want. Why do you need geometry reader and not just set the zIndex of the progress bar ? I edited your code to guess and complete missing parts: struct ContentView: View { let barHeight: CGFloat = 30 let barColor = Color.gray let duration: Double = 10 let icon = "globe" @State private var progress = 0 var body: some View { ZStack(alignment: .leading) { // Background bar RoundedRectangle(cornerRadius: 10) // .fill(Color.gray.opacity(0.3)) // .frame(height: barHeight) // Set height to the specified barHeight // Progress bar GeometryReader { geometry in RoundedRectangle(cornerRadius: 10) .fill(barColor) .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight) .animation(.linear(duration: 10), value: progress) } .cornerRadius(10) // Icon and label HStack { Image(systemName: icon) .foregroundColor(.black) .font(.system(size: 28)) // Increased size .padding(.leading, 8) .onTapGesture { progress = 10 // Added to see progress } Spacer() Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress))) .foregroundColor(.black) .bold() .font(.system(size: 24)) // Increased size .padding(.trailing, 8) } .frame(width: UIScreen.main.bounds.width * 0.9, height: barHeight) .zIndex(1) // Ensure the HStack is on top } .padding(.horizontal) } } The progressBar is above: I changed ZStack to VStack and removing geometryReader and get this: struct ContentView: View { let barHeight: CGFloat = 30 let barColor = Color.gray let duration: Double = 10 let icon = "globe" @State private var progress = 0 var body: some View { // ZStack(alignment: .leading) { VStack { // Set height to the specified barHeight // Progress bar // GeometryReader { geometry in // REMOVED RoundedRectangle(cornerRadius: 10) .fill(barColor) .frame(width: CGFloat(progress) * UIScreen.main.bounds.width, height: barHeight) // WE CAN get screen width directly // .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight) .animation(.linear(duration: 10), value: progress) // } .cornerRadius(10) // Icon and label HStack { Image(systemName: icon) .foregroundColor(.black) .font(.system(size: 28)) // Increased size .padding(.leading, 8) .onTapGesture { progress = 10 // Added to see progress } Spacer() Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress))) .foregroundColor(.black) .bold() .font(.system(size: 24)) // Increased size .padding(.trailing, 8) } .frame(width: UIScreen.main.bounds.width * 0.9, height: barHeight) // .zIndex(1) // Ensure the HStack is on top Spacer() // ADDED THIS } .padding(.horizontal) } } Is it what you are looking for ? If so, don't forget to close the thread by marking the answer as correct.
Topic: Programming Languages SubTopic: Swift Tags:
Aug ’24
Reply to App Rejected for Minimal Functionality
Sorry to say, but rejection here appears a very sound decision. Imagine the appStore populated with a lot of similar apps… what a frustration for users. Now, if you change your app to become really an educational app, showing examples of what could be a "complex" UI and a minimalist that perform the same task, that would provide some user value and may be pass the review. Good luck.
Aug ’24
Reply to Bug description: App forze on the splash screen
We don't know the tests that are done in review. So no way to reproduce, simulate or whatever. There is probably a problem in your code, you have to find where and what. What is the error report you get. Is is about a crash, a performance issue, a problem with your metadata… Without it, impossible to help. If I understand the thread title correctly(it would be better to detail in post), the app freezes on splash screen. Are you loading data from network during app launching ? Or anything else that can take a long time ?
Aug ’24
Reply to Attempting to add scrubbing to UISlider
OK, it's better. What is the problem, precisely ? What do you get ? What did you expect ? Please show screenshots. Here are my screenshots showing it is working, but thumb can move out of slider, which is probably not expected: You can force the thumb inside slider by making the following change: override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect { let thumbDiameter = CGFloat(defaultDiameter * value) let origin = CGPoint(x: (currentLocation?.x ?? bounds.width / 2) - thumbDiameter / 2, y: 0 /*(currentLocation?.y ?? thumbDiameter / 2) - thumbDiameter / 2*/) // <<-- CHANGED return CGRect(origin: origin, size: CGSize(width: thumbDiameter, height: thumbDiameter)) }
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to Attempting to add scrubbing to UISlider
Could you explain what you mean and expect exactly by 'scrubbing' ? This line does not compile (UIColor has no circle attribute) let thumbImage = UIColor.red.circle(CGSize(width: thumbDiameter, height: thumbDiameter)) Is there a line missing ? Or did you define an extension (if so, please provide it). I change the thumbImage to some systemImage. It compiles, but screen remains empty. So I added a background to SizeSlider and I get it on screen. But just a coloured rect, not a slider. Could you show what you get ? I completed code as follows, and now thumb (and slider) increase size. But thumb can get out of slider, is not saved at the end of school… Looks like there are missing parts in your code. extension UIImage { static func from(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1 return UIGraphicsImageRenderer(size: size, format: format).image { context in color.setFill() context.fill(CGRect(origin: .zero, size: size)) } } } class SizeSliderView: UISlider { private var previousLocation: CGPoint? private var currentLocation: CGPoint? private var translation: CGFloat = 0 private var scrubbingSpeed: CGFloat = 1 private var defaultDiameter: Float init(startValue: Float = 0, defaultDiameter: Float = 500) { self.defaultDiameter = defaultDiameter super.init(frame: .zero) value = clamp(value: startValue, min: minimumValue, max: maximumValue) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func draw(_ rect: CGRect) { super.draw(rect) clear() createThumbImageView() addTarget(self, action: #selector(valueChanged(_:)), for: .valueChanged) } // Clear elements private func clear() { tintColor = .clear maximumTrackTintColor = .clear backgroundColor = .clear thumbTintColor = .clear } // Call when value is changed @objc private func valueChanged(_ sender: SizeSliderView) { CATransaction.begin() CATransaction.setDisableActions(true) CATransaction.commit() createThumbImageView() } // Create thumb image with thumb diameter dependent on thumb value private func createThumbImageView() { let thumbDiameter = CGFloat(defaultDiameter * value) // let thumbImage = UIColor.red.circle(CGSize(width: thumbDiameter, height: thumbDiameter)) let thumbImage = UIImage.from(color: .blue, size: CGSize(width: thumbDiameter, height: thumbDiameter)) setThumbImage(thumbImage, for: .normal) setThumbImage(thumbImage, for: .highlighted) setThumbImage(thumbImage, for: .application) setThumbImage(thumbImage, for: .disabled) setThumbImage(thumbImage, for: .focused) setThumbImage(thumbImage, for: .reserved) setThumbImage(thumbImage, for: .selected) } // Return true so touches are tracked override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { let location = touch.location(in: self) // Ensure that start location is on thumb let thumbDiameter = CGFloat(defaultDiameter * value) print(location, bounds, thumbDiameter) if location.x < bounds.width / 2 - thumbDiameter / 2 || location.x > bounds.width / 2 + thumbDiameter / 2 || location.y < 0 || location.y > thumbDiameter { return false } previousLocation = location super.beginTracking(touch, with: event) return true } // Track based on moving slider override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { guard isTracking else { return false } guard let previousLocation = previousLocation else { return false } // Reference // location: location of touch relative to device // delta location: change in touch location WITH scrubbing // adjusted location: location of touch to slider bounds (WITH scrubbing) // translation: location of slider relative to device let location = touch.location(in: self) currentLocation = location scrubbingSpeed = getScrubbingSpeed(for: location.y - 50) let deltaLocation = (location.x - previousLocation.x) * scrubbingSpeed var adjustedLocation = deltaLocation + previousLocation.x - translation if adjustedLocation < 0 { translation += adjustedLocation adjustedLocation = deltaLocation + previousLocation.x - translation } else if adjustedLocation > bounds.width { translation += adjustedLocation - bounds.width adjustedLocation = deltaLocation + previousLocation.x - translation } self.previousLocation = CGPoint(x: deltaLocation + previousLocation.x, y: location.y) let newValue = Float(adjustedLocation / bounds.width) * (maximumValue - minimumValue) + minimumValue setValue(newValue, animated: false) sendActions(for: .valueChanged) return true } // Reset start and current location override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { self.currentLocation = nil self.translation = 0 super.touchesEnded(touches, with: event) } // Thumb location follows current location and resets in middle override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect { let thumbDiameter = CGFloat(defaultDiameter * value) let origin = CGPoint(x: (currentLocation?.x ?? bounds.width / 2) - thumbDiameter / 2, y: (currentLocation?.y ?? thumbDiameter / 2) - thumbDiameter / 2) return CGRect(origin: origin, size: CGSize(width: thumbDiameter, height: thumbDiameter)) } private func getScrubbingSpeed(for value: CGFloat) -> CGFloat { switch value { case 0: return 1 case 0...50: return 0.5 case 50...100: return 0.25 case 100...: return 0.1 default: return 1 } } private func clamp(value: Float, min: Float, max: Float) -> Float { if value < min { return min } else if value > max { return max } else { return value } } } //UIView representative: struct SizeSlider: UIViewRepresentable { private var startValue: Float private var defaultDiameter: Float init(startValue: Float, defaultDiameter: Float) { self.startValue = startValue self.defaultDiameter = defaultDiameter } func makeUIView(context: Context) -> SizeSliderView { let view = SizeSliderView(startValue: startValue, defaultDiameter: defaultDiameter) view.minimumValue = 0.1 view.maximumValue = 1 return view } func updateUIView(_ uiView: SizeSliderView, context: Context) { } } struct ContentView: View { var body: some View { SizeSlider(startValue: 0.20, defaultDiameter: 100) .frame(width: 400) .background(.red). // Just to see something .opacity(0.1) } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to Swiftui Table statement conditional table columns
You don't show the complete code, so harder to explain… But the way I would do it would be to have the condition in the dataSource through a computed var.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to SwiftUI List rows loaded all at once
Could you show the code where you build the List ?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to Will a Major Update from Flutter to SwiftUI Affect App Store Review Approval?
Will the review process reject the update due to the significant changes in the app? Not at all. Apps do evolve significantly in new releases, either functionally or technically. They don't mind as long that you comply with guidelines. You don't even have to mention the change from Flutter. In fact it would probably be seen as a positive move as more future proof and guaranteed multi platforms.
Replies
Boosts
Views
Activity
Aug ’24
Reply to SwiftUI gets stuck in a view update cycle when I pass down a Binding to a NavigationPath
You set .environmentObject(SomeEnvironmentObject()) in Preview. Do you do the same for the app where you call ContentView() ?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to Video PLayer - remove maximizer controller
Sorry not being able to help. But you'd better try to understand why it crashes. There may be a bug somewhere that will reappear sooner or later. You may also file a bug report in Feedback, in case.
Topic: Spatial Computing SubTopic: General Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to does simulator accurately reflect translucent UIs?
What simulator are you speaking about ? There is no simulator for Mac apps, it is directly the app running on the Mac. So, do you mean Preview ?
Replies
Boosts
Views
Activity
Aug ’24
Reply to Apple Intelligence- US Only
Some recent news for Apple Intelligence availability in Europe (in English only): https://www.macrumors.com/how-to/get-apple-intelligence-in-the-eu/
Replies
Boosts
Views
Activity
Aug ’24
Reply to Stack feature not working as per plan.
And now with progress bar overlaying: struct ContentView: View { let barHeight: CGFloat = 30 let barColor = Color.gray let duration: Double = 10 let icon = "globe" @State private var progress: CGFloat = 0 var body: some View { ZStack(alignment: .leading) { // VStack { // Background bar RoundedRectangle(cornerRadius: 10) // .fill(Color.gray.opacity(0.3)) // .frame(height: barHeight) // Set height to the specified barHeight // Progress bar // GeometryReader { geometry in RoundedRectangle(cornerRadius: 10) .fill(barColor.opacity(0.5)) // To see through .frame(width: CGFloat(progress) * UIScreen.main.bounds.width, height: barHeight) // .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight) .animation(.linear(duration: 10), value: progress) // } // .cornerRadius(10) // That's redundant // Icon and label HStack { Rectangle() // to avoid frame moving when animation starts) .fill(.clear) .frame(width: UIScreen.main.bounds.width * 0.05, height: barHeight) Image(systemName: icon) .foregroundColor(.black) .font(.system(size: 28)) // Increased size .padding(.leading, 8) .onTapGesture { progress = 1 // Added to see progress } Spacer() Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress))) .foregroundColor(.black) .bold() .font(.system(size: 24)) // Increased size .padding(.trailing, 8) } .frame(width: UIScreen.main.bounds.width/* * 0.9*/, height: barHeight) // Changed to avoid frame moving when animation starts .zIndex(1) // Ensure the HStack is on top Spacer() // ADDED THIS } .padding(.horizontal) } } We get this during progress: May be we could use overlay, but did not try.
Topic: Programming Languages SubTopic: Swift Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to Stack feature not working as per plan.
What is ProgressiveBar ? Is it RoundedRectangle(cornerRadius: 10) What do you mean by above or on top. Please show what you get and what you want. Why do you need geometry reader and not just set the zIndex of the progress bar ? I edited your code to guess and complete missing parts: struct ContentView: View { let barHeight: CGFloat = 30 let barColor = Color.gray let duration: Double = 10 let icon = "globe" @State private var progress = 0 var body: some View { ZStack(alignment: .leading) { // Background bar RoundedRectangle(cornerRadius: 10) // .fill(Color.gray.opacity(0.3)) // .frame(height: barHeight) // Set height to the specified barHeight // Progress bar GeometryReader { geometry in RoundedRectangle(cornerRadius: 10) .fill(barColor) .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight) .animation(.linear(duration: 10), value: progress) } .cornerRadius(10) // Icon and label HStack { Image(systemName: icon) .foregroundColor(.black) .font(.system(size: 28)) // Increased size .padding(.leading, 8) .onTapGesture { progress = 10 // Added to see progress } Spacer() Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress))) .foregroundColor(.black) .bold() .font(.system(size: 24)) // Increased size .padding(.trailing, 8) } .frame(width: UIScreen.main.bounds.width * 0.9, height: barHeight) .zIndex(1) // Ensure the HStack is on top } .padding(.horizontal) } } The progressBar is above: I changed ZStack to VStack and removing geometryReader and get this: struct ContentView: View { let barHeight: CGFloat = 30 let barColor = Color.gray let duration: Double = 10 let icon = "globe" @State private var progress = 0 var body: some View { // ZStack(alignment: .leading) { VStack { // Set height to the specified barHeight // Progress bar // GeometryReader { geometry in // REMOVED RoundedRectangle(cornerRadius: 10) .fill(barColor) .frame(width: CGFloat(progress) * UIScreen.main.bounds.width, height: barHeight) // WE CAN get screen width directly // .frame(width: CGFloat(progress) * geometry.size.width, height: barHeight) .animation(.linear(duration: 10), value: progress) // } .cornerRadius(10) // Icon and label HStack { Image(systemName: icon) .foregroundColor(.black) .font(.system(size: 28)) // Increased size .padding(.leading, 8) .onTapGesture { progress = 10 // Added to see progress } Spacer() Text(String/*timeString*/(format: "%.1f", /*from: */duration * Double(progress))) .foregroundColor(.black) .bold() .font(.system(size: 24)) // Increased size .padding(.trailing, 8) } .frame(width: UIScreen.main.bounds.width * 0.9, height: barHeight) // .zIndex(1) // Ensure the HStack is on top Spacer() // ADDED THIS } .padding(.horizontal) } } Is it what you are looking for ? If so, don't forget to close the thread by marking the answer as correct.
Topic: Programming Languages SubTopic: Swift Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to App Rejected for Minimal Functionality
Sorry to say, but rejection here appears a very sound decision. Imagine the appStore populated with a lot of similar apps… what a frustration for users. Now, if you change your app to become really an educational app, showing examples of what could be a "complex" UI and a minimalist that perform the same task, that would provide some user value and may be pass the review. Good luck.
Replies
Boosts
Views
Activity
Aug ’24
Reply to SwiftUI Hierarchical List Performance
I have no specific recommendation either, but found this thread which addresses some lists performance issues and proposes solutions: https://fatbobman.com/en/posts/optimize_the_response_efficiency_of_list/ I did not test, but hope that may help.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Aug ’24
Reply to Bug description: App forze on the splash screen
We don't know the tests that are done in review. So no way to reproduce, simulate or whatever. There is probably a problem in your code, you have to find where and what. What is the error report you get. Is is about a crash, a performance issue, a problem with your metadata… Without it, impossible to help. If I understand the thread title correctly(it would be better to detail in post), the app freezes on splash screen. Are you loading data from network during app launching ? Or anything else that can take a long time ?
Replies
Boosts
Views
Activity
Aug ’24
Reply to Sending '$0' risks causing data races
I cannot find this line of code in the referenced link… But it could have to deal with $0 not being sendable. Read here explanations in a different context: https://forums.swift.org/t/cannot-understand-the-nature-of-data-race-warnings-in-swift-5-10/70472
Topic: Media Technologies SubTopic: Video Tags:
Replies
Boosts
Views
Activity
Aug ’24