I'm getting an error when trying to do the animation:
SuccessNotificationView()
.offset(y: self.showSuccessSave ? -UIScreen.main.bounds.height/3 : -UIScreen.main.bounds.height)
.animation(.interactiveSpring(mass: 1.0, stiffness: 100.0, damping: 10, initialVelocity: 0))
where SuccessNotificationView() is:
struct SuccessNotificationView: View {
var body: some View {
Text("Success")
.padding()
.foregroundColor(Color.white)
.frame(width: UIScreen.main.bounds.width, height: 100)
.background(Color.green)
.cornerRadius(20)
}
}
The error I'm getting is: Extra arguments at positions #1, #2, #3, #4 in call
How can I fix that?
You need to pass in the the proper parameters to interactiveSpring().
.animation(
.interactiveSpring(
response: Double,
dampingFraction: Double,
blendDuration: Double
)
)
There are only two method calls for interactiveSpring(). One is with no parameters and the second is the example shown above.
I believe that you are trying to use interpolatingSpring(). In that case, use the following code snippet:
.animation(
.interpolatingSpring(
mass: 1,
stiffness: 100.0,
damping: 10,
initialVelocity: 0
)
)
Related
I'm creating a chart in SwiftUI. It's weather related and I have the data successfully displaying. Now, I'm attempting to display the temperature on each symbol in the chart, but it only displays on the first symbol.
Here's what I've done:
Chart {
ForEach(temperatures, id: \.tempType) { series in
ForEach(series.data) { element in
LineMark(x: .value("Day", element.day), y: .value("Temps", element.temp))
.interpolationMethod(.catmullRom)
.foregroundStyle(by: .value("TemperatureType", series.tempType))
.symbol {
Circle()
.fill(.yellow)
.frame(width: 10)
.shadow(radius: 2)
}
.lineStyle(.init(lineWidth: 5))
} // end for each
} // end for each
}
This works. Then, I attempt to add text using this modifier on the LineMark:
.annotation(position: .overlay, alignment: .bottom) {
let text = "\(element.temp)"
Text(text)
}
It only displays the text on the first symbol's data point:
Since the annotation modifier is within the ForEach loop, I thought it would display the temperature at each data point, but it doesn't. What's the best way to have the temperature displayed at each symbol instead of only the first?
The short answer is that the .annotation refers to the type of "Mark" that you attach it to - and you are attaching it to a LineMark, so it is the entire line you are "annotating", not the individual points.
Had you used BarMarks or PointMarks, the annotation will attach to the individual bar or point. So try this instead:
Chart {
ForEach(Array(zip(numbers, numbers.indices)), id: \.0) { number, index in
LineMark(
x: .value("Index", index),
y: .value("Value", number)
)
.lineStyle(.init(lineWidth: 5))
PointMark(
x: .value("Index", index),
y: .value("Value", number)
)
.annotation(position: .overlay,
alignment: .bottom,
spacing: 10) {
Text("\(number)")
.font(.largeTitle)
}
}
}
To make it compatible with your nice symbols, we need to add a couple of extra steps:
Chart {
ForEach(Array(zip(numbers, numbers.indices)), id: \.0) { number, index in
LineMark(
x: .value("Index", index),
y: .value("Value", number)
)
.interpolationMethod(.catmullRom)
.lineStyle(.init(lineWidth: 5))
.symbol {
// This still needs to be associated
// with the LineMark
Circle()
.fill(.yellow)
.frame(width: 10)
.shadow(radius: 2)
}
PointMark(
x: .value("Index", index),
y: .value("Value", number)
)
// We need .opacity(0) or it will
// overlay your `.symbol`
.opacity(0)
.annotation(position: .overlay,
alignment: .bottom,
spacing: 10) {
Text("\(number)")
.font(.largeTitle)
}
}
}
I'm trying to create a Range chart that looks like a native iOS heart rate chart but with some additional lines on it. . I found the example here https://github.com/jordibruin/Swift-Charts-Examples
I tried to modify my chart by adding a GeometryReader from another chart. FindElement works fine but nothing happens after. So maybe you know a fast answer what should I fix or add to show that line? Or maybe can take a piece of advice on how to get it done using another solution.
private var chart: some View {
Chart(data, id: \.weekday) { dataPoint in
Plot {
BarMark(
x: .value("Day", dataPoint.weekday, unit: .day),
yStart: .value("BPM Min", dataPoint.dailyMin),
yEnd: .value("BPM Max", dataPoint.dailyMax),
width: .fixed(isOverview ? 8 : barWidth)
)
.clipShape(Capsule())
.foregroundStyle(chartColor.gradient)
}
.accessibilityLabel(dataPoint.weekday.weekdayString)
.accessibilityValue("\(dataPoint.dailyMin) to \(dataPoint.dailyMax) BPM")
.accessibilityHidden(isOverview)
}
.chartOverlay { proxy in
GeometryReader { geo in
Rectangle().fill(.clear).contentShape(Rectangle())
.gesture(
SpatialTapGesture()
.onEnded { value in
let element = findElement(location: value.location, proxy: proxy, geometry: geo)
if selectedElement?.weekday == element?.weekday {
// If tapping the same element, clear the selection.
selectedElement = nil
} else {
selectedElement = element
}
}
.exclusively(
before: DragGesture()
.onChanged { value in
selectedElement = findElement(
location: value.location,
proxy: proxy,
geometry: geo
)
}
)
)
}
}
.chartXAxis {
AxisMarks(values: .stride(by: ChartStrideBy.day.time)) { _ in
AxisTick().foregroundStyle(.white)
}
}
.accessibilityChartDescriptor(self)
.chartYAxis(.visible)
.chartXAxis(.visible)
.frame(height: isOverview ? Constants.previewChartHeight : Constants.detailChartHeight)
}
Just found that a better solution will be adding another MarkBar with different color and width at the last element to create that vertical line. Also to create that dashed line with annotation it's better to use RuleMark.
So the final code will look like that(data is var data = HeartRateData.lastWeek, you can get it from Apple charts examples code):
private var chart: some View {
Chart(data, id: \.day) { dataPoint in
Plot {
BarMark(
x: .value("Day", dataPoint.day, unit: .day),
yStart: .value("BPM Min", dataPoint.dailyMin),
yEnd: .value("BPM Max", dataPoint.dailyMax),
width: .fixed(6)
)
.clipShape(Capsule())
.foregroundStyle(chartColor.gradient)
}
.accessibilityLabel(dataPoint.day.weekdayString)
.accessibilityValue("\(dataPoint.dailyMin) to \(dataPoint.dailyMax) BPM")
RuleMark(y: .value("min", 50))
.foregroundStyle(.gray)
.lineStyle(StrokeStyle(lineWidth: 1, dash: [5]))
.annotation(position: .trailing, alignment: .leading) {
Text("50")
.foregroundStyle(.gray)
.offset(x: 10, y: 0)
}
RuleMark(y: .value("max", 90))
.foregroundStyle(.gray)
.lineStyle(StrokeStyle(lineWidth: 1, dash: [5]))
.annotation(position: .trailing, alignment: .leading) {
Text("90")
.foregroundStyle(.gray)
.offset(x: 10, y: 0)
}
BarMark(
x: .value("Day", data.last!.day, unit: .day),
yStart: .value("BPM Min", 40),
yEnd: .value("BPM Max", 100),
width: .fixed(2)
)
.clipShape(Capsule())
.foregroundStyle(.white)
}
.accessibilityChartDescriptor(self)
.chartYAxis(.hidden)
.chartXAxis(.hidden)
.frame(height: 64)
}
This question already has answers here:
How to print() to Xcode console in SwiftUI?
(15 answers)
Closed 5 months ago.
var body: some View {
ScrollView(.horizontal,showsIndicators: false){
GeometryReader{
ViewGeoIndex in
And I get the Error called "Type '()' cannot conform to 'View'" in the following print statement.
I guess maybe there should not be any statements except for the views and stacks(something to be shown on the view)
If so, then where should I put my debug statements like print.
print("The centerX of the screen is \(ViewGeoIndex.frame(in:.global).midX)")
HStack(alignment:.center,spacing:0){
ForEach(CardName.allCases,id:\.self){
option in
// Circle().frame(width:10,height: 30)
GeometryReader{
BarGeoIndex in
Button {
activeCard=option.title
print("Success")
} label:{
ZStack{
Circle().frame(width: 60, height:60, alignment: .center)
.foregroundColor(.white)
.shadow(color: .gray, radius: 0.5, x: 0.5, y: 0.5)
Text(option.image)
}//content of the button
.frame(width:100)
}
var BarMidX = BarGeoIndex.frame(in: .global).midX
Here occurs the same problem like the last one.
if (BarMidX == ViewGeoIndex.frame(in: .global).midX)
{
print("Success")
}
```
}.frame(width:100)
}
}//HStack
.padding([.horizontal],0)
}
// Text("\(index.frame(in: CoordinateSpace.global).midX)")
}//ScrollView
.padding([.horizontal],0)
}
I have been stuck here for 1 hour. Realllly appreciate if you help me out.
The closure you are in expects to return only Views. But print does not.
You can use the print this way:
let _ = print(...
Goal:
I am currently working on some code to create a grid of hexagons, each one individually coloured with a gradient. However I am quite new to swiftUI and don't fully understand why my code doesn't work.
Code:
ForEach(0 ..< 11, id: \.self) { Xnum in
ForEach(0 ..< 11, id: \.self) { Ynum in
self.MyNewPath(in: CGRect(), Xcoord: Double(Xnum), Ycoord: Double(Ynum), Type: 1)
.fill(RadialGradient(
gradient: Gradient(colors: [Color.red, Color.blue]),
center: .init(
x: self.gradientParametersX(Xpos: Double(Xnum)),
y: self.gradientParametersY(Ypos: Double(Ynum), Xpos: Double(Xnum))),
startRadius: CGFloat(2.0),
endRadius: CGFloat(70.0)))
.gesture(
TapGesture().onEnded {_ in
self.dataEditor(Xplace: Int(Xnum), Yplace: Int(Ynum))
}
)
}
}
Return Types:
MyNewPath() - Path (of a hexagon)
gradientParametersY() - CGFloat
gradientParametersY() - CGFloat
Error:
The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
The error appears to be centred around the passing of Xnum and Ynum to functions gradientParametersX() and gradientParametersY().
When I pass 7.0 and 0.0 for example:
x: self.gradientParametersX(Xpos: Double(7.0)),
y: self.gradientParametersY(Ypos: Double(0.0), Xpos: Double(7.0))),
...there is no error.
Try to separate grid item creation in separate function as below (the code snapshot is not testable, so just scratchy to demo idea)
...
ForEach(0 ..< 11, id: \.self) { Xnum in
ForEach(0 ..< 11, id: \.self) { Ynum in
self.createItem(for: Xnum, Ynum: Ynum)
}
}
...
private func createItem(for Xnum: Int, Ynum: Int) -> some View {
self.MyNewPath(in: CGRect(), Xcoord: Double(Xnum), Ycoord: Double(Ynum), Type: 1)
.fill(RadialGradient(
gradient: Gradient(colors: [Color.red, Color.blue]),
center: .init(
x: self.gradientParametersX(Xpos: Double(Xnum)),
y: self.gradientParametersY(Ypos: Double(Ynum), Xpos: Double(Xnum))),
startRadius: CGFloat(2.0),
endRadius: CGFloat(70.0)))
.gesture(
TapGesture().onEnded {_ in
self.dataEditor(Xplace: Int(Xnum), Yplace: Int(Ynum))
}
)
}
EDIT : Does your answer concerns SwiftUI and not just Swift ? If yes, please edit your question, and see user3441734 comment under it.
The compilator seems to have troubles deducing the types of Xnum and Ynum.
You might have to explicitly write their type.
Your ForEach syntax seems quite weird, have you tried
for Xnum:Int in 0..<11
{
for Ynum:Int in 0..<11
{
}
}
And then casting Xnum and Ynum to Double ?
You can also directly do a foreach on doubles this way :
for Xnum:Double in stride(from: 0, through: 10, by: 1.0)
{
for Ynum:Double in stride(from: 0, through: 10, by: 1.0)
{
}
}
I have a little problem on the lastest SwiftUI, the error is "The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions"
My code is like that :
let cards = ["Azertyuiop", "Bzertyuiop", "Czertyuiop", "Dzertyuiop", "Ezertyuiop", "Fzertyuiop", "Gzertyuiop", "Hzertyuiop", "Izertyuiop", "Jzertyuiop", "Kzertyuiop", "Lzertyuiop", "Bzertyuiop", "Czertyuiop", "Dzertyuiop", "Ezertyuiop", "Fzertyuiop", "Gzertyuiop", "Lzertyuiop", "Bzertyuiop", "Czertyuiop", "Dzertyuiop", "Ezertyuiop", "Fzertyuiop", "Gzertyuiop", "Lzertyuiop", "Bzertyuiop", "Czertyuiop", "Dzertyuiop", "Ezertyuiop", "Fzertyuiop", "Gzertyuiop"]
var body: some View {
ScrollView{
VStack (spacing: 0, content: {
ForEach(0..<cards.count/3) { row in // create number of rows
HStack (spacing: 0, content: {
ForEach(0..<3) { column in // create 3 columns
ZStack(alignment: .bottomLeading){
Image("ghost").resizable().aspectRatio(contentMode: .fill)
.overlay(Rectangle().fill (LinearGradient(gradient: Gradient(colors: [.clear, .black]),startPoint: .center, endPoint: .bottom)).clipped())
Text(self.cards[row * 3 + column]) // this cause the error
.fontWeight(.semibold)
}
}
})
}
})
}
}
I guess that the error comes from : row * 3 + column
So I tried to put the integer 1 instead of this calculation, and it worked.
How to do this calculation in my body and my View? because SwiftUI does not allow me and shows me "Expected pattern"
Thanks a lot !
There are two problems. One is using ZStack with overlay, the other is Linear Gradient is a view and you can use it directly.
ZStack(alignment: .bottomLeading){
Image("ghost").resizable().aspectRatio(contentMode: .fill)
LinearGradient(gradient: Gradient(colors: [.clear, .black]),startPoint: .center, endPoint: .bottom).clipped()
Text(self.cards[row * 3 + column]) // this cause the error
.fontWeight(.semibold)
}