I'm building an ios app using SwiftUI for frontend and ts for API.
I've tried printing the fetched data out using List(results) { result in... and then Text(result.current_button.title) instead of showing the data I had a white space there.
Now I'm trying to solve the problem using ForEach(list.datas){ , but it's also now showing.
How do I print the fetched data on the app's screen?
import SwiftUI
class MainScreenVM: ObservableObject {
#Published var datas = [MainScreenStruct]()
init() {
loadData()
}
func loadData() {
print("Fetching started")
guard let url = URL(string: "http://localhost:3000/getMainScreen")
else {
print("Invalid URL")
return
}
let json: [String: Any] = ["grade": "12R",
"group": ["matemaatika": "G1",
"eesti keel": "G2"]]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
if let response = try? JSONDecoder().decode([MainScreenStruct].self, from: data) {
DispatchQueue.main.async {
//DispatchQueue.global().async {
self.datas = response
}
return
}
}
}.resume()
}
}
struct MainScreen: View{
#StateObject var list = MainScreenVM()
var body: some View {
ZStack{
LinearGradient(colors: [.pink, .orange], //if all lessons are finished or a weekend than fun color
startPoint: .topLeading, endPoint: .bottomTrailing)
.edgesIgnoringSafeArea(.all)
VStack {
VStack {
ProgressView(value: 2, total: 5) //value and total depends on the amount of lessons and lessons done
.padding()
HStack {
VStack(alignment: .leading) {
Text("Lessons done")
.font(.system(size: 20))
Label("3", systemImage: "house.fill") //instead of actual amount "300"
}
.padding()
Spacer()
VStack(alignment: .trailing) {
Text("Lessons left")
.font(.system(size: 20))
Label("2", systemImage: "flag.checkered.2.crossed")
}
.padding()
}
Spacer()
HStack {
VStack(alignment: .center) {
Button(action: {
print("VENE SUUR SÖÖGISAAL")
}) {
ForEach(list.datas) { item in
HStack{
Image(systemName: "brain.head.profile")
.font(.largeTitle)
Text(item.current_button.title)
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.foregroundColor(.white)
.background(LinearGradient(colors: [.indigo, .accentColor],
startPoint: .bottomTrailing, endPoint: .leading))
.cornerRadius(10)
.shadow(color: .gray, radius: 5.0)
.padding()
}
}
VStack() {
Text("Ends in {0} hours {20} minutes {4} seconds")
}
}
}
HStack {
VStack(alignment: .center) {
Button(action: {
print("VENE SUUR SÖÖGISAAL")
}) {
HStack{
Image(systemName: "books.vertical.fill")
.font(.largeTitle)
Text("Next lesson is {English}")
.font(.subheadline )
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.foregroundColor(.white)
.background(LinearGradient(colors: [.indigo, .accentColor],
startPoint: .bottomTrailing, endPoint: .leading))
.cornerRadius(10)
.shadow(color: .gray, radius: 5.0)
.padding()
}
Text("The lesson starts at {14:50}")
}
}
HStack {
VStack(alignment: .center) {
Button(action: {
print("VENE SUUR SÖÖGISAAL")
}) {
HStack{
Image(systemName: "fork.knife.circle.fill")
.font(.largeTitle)
Text("Lunch is in 1 hour 15 minutes 30 seconds")
.font(.subheadline )
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.foregroundColor(.white)
.background(LinearGradient(colors: [.indigo, .accentColor],
startPoint: .bottomTrailing, endPoint: .leading))
.cornerRadius(10)
.shadow(color: .gray, radius: 5.0)
.padding()
}
}
}
Spacer()
}
}
}
}
}
struct TimeLeft_Previews: PreviewProvider {
static var previews: some View {
MainScreen()
}
}
class VM: ObservableObject {
#Published var posts: [Post] = []
#Published var errorString:Bool = false
init() {
getDataFromAPI()
}
func getDataFromAPI() {
// Make a request to your localhost to retrieve the list of users
guard let url = URL(string: "http://localhost:3000/posts") else {
print("Invalid URL")
return
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
print("Error fetching users: \(error.localizedDescription)")
DispatchQueue.main.async {
self.errorString = true
}
return
}
guard let data = data else { return }
do {
// Parse the JSON data and create an array of User objects
let jsonDecoder = JSONDecoder()
let posts = try jsonDecoder.decode([Post].self, from: data)
DispatchQueue.main.async {
self.posts = posts
}
} catch {
print("Error parsing JSON: \(error.localizedDescription)")
}
}.resume()
}
}
This is my view model and fetch func. You can change the code as you need.
Related
am a beginner in swiftui, still learning how to deal with ObservableObject
let me show my code and illustrate what is my question...
JsonResponse as follows:
{
"error" : false,
"user" : {
"username" : "Maxwell",
"id" : 84560,
"name" : "Max",
"authority" : "Manager"
}
}
Authenticate User Class (ObservableObject):
import Foundation
import Alamofire
struct UserDetails{
static var id: String = ""
static var name: String = ""
static var authority: String = ""
}
class AuthenticateUser: ObservableObject{
#Published var isLoggedin: Bool = false
func Authenticate(Username:String,Password:String){
let url:String = "http://…./Login.php"
let headers: HTTPHeaders = ["Content-Type":"application/x-www-form-urlencoded"]
let data: Parameters = ["username":Username,"password":Password]
AF.request(url, method: .post, parameters: data, encoding: URLEncoding.default, headers: headers).validate(statusCode: 200 ..< 299).response { AFdata in
do {
guard let jsonObject = try JSONSerialization.jsonObject(with: AFdata.data!, options: .mutableContainers) as? NSDictionary else {
print("Error: Cannot convert data to JSON object")
return
}
guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted) else {
print("Error: Cannot convert JSON object to Pretty JSON data")
return
}
guard let prettyPrintedJson = String(data: prettyJsonData, encoding: .utf8) else {
print("Error: Cannot print JSON in String")
return
}
//if there is no error
if(!(jsonObject.value(forKey: "error") as! Bool)){
print(prettyPrintedJson)
//getting the user from response
let user = jsonObject.value(forKey: "user") as! NSDictionary
//getting user values
let userID = user.value(forKey: "id") as! Int
let name = user.value(forKey: "name") as! String
let authority = user.value(forKey: "authority") as! String
//saving user values
UserDetails.id = String(userID)
UserDetails.name = name
UserDetails.authority = authority
self.isLoggedin = true
}else{
//error message in case of wrong credentials
print("Wrong Credentials")
}
} catch {
print("Error: Trying to convert JSON data to string")
return
}
}
}
}
Login View:
import SwiftUI
struct Login: View {
#StateObject private var loginManager = AuthenticateUser()
#State var username = ""
#State var password = ""
var body: some View {
ZStack{
Rectangle()
.fill(Color(red: 33 / 255, green: 34 / 255, blue: 36 / 255))
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
VStack(){
Spacer()
Image("Logo")
Spacer()
VStack(){
Text("RIVIERA BEACH CHALETS")
.font(.title2)
.fontWeight(.semibold)
.foregroundColor(.white)
.multilineTextAlignment(.center)
Text("Administration System")
.font(.headline)
.fontWeight(.light)
.foregroundColor(.white)
}
Spacer()
Text("Sign in")
.font(.largeTitle)
.fontWeight(.medium)
.foregroundColor(.white)
Spacer()
VStack(){
ZStack {
if username.isEmpty {
Text("Username")
.foregroundColor(.white.opacity(0.3))
}
TextField("", text: $username)
.padding()
.multilineTextAlignment(.center)
.foregroundColor(.white)
.overlay(RoundedRectangle(cornerRadius: 20).stroke(Color.white,lineWidth: 1))
}.padding(.horizontal,5).padding(.vertical,5)
Spacer().frame(height: 15)
ZStack {
if password.isEmpty {
Text("Password")
.foregroundColor(.white.opacity(0.3))
}
SecureField("", text: $password)
.padding()
.multilineTextAlignment(.center)
.foregroundColor(.white)
.overlay(RoundedRectangle(cornerRadius: 20).stroke(Color.white,lineWidth: 1))
}.padding(.horizontal,5).padding(.vertical,5)
Spacer().frame(height: 15)
HStack {
Button(action:{
//BUTTON ACTION
loginManager.Authenticate(Username: username, Password: password)
},label: {
Spacer()
Text("AUTHENTICATE")
.font(.subheadline)
.fontWeight(.bold)
.foregroundColor(.white.opacity(0.8))
Spacer()
}) .padding()
.background(Color(red: 40 / 255, green: 41 / 255, blue: 43 / 255))
.cornerRadius(20)
}.padding(.horizontal,20).padding(.vertical,5).padding()
Spacer()
}.padding(20)
Spacer()
}
}
}
}
struct LoginPreview: PreviewProvider {
static var previews: some View {
Login()
}
}
let me explain what is going on... and what is my question:
As you can see in code, we have a Json Object response being parsed as NS dictionary while revalidating the UserDetails variables with the data from the Json response, and a published Bool to detect whether logged in or not !
so the question is, how to setup that bool to let the view detect whether user logged in or not ... ? in another words ,what to type in the view code to let the app switch the view to Home view for example if logged in was true ... ? while parsing the user details to show it in that Home view.
Any help would be appreciated !
I make a json call to get some data from as seen from the image, but I have to sort these items by stargazers_count, ie the items with the largest stargazers_count put before.
Can you give me a hand?
Code:
import SwiftUI
import AppKit
struct Obj: Codable, Identifiable {
public var id: Int
public var name: String
public var language: String?
public var description: String?
public var stargazers_count: Int
public var forks_count: Int
}
class Fetch: ObservableObject {
#Published var results = [Obj]()
init(name: String) {
let url = URL(string: "https://api.github.com/users/"+name+"/repos?per_page=1000")!
URLSession.shared.dataTask(with: url) { data, response, error in
do {
if let data = data {
let results = try JSONDecoder().decode([Obj].self, from: data)
DispatchQueue.main.async {
self.results = results
}
print("Ok.")
} else {
print("No data.")
}
} catch {
print("Error:", error)
}
}.resume()
}
}
struct ContentViewBar: View {
#ObservedObject var fetch = Fetch(name: "github")
var body: some View {
VStack(alignment: .leading, spacing: 0) {
List(fetch.results) { el in
VStack(alignment: .leading, spacing: 0) {
Text("\(el.name) (\(el.stargazers_count)/\(el.forks_count)) \(el.language ?? "")").padding(EdgeInsets(top: 5, leading: 0, bottom: 0, trailing: 0))
if el.description != nil {
Text("\(el.description ?? "")")
.font(.system(size: 11))
.foregroundColor(Color.gray)
}
}
}.listStyle(SidebarListStyle())
// Button(action: { NSApplication.shared.terminate(self) }){
// Text("X")
// .font(.caption)
// .fontWeight(.semibold)
// }
// .padding(EdgeInsets(top: 2, leading: 0, bottom: 2, trailing: 2))
// .frame(width: 360.0, alignment: .trailing)
}
.padding(0)
.frame(width: 360.0, height: 360.0, alignment: .top)
}
}
struct ContentViewBar_Previews: PreviewProvider {
static var previews: some View {
ContentViewBar()
}
}
In the end, he seems to have succeeded.
Code:
List(fetch.results.sorted { $0.stargazers_count > $1.stargazers_count }) { el in
Sorting in UI drawing cycle might result in performance issue (especially in case of huge container), so it is better to perform sort either in-advance, or out-of-UI flow.
So I'd recommend to do it here
let results = try JSONDecoder().decode([Obj].self, from: data)
let sorted = results.sorted { $0.stargazers_count > $1.stargazers_count }
DispatchQueue.main.async {
self.results = sorted
}
I use 'Api' as an ObervableObject and inside there's #Published var isAscd to be toggled. Function getPost fetch JSON data from web and populate is List View. I use a button in HeaderView to toggle the sorting method. Compiling is succeeded but button takes no action. I don't know what goes wrong?
class Api: ObservableObject {
#Published var posts: [Post] = []
#Published var isAscd: Bool = false
func getPosts(completion: #escaping ([Post]) -> ()) {
guard let url = URL(string: getListURLString) else { return }
URLSession.shared.dataTask(with: url) { (data, _, _) in
let posts = try! JSONDecoder().decode([Post].self, from: data!)
DispatchQueue.main.async {
completion(posts)
}
}
.resume()
}
}
struct HeaderView: View {
var holding: String = "市值/數量"
var earning: String = "現價/成本"
var profit: String = "持倉賺蝕"
#ObservedObject var api = Api()
var body: some View {
HStack{
Button(action: {
self.api.isAscd.toggle()
if self.api.isAscd {
self.api.posts.sort { $0.stockcode > $1.stockcode}
} else { self.api.posts.sort { $0.stockcode < $1.stockcode}
}
print(self.api.posts.count)
print(self.api.isAscd)
}.......}
List {
Section(header: HeaderView())
{
ForEach(posts)
{ post in
HStack {
VStack(alignment: .leading)
..........
}
}.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 250, alignment: .center)
.onAppear {
Api().getPosts {(posts) in
self.posts = posts
//self.apr.isAscd.toggle()
}
}
}
I need to post a https request to login view (SwiftUI), my code follow I have in getres.swift:
so I neet to get value from response and put it in the text
import Foundation
import Combine
struct result: Decodable {
let res, ordercount, rate: String
}
class getres: ObservableObject {
let objectWillChange = PassthroughSubject<getres, Never>()
#Published var authenticated = ""
#Published var todos = [result]() {
didSet {
objectWillChange.send(self)
}
}
func auth(username: String, password: String) {
guard let url = URL(string: "http://company.com/auth.php") else { return }
let body: [String: String] = ["username": username, "password": password]
let finalBody = try! JSONSerialization.data(withJSONObject: body)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = finalBody
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data=data else{return}
let fineldata=try! JSONDecoder().decode(result.self, from: data)
DispatchQueue.main.async {
self.todos = [fineldata]
self.authenticated=fineldata.res
}
print(fineldata)
}.resume()
}
}
and in the login page I try to show other view
in this code I will get values from function as json response I will get ordercount and rate I put it in the other view
import SwiftUI
struct ContentView: View {
#State private var username: String = ""
#State private var password: String = ""
#ObservedObject var manager = getres()
var body: some View {
VStack(alignment: .leading) {
if manager.authenticated == "2"{
userdetails()
}else{
Text("Username")
TextField("placeholder", text: $username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
.autocapitalization(.none)
Text("Password")
SecureField("placeholder", text: $password)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
Button(action: {
self.manager.auth(username: self.username, password: self.password)
}) {
HStack{
Spacer()
Text("Login")
Spacer()
}
.accentColor(Color.white)
.padding(.vertical, 10)
.background(Color.red)
.cornerRadius(5)
.padding(.horizontal, 40)
}
}.padding()}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
and in userdetails this so I need to get values from response
struct userdetails: View {
#State var controller = getres()
var body : some View{
ScrollView(Axis.Set.vertical, showsIndicators: true) {
VStack(spacing: 20){
Image("wlogo").renderingMode(.original); HStack(spacing: 15){
Spacer()
VStack(alignment: .center, spacing: 10) {
Text(???).foregroundColor(Color.white).bold()
.font(.largeTitle)
Text("")
.foregroundColor(Color.white)
.font(.headline) }
Spacer()
}}}}
how can I get ordercount from response and put in
text(???)
in the view userdetails
for example controller.todos.ordercount
I get this error
Value of type '[result]' has no member 'ordercount'
when I try
Text(controller.todos.ordercount)
json response
{"res":"2","ordercount":"20","rate":"5"}
UPDATED ANSWER
1.) it would be helpful if you copy your code in just one part - this is easier for all of us to copy
2.) you should try out your code yourself before you copy or change something in your code manually. it is annoying to find mistakes like:
if manager.authenticated == "2"{
userdetails()
} else{
Text("Username")
TextField("placeholder", text: $username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
.autocapitalization(.none)
Text("Password")
SecureField("placeholder", text: $password)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
Button(action: {
self.manager.auth(username: self.username, password: self.password)
}) {
HStack{
Spacer()
Text("Login")
Spacer()
}
.accentColor(Color.white)
.padding(.vertical, 10)
.background(Color.red)
.cornerRadius(5)
.padding(.horizontal, 40)
}
}.padding()}
}
where you are adding .padding() to an if-statement....
3.) you should name class names in that way people can understand what the class if for and start with a capitalized letter like Apple does with all class names
4.) you should also begin View names capitalized (like Apple does)
5.) since i have to access to your page and you did not provide example data and/or password i have no idea what data are coming there...
here is my solution code so far:
i added some faking data, because i cannot access your data ....so you can see something in details.
struct ToDo: Decodable, Identifiable {
var id = UUID().uuidString
let res, ordercount, rate: String
}
class ToDoGetter: ObservableObject {
let objectWillChange = PassthroughSubject<ToDoGetter, Never>()
#Published var authenticated = ""
#Published var todos = [ToDo]() {
didSet {
objectWillChange.send(self)
}
}
let someFakingTodos = [
ToDo(res: "a", ordercount: "5", rate: "75%"),
ToDo(res: "b", ordercount: "52", rate: "5%"),
ToDo(res: "c", ordercount: "566", rate: "7%"),
ToDo(res: "d", ordercount: "53", rate: "33%"),
ToDo(res: "e", ordercount: "15", rate: "44%"),
ToDo(res: "f", ordercount: "345", rate: "10%")
]
func auth(username: String, password: String) {
guard let url = URL(string: "http://company.com/auth.php") else { return }
let body: [String: String] = ["username": username, "password": password]
let finalBody = try! JSONSerialization.data(withJSONObject: body)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = finalBody
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data=data else{return}
let fineldata=try! JSONDecoder().decode(ToDo.self, from: data)
DispatchQueue.main.async {
self.todos = [fineldata]
self.authenticated=fineldata.res
}
print(fineldata)
}.resume()
}
}
struct ContentView: View {
#EnvironmentObject var todoGetter : ToDoGetter
#State private var username: String = ""
#State private var password: String = ""
#State var navigateToDetail : Bool = false
var body: some View {
NavigationView {
VStack(alignment: .leading) {
if todoGetter.authenticated == "2"{
Userdetails().environmentObject(todoGetter)
} else{
Text("Username")
TextField("placeholder", text: $username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
.autocapitalization(.none)
Text("Password")
SecureField("placeholder", text: $password)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
NavigationLink(destination: Userdetails(), isActive: self.$navigateToDetail) {
EmptyView() }
.hidden()
.padding()
Button(action: {
self.todoGetter.auth(username: self.username, password: self.password)
self.navigateToDetail.toggle()
}) {
HStack{
Spacer()
Text("Login")
Spacer()
}
.accentColor(Color.white)
.padding(.vertical, 10)
.background(Color.red)
.cornerRadius(5)
.padding(.horizontal, 40)
}
}
}
}
}
}
struct Userdetails: View {
#EnvironmentObject var todoGetter : ToDoGetter
var body : some View{
VStack(spacing: 20) {
Image("wlogo").renderingMode(.original); HStack(spacing: 15){
Spacer()
List(todoGetter.someFakingTodos) { todo in
VStack(alignment: .center, spacing: 10) {
HStack {
Text(todo.res).foregroundColor(Color.white).bold()
.font(.largeTitle)
Text(todo.ordercount)
.foregroundColor(Color.white)
.font(.headline)
Text(todo.rate)
.foregroundColor(Color.white)
.font(.headline)
}
}.background(Color.black)
Spacer()
}
}
}
}
}
OLD ANSWER
you call getres 2 times. you have to call it just once and then give the value to the detailview.
the model should only be created once per app.
I am trying to call a function I have made which pulls data from an API. The function is created before the var body: some View part and is call inside of that. There are no compiler errors in the function itself or anywhere else. Before I started to use SwiftUI I had no issue with this type of function and the code is almost the exact same. Here is the code for the function including the Struct I have for the JSON data;
var postDetailsData = postDetails.self
var commentsArray = comments.self
struct postDetails: Decodable {
let count: Int?
var results: [results]
}
struct results: Decodable {
var id: String
let author: author?
let anonym: Bool
let subscribed: Bool
let created: String
let active: Bool
let text: String
let image: String?
let comments: [comments]
}
struct author: Decodable {
let user: Int
var name: String
let avatar: String?
let banned: Bool
}
struct comments: Decodable, Identifiable {
let id: Int
let text: String
let author: authorOfComment?
}
struct authorOfComment: Decodable {
let name: String
let avatar: String?
}
//And now the actual function
let tokenData = UserDefaults.standard.object(forKey: "savedToken")
var spread = Bool()
let request = NSMutableURLRequest(url: NSURL(string: "http://localhost:8000/areas/sample/")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
func pullData(){
let headers = [
"Authorization": "token \(tokenData ?? "nope")",
"cache-control": "no-cache",
"Postman-Token": "53853353-f547-410a-b289-e3c4ced8e426"
]
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error)
}
guard let data = data else {return}
do{
let JSONFromServer = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
print(JSONFromServer)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let postDetailsDataArray = try decoder.decode(postDetails.self, from: data)
print(postDetailsDataArray.results)
for results in postDetailsDataArray.results{
DispatchQueue.main.async {
//Account Pic Post and Other Stuff In The HStack
let accountPicAndStuff = HStack {
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
ImageWithActivityIndicator(imageURL: results.author?.avatar ?? "")
.frame(width: 30, height: 30)
.clipShape(Circle())
.offset(x: -75, y: 0)
}
Text(results.author?.name ?? "Annon")
.offset(x: -75)
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Image("BookMark").offset(x: 70)
}
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Image("more-vertical").offset(x: 70)
}
}.offset(y: 65)
//accountPicAndStuff.offset(y: 65)
//Description code (pulls data from api)
var postTextTest = results.text
Text(results.text)
//.padding(.bottom, 0)
.offset(y: 10)
.lineLimit(4)
//Image From Post Stuff
if results.image == nil{
print("no image")
}else{
ImageWithActivityIndicator(imageURL: results.image ?? "")
.offset(y: 50)
.scaledToFit()
}
//Date and time for post
Text(results.created)
.font(.footnote)
.fontWeight(.light)
.foregroundColor(Color.gray)
.multilineTextAlignment(.leading)
.offset(x: -85, y: 50)
for comments in results.comments{
print(comments)
//Comment View Code using Lists
List(results.comments){ comments in
HStack{
ImageWithActivityIndicator(imageURL: comments.author?.avatar ?? "")
.frame(width: 100.0, height: 100.0)
}
}
}
}
}
}catch{
print("Failed to decode:", error)
}
})
dataTask.resume()
}
This is how I call the function;
struct FunAreaSmall: View {
//Code from above goes here...
var body: some View {
//Smaller UI
VStack {
pullData()
HStack {
Button(action:{}) {
Image("SkipBtn")
.offset(y: 60)
.scaledToFit()
}
Button(action: {}) {
Image("IgniteBtn")
.offset(y: 60)
.scaledToFit()
}
}
}
}
}
The error itself,
'Int' is not convertible to 'CGFloat'
appears on .offset(y: 60) on the first button in the HStack which I know isn't the issue because when I comment out the call to the function, the error goes away. I have tried different ways of doing getting around this error but all I get is more errors. I have tried to look up the errors on google and nothing has helped yet.
You can't just put function call in a ViewBuilder, because it can't resolve opaque return type.
There are several possible solutions, depending on your needs:
1) Put call of pullData in init()
2) Provide explicit return in ViewBuilder (all of them)
3) Call in some closure (seems most appropriate in this use-case) as in below:
struct FunAreaSmall: View {
//Code from above goes here...
var body: some View {
//Smaller UI
VStack {
HStack {
Button(action:{}) {
Image("SkipBtn")
.offset(y: 60)
.scaledToFit()
}
Button(action: {}) {
Image("IgniteBtn")
.offset(y: 60)
.scaledToFit()
}
}
}
.onAppear() {
self.pullData()
}
}
}