How to constantly make iPhone vibrate every time the timepicker wheel rolls - swiftui

I am new to SwiftUI programming, and I currently am working on a mock-up project where I want to create an iPhone timepicker simulator.
Part of the codes are shown below and the main part is inspired by the tutorial given by The Swift Academy (https://www.youtube.com/watch?v=AmEEjsXhKIg). What I am trying to do here is to have the iPhone repeatedly provide haptic feedback as long as the timepicker wheel is rolling. Ideally the haptic feedback is given at the same time when numbers are refreshed, but it only happens once when the wheel scrolling stops. Is there any solution to fix this? Any idea will be much appreciated :)
Here are some codes that I already wrote down.
import SwiftUI
import CoreHaptics
struct ContentView: View {
#State var hourSelection = 0
var hours = [Int](0..<24)
var body: some View {
Picker(selection: self.$hourSelection, label: Text("")) {
ForEach(0..<self.hours.count) {index in
Text("\(self.hours[index])h").tag(index)
prepareHaptics()
HapticEvent()
}
}.pickerStyle(WheelPickerStyle())
}
//make haptic engine ready
func prepareHaptics(){...}
//play haptic pattern
func HapticEvent(){...}
}

Related

How to prevent scrolling when interacting with a PKCanvasView in a Scroll view in SwiftUI?

I have a UIViewRepresentable that represents a PKCanvasView.
struct PKCanvasRepresentable : UIViewRepresentable
{
#Binding var canvas: PKCanvasView
func makeUIView(context: Context) -> PKCanvasView {
canvas.tool = PKInkingTool(.pen, color: .black, width: 2)
canvas.drawingPolicy = .anyInput
canvas.isOpaque = false
canvas.backgroundColor = .clear
return canvas
}
func updateUIView(_ uiView: PKCanvasView, context: Context) {}
}
I want to use it as part of a sheet, that contains other input components and must be vertically scrollable.
#State var canvas = PKCanvasView()
var body: some View {
NavigationView {
ScrollView {
VStack {
// ..various components..
PKCanvasRepresentable(canvas: $canvas)
}
}
}
}
The drawing does not work, because the drawing gesture gets canceled by the scroll gesture.
I would like the PKCanvasView related gestures having priority over the scroll view ones. How can i achieve this?
Example
The expected behaviour can be seen when - for example - a DatePicker in wheel style is in a ScrollView. The scroll view does not receive any gesture input when interacting with the DatePicker. I would like to have the same behaviour for a PKCanvasView.
Additional info
I tried to add various Gesture modifiers to the Representable which prevents the ScrollView from getting input events - but of course that also prevents the Canvas from getting user input.
I built a drawing component myself in the past which worked, because i had control over the Gestures that were added to make the component happen. But i would prefer to use PKCanvasView, which does everything i need already - except from the described issue.
I saw this question - but it has nothing to do with PKCanvasView and its solution does not help.
I tried ai based code generators - but i don't have any subscriptions so i'm limited in tries and length of the answer. I tried the following quote, which produced only invalid, tutorial level answers:
Write a SwitUI view that contains of a ScrollView which has a nested UIViewRepresentable of a PKCanvasView where the ScrollView does not receive any kind of user input, events or gestures while the user interacts with the PKCanvasView and tries to draw but functions normally whenever the user does not interact with the PKCanvasView

How to set the background of a SwiftUI accessoryCorner watch widget?

I want to setup a very simple accessoryCorner SwiftUI widget, but it displays ugly.
This is my code:
struct WidgetView: View {
#Environment(\.widgetFamily) var widgetFamily
var body: some View {
switch widgetFamily {
case .accessoryCorner:
Image(systemName: "cart")
.widgetLabel {
Text("Label")
}
default:
Text("?")
}
}
}
This yields the following watch face:
For some reason, the image (the cart) is displayed in white color on a nearly white background, i.e. it cannot be seen.
I tried various methods to set a better background, e.g. ZStack with AccessoryWidgetBackground(), background(Color.clear), etc., but none worked.
How to display the image without a background, like the day (DI) in the left upper corner?
I contacted Apple and got the following answer:
We have reviewed your request and have concluded that there is no
supported way to achieve the desired functionality given the currently
shipping system configurations.

SwiftUI controls don't respond to input (clicks) in Catalyst if revealed in ScrollView

I'm dealing with what I am nearly certain to be a SwiftUI/Catalyst bug and am looking for a solution to get around it.
In the following code, about 30% of the time (5/15 in my tests), once the controls are revealed, the Toggle elements do not respond to clicks (and thus do not turn on/off).
I'm testing on Xcode 12.3 on Big Sur 11.1, running this code in Catalyst. It does work as expected 100% of the time as far as I can tell on iOS 14.3.
struct ContentView: View {
var body: some View {
ScrollView {
Row()
Row()
}
.padding()
}
}
struct Row : View {
#State private var showControls = false
#State private var toggleOn = false
var body: some View {
VStack {
HStack {
Text("Top section")
Button("\(showControls ? "Hide" : "Show") controls") {
showControls.toggle()
}
}
.frame(height: 100)
if showControls {
HStack {
Toggle("Toggle", isOn: $toggleOn)
Toggle("Toggle", isOn: $toggleOn)
}
}
}
}
}
The problem seems to come from having the Rows embedded in the ScrollView. The problem disappears completely if the controls start in their visible state (ie showControls = true), and only happens when they get revealed (ie showControls.toggle()) after the app starts.
I've also noticed that while Toggle and Slider fail about 30% of the time, a plain Button seems to be responsive 100% of the time.
The view debugger doesn't show anything 'in front' of the views that would be intercepting clicks.
I've tried changing to a List, which solves the problem, but yields other unfortunate side effects in behavior that I'd like to avoid in my real non-trivial app.
Can anyone else think of a reliable solution to avoiding this?

SwiftUI KeyboardShortcut with Arrow Keys

I’m having trouble using an arrow key as a .keyboardShortcut in SwiftUI. Sample iOS app:
struct ContentView: View {
#State var time: Date = Date()
var body: some View {
VStack {
Button("Press Me") {
time = Date()
}
.keyboardShortcut(KeyEquivalent.rightArrow, modifiers: [])
Text("\(time)")
}
}
}
This puts up a button that, when pressed, changes the time displayed in the text. I should be able to use the right arrow key on the keyboard and get it to work as well, but it doesn’t. If I change the keyboardShortcut line to, say, this:
.keyboardShortcut(KeyEquivalent(“a”), modifiers: [])
everything works as expected. You can press the “a” key and the time changes. If you hold down the command key, you get the system-provided HUD that shows the “a" shortcut. Change it to .rightAarrow and it shows the HUD but there’s an enclosed “?” for the shortcut, and the shortcut doesn’t fire when the arrow key is pressed.
(I’m aware I could do this using UIKit. Trying to understand why the SwiftUI version doesn’t work.)
I am attempting to accomplish the same objective in my MacOS SwiftUI app. Using your code as an example, I inserted the .keyboardShortcut(KeyEquivalent.rightArrow, modifiers: []) after my Button{} and it works fine. I then pasted your entire code into my ContentView and again it works fine. I do not know why it works in my MacOS app but not in your iOS app.
Copying my answer from this post. I wasn't able to use SwiftUI's commands to get this to work on iOS/iPadOS. However I found some luck using view controllers, and if you're using SwiftUI views then this will work with a hosting controller.
In your view controller, add the code below. The important bit is setting wantsPriorityOverSystemBehavior to true:
override var keyCommands: [UIKeyCommand]? {
let upArrow = UIKeyCommand(input: UIKeyCommand.inputUpArrow, modifierFlags: [], action: #selector(test))
upArrow.wantsPriorityOverSystemBehavior = true
return [upArrow]
}
#objc func test(_ sender: UIKeyCommand) {
print(">>> test was pressed")
}

SwiftUI achieve Master and Detail structure in tvOS

The way to achieve Master and Detail structure, as of beta 4, it should be by using .navigationViewStyle(.doubleColumn). Works perfectly on iOS / iPadOS / macOS but not in tvOS... it's a bug or I'm missing something?
import SwiftUI
struct ContentView: View {
var arra = ["Margherita","Marinara","Calzone"]
var body: some View {
NavigationView {
List(arra, id: \.self) { pizza in
NavigationLink(destination: SecondView(pizza: pizza)) {
Text(pizza)
}
}.navigationBarTitle("MASTER")
SecondView(pizza: arra[0])
}
.navigationViewStyle(.doubleColumn)
}
}
struct SecondView: View {
var pizza : String
var body: some View {
Text(pizza)
.navigationBarTitle("DETAIL")
}
}
(as of GM release) The official doc tells something like: double column style will be stacked on tvOS, like it's an iPhone in portrait mode. So it's impossible to automatically achieve the "master and detail" look like it's an iPad in landscape, you have to build it for yourself. Even if you use one UISplitViewController in UIKit! With this behavior I think it's good to go only if the master it's a fullscreen CollectionView, sorta like Netflix App.