I am building an app using swift that is based around the idea of streaks. You open the app, log in, and the server sends back your information based on your login. I have a function, called
resetStreak that sends a POST request to the server giving it the username (thats how i manage each users information- based on their username) and telling the server to update their information, setting their streak to 0. Here is the code:
func resetStreak(){
print("Started resetSTREAK!!")
let url = URL(string: "http://127.0.0.1:5000/resetstreak/")!
var request = URLRequest(url: url)
let jsonData = "\"\(username)\""
print(jsonData)
request.httpMethod = "POST"
//request.httpBody = thetask.data(using: .utf8)
request.setValue("\(String(describing: jsonData.count))", forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let thenewtask = jsonData.data(using: .utf8) //string into data format
request.httpBody = thenewtask
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Request error: ", error)
return
}
guard let response = response as? HTTPURLResponse else { return }
if response.statusCode == 200 {
guard let data = data else { return }
DispatchQueue.main.async {
do {
let decodedTasks = try JSONDecoder().decode([String].self, from: data)
self.LoginResponse = decodedTasks
print("Decoded Tasks: \(decodedTasks)")
print("Login Response: \(LoginResponse)")
} catch let error {
print("Error decoding: ", error)
}
}
}
}
task.resume()
}
I have almost identical code like this, sending other POST request with different information which is why I know it shouldn't be erroring. however, I NEVER CALL THIS FUNCTION. and yet, I keep getting this error on my server:

