@sha921 @thibautrichez Thank you for your responses. I get the following errors with the code below:
Button {
login()
} label: {
ZStack {
RoundedRectangle(cornerRadius: 5)
.fill(Color.black)
.frame(width: UIScreen.main.bounds.width - 50, height: 50)
Text("Sign in")
.foregroundColor(.white)
}
}
func login() {
print("test")
}
Incorrect argument label in call (have '_: label:', expected 'value:selected:')
Trailing closure passed to parameter of type 'String' that does not accept a closure
Thank you again for the help so far.
Post
Replies
Boosts
Views
Activity
I have two follow up questions. Any help would be greatly appreciated.
How can I implement a scroll feature with the Canvas so that the Canvas itself would be larger than the screen?
How can I draw on the canvas upon loading the canvas? For example, if I pass data stored as a Line variable to the view that the Canvas is on, how can I draw onto the canvas upon loading based off of that data?
Thank you.
@Claude31 Thank you for your response. Below is revised code, with the ScrollView implemented, so the drawing aspect isn't going to work unless that's removed. I put a comment in .onAppear { } where I'm assuming code needs to be written to plot the points from lines onto the canvas. I looked at the official documentation for canvas' that draws upon loading but I can't seem to figure out how to apply it to what I'm doing.
import SwiftUI
struct LineData {
var points: [CGPoint]
var color: Color
}
struct CanvasExample: View {
@State var lines: [LineData] = []
@State var selectedColor: Color = Color.black
var body: some View {
ScrollView (showsIndicators: false) {
VStack {
Canvas { ctx, size in
for line in lines {
var path = Path()
path.addLines(line.points)
ctx.stroke(path, with: .color(line.color), style: StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round))
}
}.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged({ value in
let position = value.location
if value.translation == .zero {
lines.append(LineData(points: [position], color: selectedColor))
} else {
guard let lastIndex = lines.indices.last else {
return
}
lines[lastIndex].points.append(position)
}
})
)
.onAppear {
// code that takes data passed to variable lines and draws on canvas
}
}
}
}
}
#Preview {
CanvasExample()
}
Thank you.
One thing I have noticed is the Canvas code doesn't run until there's a gesture, and I'm not sure why that is because the documentation has an example that displays a drawing upon loading the Canvas.
struct Line {
var points: [CGPoint]
var color: Color
}
var body: some View {
@State var lines: [Line] = []
Canvas { ctx, size in
for line in lines {
let color = line.colorName == nil ? getColor(colorName: nil, rgb: line.rgb) : getColor(colorName: line.colorName, rgb: nil)
var path = Path()
print(line.points) // this is how I noticed this code doesn't run until the gesture runs. This print statement doesn't run upon loading the Canvas
path.addLines(line.points)
ctx.stroke(path, with: .color(color), style: StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round))
}
}
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged({ value in
draw(position: value.location, translation: value.translation)
}
})
)
.onAppear {
lines = parseLinesString()
for line in lines {
for point in line.points {
draw(position: point, translation: nil)
}
}
}
func draw(position: CGPoint, translation: CGSize?) {
if translation == .zero || translation == nil {
lines.append(Line(points: [position], color: color.black))
} else {
guard let lastIndex = lines.indices.last else {
return
}
lines[lastIndex].points.append(position)
unsaved = true
}
}
}
As I mentioned previously, I'm not sure how to translate the documentation example to my application. If anyone could point me in the right direction that would be greatly appreciated. Thank you.
One thing I now realize is that it's not practical to have a Canvas inside a ScrollView because it interferes with the drawing gesture. However, I'm still unsure of how to draw on a Canvas upon loading.
Hi,
Thank you for your response. Here is the whole function:
func createAccount(account: AccountCreationData, completion: @escaping (Response) -> Void) {
guard let url = URL(string: "http://localhost:4300/account/create-account") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
print(account)
guard let encoded = try? JSONEncoder().encode(account) else {
print("Failed to encode request")
return
}
print(encoded)
request.httpBody = encoded
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else { return }
do {
let resData = try JSONDecoder().decode(Response.self, from: data)
DispatchQueue.main.async {
completion(resData)
}
} catch let jsonError as NSError {
print("JSON decode failed: \(jsonError)")
}
}.resume()
}
Below are print statements of account and encoded:
AccountCreationData(name: "name", email: "email", phone: "phone", password: "password")
110 bytes
Hi,
Thank you for all the help. There was a discrepancy in the bytes because I removed a field from the data set. I was missing the Content-Type: application/json header which caused the issue.
Hi,
I have a follow up question. In an older project, using that code, I get an error: 'onChange(of:initial:_:)' is only available in iOS 17.0 or newer
The solution provided is to wrap the code in if #available(iOS 17.0, *) { }, but I'm only able to wrap the whole view inside of it, like so:
if #available(iOS 17.0, *) {
VStack () {
// view with .onChange
}
} else {
VStack () {
// view with older solution
}
}
The view is quite lengthy so it would be very redundant to have the same view twice, (the same view for each component of the if/else statement). Is there a way to implement an if statement so that I would only need the code for the view once (something like the code below)?
VStack {
}
if #available(iOS 17.0, *) {
.onChange() {
}
} else {
// older solution
}
With this code I get the error:
.onChange(of: buttonState) { oldState, newState in
}
But not with this:
.onChange(of: buttonState) { state in
}
Would it be recommended to use a slightly older target so that more users would be able to access the app?
Hi,
Just bumping this to see if anyone knows why I'm getting these errors. Please let me know if anymore information is needed.
Hi,
Thank you for your response. Using Xcode 15.4, how can I create a git repository for an already existing project? The Source Control tab is blank and I don't see a button to create a repository.
Hi,
Thanks for your response, however I'm not sure where that file would be located. I don't see a database file in my file directory. All I have is the file with the model class.
Thank you for your response. Both branches are completely empty aside from the auto-generated code that new projects have.
Regardless of whether I'm in main or the new branch, the only files are the template files that are generated when creating a new project.
There are two files under "Changes": (Project Name)-Info and build.