TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

Lost in GridView

Forums > SwiftUI

Hi,

I am new to Swift UI. I want to do a two dimensional grid view in an iOS app. (Details: it's a storyboard-app, with an UIHostingController. I get data via Rest-API, put them in SwiftData) All worked until now with only showing the data (Text), but now I have to use TextField. The data from (given) rest-api already represent the elements of a view. Here is a minimalized version: (I deleted many attributes and simplified some attributenames here)

@Model
class SDPFData {
  let pId: String
  let arId: String
  let row: Int
  let column:Int
  let fType: String
  let connectCol: Int
  var textString: String?

  init(...){...}//simple init
  }
  // the data of one person with "pId" have to be viewed. Every pId has many SPDFData, that construct to a view.
      func getSpanColumns() -> Int
    {
        return (self.connectCol + 1)
    }
  class pViewModel{
    var prueflingId: String
    var fields:   [[SDPFData]]
    //array of arrays: fields[0] is an array of all SDPFData of the first row ... all are already sorted
    init(pId: String) {...loading all data fo one pId , sorting them into "fields"}
    }
 struct SwiftUIViewPPB: View {
    @State var pD: pViewModel
    @State private var currentZoom = 0.0
    @State private var totalZoom = 1.0
    var body: some View {
        Text("Hello, World!)
        ScrollView([.horizontal, .vertical]){
            Grid(alignment: .leading, horizontalSpacing: 5, verticalSpacing: 5) {
                ForEach(pD.fields, id: \.self)
                {
                    rowArray in
                    GridRow{
                        ForEach(rowArray){
                            fData in
                            switch fData.fType{
                            case "textout“:
                                Text(fData.textString ?? "/").gridCellColumns(fData.getSpanColumns())
                            case "textblock":
                                Text(fData.textString ?? "//").gridCellColumns(fData.getSpanColumns())
                            case "textinput“:
                                Text(„input“)//TextField(fData.textString ?? "" , text: $fData.textString)
                            default:
                                Text("##" + fData.fType).gridCellColumns(fData.getSpanColumns())
                            }
                        }
                    }//GridRowEnd
                }.padding(.horizontal)
            }
        }.scaleEffect(currentZoom + totalZoom)
            .gesture(
                MagnifyGesture()
                    .onChanged { value in
                        currentZoom = value.magnification - 1
                    }
                    .onEnded { value in
                        totalZoom += currentZoom
                        currentZoom = 0
                    }
            )
            .accessibilityZoomAction { action in
                if action.direction == .zoomIn {
                    totalZoom += 1
                } else {
                    totalZoom -= 1
                }
            }
        Text("")

    }
}

Until this point, all does work well: I get a scrollable, pinchable Grid. Fine.

But when I want to change "TextField" for input nothing works. First try: TextField as outcommented above: "$fData.textString not in scope". OK. I think I do not have to present the local fData (fData.textString), but the central pD: *pD[row][column]

So I tried to do the ForEach with .indices : ForEach(pD.fields.indices, id: .self) rowIn in ... ForEach(pD.fields[rowIn], id: .self) colIn in ... and then pD.field[rowIn][colIn].textString

But that does not work, too: "Non-constant range: not an integer range"

Then I tried instead 0..<pD.count: "Generic parameter could not be inferred".

So I am a little lost, how to go on. I think, the solution is not searchinbg for the indices-problems. I guess I have a (mind) problem somewhere earlier in my code. Any suggestions?

I am not flexible about the founding data-structure, because it's as-is from a rest-api I have to use. But of course I can go all different directions in my swift-app.

Thanks for help

1      

On the same day she creates her account @ps2024 drops a coding mess and seeks help....

So I am a little lost, how to go on. I think, the solution is not
searchinbg for the indices-problems. I guess I have a (mind) problem
somewhere earlier in my code. Any suggestions?

Wow! Welcome to HackingWithSwift. @twoStraws asks us to help others in these forums, but we're asked to criticise ideas, not people.

Bad Idea

Your code gives us clues that you're not following the 100 Days of SwifUI program. There are several coding violations that a 100 Days student would have corrected before posting this code. You ask for suggestions? I suggest you put your project off to the side for a few weeks, and follow at least the first 60 of the 100 Days program.

JSON, SwiftData, @StateObjects and more!

If you analyse your application, you have several parts that you should consider as separate problems to solve.

First, grabbing data from JSON. Maybe you have this solved? If not there are several good lessons here in HWS. Once you've pulled JSON data into your application, it's not JSON data anymore! It's your application's data.

Application's Data

I am not flexible about the founding data-structure, because it's as-is from a rest-api

Second, turning the JSON into SwiftData. One lesson you may want to consider is once you've extracted the JSON elements, you are FREE to reformat the data in your application to suit your own needs. You are not obligated to use the formats, names, or structures of the JSON that was provided to you. You're the architect. You make the decisions.

Sharing Objects

You're having issues trying to change data on screen, and have those changes reflected in your data store.

I want to change "TextField" for input nothing works

Our excellent instructor, @twoStraws, teaches this very lesson in this course. I implore you to step away from your code and watch several of his lessons. You do not share objects using the @State decorators. But telling you to not use this doesn't help you. You need to know WHY this is incorrect, and @twoStraw's lessons will bring you to that state of awareness (pun intended) .

struct SwiftUIViewPPB: View {
    @State var pD: pViewModel  // <- Do you know why?

Keep Coding

Follow the lessons!

1      

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.