As for the code on the server, it shouldn't matter as it receieves a GET request every minute. This is the code it has:
@app.route("/resetstreak/", methods = ['POST'])
def reset_streak():
print("RESETTING STREAK")
username = request.json # username
I do, however, have something added that is probably the cause of the issue. Since I would like to reset the user's streak after two days, I need to check if it has been 2 days since their last completed task! I implemented a timer that updates every minute, and does something. This is the code:
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack{
HStack{
Text("\(getStreak())")
.font(.largeTitle)
.onReceive(timer) { time in //updates every minute
print("TIMER ACTIVATED")
let dayDistance = compareCompletedTasks()
let theStreak = getStreak()
if dayDistance == 2 && theStreak != "loading..." && Int(theStreak)! > 0{ //they missed a day (reset streak)
//resetStreak()
print("reset streak")
}
}
please note that I changed the timer to 1 second, still the error occurs every minute. it never prints "reset streak" either which is super odd. PLEASE HELP! I will put the whole file of code if needed, because I am not good at asking questions.
import SwiftUI
import Foundation
extension Date {
func get(_ components: Calendar.Component..., calendar: Calendar = Calendar.current) -> DateComponents {
return calendar.dateComponents(Set(components), from: self)
}
func get(_ component: Calendar.Component, calendar: Calendar = Calendar.current) -> Int {
return calendar.component(component, from: self)
}
}
struct HomeScreen: View {
@Binding var username: String
@Binding var LoginResponse: [String]
@Binding var lastCompleted: String
@State var lastCompletedList: [String] = []
@State var currentDate = Date()
@State var tasks: [String] = []
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
let date = Date()
let df = DateFormatter()
func daysBetweenDates(year1: Int, month1: Int, day1: Int, year2: Int, month2: Int, day2: Int) -> Int {
let calendar = Calendar.current
let startDateComponents = DateComponents(year: year1, month: month1, day: day1)
let endDateComponents = DateComponents(year: year2, month: month2, day: day2)
guard let startDate = calendar.date(from: startDateComponents),
let endDate = calendar.date(from: endDateComponents) else {
return 0
}
let components = calendar.dateComponents([.day], from: startDate, to: endDate)
return abs(components.day ?? 0)
}
func getTaskNumber() -> Int { //number will always go up
let currentDate = Date()
let calendar = Calendar.current
let currentDateComponents = calendar.dateComponents([.year, .month, .day], from: currentDate)
return daysBetweenDates(
year1: 2023,
month1: 8,
day1: 3,
year2: currentDateComponents.year ?? 0,
month2: currentDateComponents.month ?? 0,
day2: currentDateComponents.day ?? 0
)
}
func getCurDate() -> String {
let currentDate = Date()
let calendar = Calendar.current
let currentDateComponents = calendar.dateComponents([.year, .month, .day], from: currentDate)
if let year = currentDateComponents.year, let month = currentDateComponents.month, let day = currentDateComponents.day {
return "\(year) \(month) \(day)"
} else {
return "Date components not available"
}
} //returns a string of the date with each number seperated by a space
func compareCompletedTasks() -> UInt{ //returns
let lastCompletedDate = lastCompleted.components(separatedBy: " ") //split it into a list
let curDate = getCurDate().components(separatedBy: " ")
let dayDiff = daysBetweenDates(year1: Int(lastCompletedDate[0])!, month1: Int(lastCompletedDate[1])!, day1: Int(lastCompletedDate[2])!, year2: Int(curDate[0])!, month2: Int(curDate[1])!, day2: Int(curDate[2])!) //equal to the number of days from the last time they did a task, and today
//if its still the same day
if dayDiff == 0{
return 0
}
//if its been 1 day
if dayDiff == 1{
return 1
}
//if its been 2 or more days
return 2
}
func completeTask(){
let url = URL(string: "http://127.0.0.1:5000/addtostreak/")!
var request = URLRequest(url: url)
//let jsonData = try? JSONSerialization.data(withJSONObject:thetask)
let jsonData = "\"\(username),\(getCurDate())\""
print(jsonData)
request.httpMethod = "POST"
//request.httpBody = thetask.data(using: .utf8)
request.setValue("\(String(describing: jsonData.count))", forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let thenewtask = jsonData.data(using: .utf8) //string into data format
request.httpBody = thenewtask
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Request error: ", error)
return
}
guard let response = response as? HTTPURLResponse else { return }
if response.statusCode == 200 {
guard let data = data else { return }
DispatchQueue.main.async {
do {
let decodedTasks = try JSONDecoder().decode([String].self, from: data)
self.LoginResponse = decodedTasks
print("Decoded Tasks: \(decodedTasks)")
print("Login Response: \(LoginResponse)")
lastCompletedList = LoginResponse[2].components(separatedBy: " ")
lastCompleted = "\(lastCompletedList[0]) \(lastCompletedList[1]) \(lastCompletedList[2])"
} catch let error {
print("Error decoding: ", error)
}
}
}
}
task.resume()
}
func getTasks() { // make the http request
guard let url = URL(string: "http://127.0.0.1:5000/tasks/") else { fatalError("Missing URL") }
let urlRequest = URLRequest(url: url)
let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if let error = error {
print("Request error: ", error)
return
}
guard let response = response as? HTTPURLResponse else { return }
if response.statusCode == 200 {
guard let data = data else { return }
DispatchQueue.main.async {
do {
let decodedTasks = try JSONDecoder().decode([String].self, from: data)
self.tasks = decodedTasks
} catch let error {
print("Error decoding: ", error)
}
}
}
}
dataTask.resume()
}
func resetStreak(){
print("Started resetSTREAK!!")
let url = URL(string: "http://127.0.0.1:5000/resetstreak/")!
var request = URLRequest(url: url)
let jsonData = "\"\(username)\""
print(jsonData)
request.httpMethod = "POST"
//request.httpBody = thetask.data(using: .utf8)
request.setValue("\(String(describing: jsonData.count))", forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let thenewtask = jsonData.data(using: .utf8) //string into data format
request.httpBody = thenewtask
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Request error: ", error)
return
}
guard let response = response as? HTTPURLResponse else { return }
if response.statusCode == 200 {
guard let data = data else { return }
DispatchQueue.main.async {
do {
let decodedTasks = try JSONDecoder().decode([String].self, from: data)
self.LoginResponse = decodedTasks
print("Decoded Tasks: \(decodedTasks)")
print("Login Response: \(LoginResponse)")
} catch let error {
print("Error decoding: ", error)
}
}
}
}
task.resume()
}
func getTask(year: Int, month: Int, day: Int) -> String{
if tasks.count == 0{
return "loading..."
}
return tasks[getTaskNumber() % tasks.count]
}
func getStreak() -> String{
if LoginResponse.count < 2{
return "loading..."
}
return LoginResponse[1]
}
func flameColor() -> Color{
if isComplete(){ // if they did their task for today
return Color.red
}
return Color.gray //they didnt do their task today
}
func buttonColor() -> Color{
if isComplete(){ // if they did their task for today
return Color.gray
}
return Color.red //they didnt do their task today
}
func getTime() -> String{
df.dateStyle = DateFormatter.Style.none
df.timeStyle = DateFormatter.Style.short
return df.string(from: currentDate)
}
func getTheTime(from date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm:ss"
dateFormatter.dateFormat = "ss"
return dateFormatter.string(from: date)
}
func isComplete() -> Bool{
let lastCompletedDate = lastCompleted.components(separatedBy: " ") //split it into a list
let curDate = getCurDate().components(separatedBy: " ")
//return true if they did the task today
//return false if they didnt do the task today
if lastCompletedDate[0] == curDate[0] && lastCompletedDate[1] == curDate[1] && lastCompletedDate[2] == curDate[2]{
return true
}
return false
}
func todaysTask() -> String{
if isComplete(){ //if they did their task today
return "Completed"
}
return getTask(year: currentDate.get(.year), month: currentDate.get(.month), day: currentDate.get(.day))
}
var body: some View {
VStack{
HStack{
Text("\(getStreak())")
.font(.largeTitle)
.onReceive(timer) { time in //updates every minute
print("TIMER ACTIVATED")
let dayDistance = compareCompletedTasks()
let theStreak = getStreak()
if dayDistance == 2 && theStreak != "loading..." && Int(theStreak)! > 0{ //they missed a day (reset streak)
//resetStreak()
print("reset streak")
}
}
Text(Image(systemName: "flame.fill"))
.font(.largeTitle)
.foregroundColor(flameColor())
}
Spacer()
VStack{
Text("Task")
.font(.title)
.fontWeight(.bold)
Text(todaysTask())
.font(.title2)
.padding()
//.overlay {Rectangle().stroke(.gray, lineWidth: 5)}
Button(action: completeTask){
Text("Complete")
.padding()
.overlay{
Rectangle().stroke(.black, lineWidth: 3)
}
.background(buttonColor())
.foregroundColor(.black)
}
.disabled(isComplete())
// Text(getTheTime(from: currentDate))
// .onReceive(timer) { input in
// currentDate = input
// print(currentDate)
// }
}
Spacer()
Spacer()
.frame(width: 10000, height: 150)
}
.background(.green)
.onAppear(perform: getTasks)
}
}
struct HomeScreen_Previews: PreviewProvider {
@State static var placeHolder: [String] = ["123456", "0", "2022 1 1"]
@State static var placeHolder2: String = ""
@State static var placeHolder3: String = "2022 1 1"
static var previews: some View {
HomeScreen(username: $placeHolder2, LoginResponse: $placeHolder, lastCompleted: $placeHolder3)
}
}
I stopped calling the function expecting the error to stop, it never did. I reset my computer hoping it would fix, it didn't I changed the timer requency hoping the error would then happen every second, it didn't. It happened every minute still