Reputation: 453
I'm struggling to output a random String inside the View.
Due to the error:
Type '()' cannot conform to 'View
I've learned that View isn't the appropriate place to write down the functions itself.
What should I do to output itemX.randomElement()
and itemY.randomElement()
?
struct SummaryView: View {
var avgValue = 1.5
var roundedKarvonenValue: Double
var itemX = ["A", "B", "C", "D", "E", "F", "G", "H"]
var itemY = ["I", "J", "K", "L", "M", "N", "O", "P"]
var body: some View {
ScrollView {
VStack(alignment: .leading) {
if workoutManager.averageHeartRate < roundedKarvonenValue {
print(itemX.randomElement()!)
} else {
print(itemY.randomElement()!)
}
}
}
}
}
Upvotes: 33
Views: 56306
Reputation: 915
For every one else facing this error you can not run code inside the views body.
either use the the let _ = func() approach
or
we can run code in side such event ie
.onTapGesture { self.func() }
.onDisappear{ self.func() }
.onAppear{ self.func() }
for reference visit this Link
Upvotes: 9
Reputation: 81
Another reason could be you are attempting to iterate over a collection in a functional nature.
Run into this sometimes when I switch between UIKit and SwiftUI and forget :)
Example:
Using collection.forEach { item in
in a view/stack
Upvotes: 1
Reputation: 9725
There is a great deal to unpack in this question, but we will start with the simple first. Views
are for displaying something on screen. Nothing more. The reason you are having issues with the print()
statements is that they are for printing to the console, not the screen. Therefore, the compiler gives you an error. To fix this, use Text
like @JoakimDanielson said:
struct SummaryView: View {
var workoutManager: WorkoutManager //This var must be declared
var avgValue = 1.5
var roundedKarvonenValue: Double
var itemX = ["A", "B", "C", "D", "E", "F", "G", "H"]
var itemY = ["I", "J", "K", "L", "M", "N", "O", "P"]
var body: some View {
ScrollView {
VStack(alignment: .leading) {
if workoutManager.averageHeartRate < roundedKarvonenValue{
Text(itemX[0])
} else {
Text(itemY[0])
}
}
}
}
}
As to your second part as to where to place your functions, is not as clear cut. You should look up MVVM architecture to gain an understanding of the standard way to structure your app in SwiftUI. Right now, you are simply displaying data from HealthKit
using Apple's WWDC class WorkoutManager
(I presume).
At the very basic level, if your function has to do with changing how the data is displayed, it stays in the View
. If the function fundamentally changes something about your Model
or is needed by multiple views, it should go into the Model
. That is a judgment call.
So, for your code, you are showing a random element from a variable declared in a view. That is all local stuff, so the function stays in the view. Adding the func randomElement()
and cleaning your code up a bit more leaves you with this:
struct SummaryView: View {
// If you are not changing the variables, declare them as constants. This uses less memory.
let workoutManager: WorkoutManager
let avgValue = 1.5
let roundedKarvonenValue: Double
let itemX = ["A", "B", "C", "D", "E", "F", "G", "H"]
let itemY = ["I", "J", "K", "L", "M", "N", "O", "P"]
var body: some View {
ScrollView {
VStack(alignment: .leading) {
// I turned your if statement into a Terniary Conditional Operator to shrink the amount of code.
Text(workoutManager.averageHeartRate < roundedKarvonenValue ? randomElement(itemX) : randomElement(itemY))
}
}
}
func randomElement(_ stringArray: [String]) -> String {
let end = stringArray.count - 1
let index = Int.random(in: 0...end)
return stringArray[index]
}
}
Upvotes: 18
Reputation: 1125
You can use print statements inside views like this:
VStack(alignment: .leading) {
if workoutManager.averageHeartRate < roundedKarvonenValue {
let _ = print(itemX.randomElement()!)
} else {
let _ = print(itemY.randomElement()!)
}
}
Upvotes: 41