AR ForEach Help Please

Hi there,

I am trying to create an AR model viewer based on the ARCourse here on CWC. This has some models which are defined in a JSON. I’ve created a model and DataService to decode but can’t get the ForEach to work in ContentView. Please could you help?


What does your modelTitle look like?

Your id is an int change it to a string so it can iterate it…and it can display on your text field

Var Id:string

Or
Var Id = uuid()

Then
ForEach(model, Id:.id) { i in

Button{
Text(i.name)
}

Or with int try this

ForEach(model, Id:.Id) {
Text(“($0.name)”)

}

Hi Jermaine,

I really appreciate your help. Thanks.

The modelTitle is a string as in the image of the json attached.

I’ve tried the changes to the ForEach loop but still get some errors. The Id is on line 7. Please could you advise?

Again, many thanks for your help.

you getting it wrong you need to decode your json in to your model and use combine framework to pass watch the recipe tutorials you will get it on cwc+

@ahowe.CWC

Hi Adrian,

In your Models.swft file do you have a Published property which is an array for each one of your JSON elements to be stored in after decoding and do you have an init() { } function that is calling your DataService to decode your JSON into that array?

@ahowe.CWC

The other thing that will help us to help you is if you post your code as text rather than a screenshot.

To format the code nicely, place 3 back-ticks ``` on the line above your code and 3 back-ticks ``` on the line below your code. Like this:

```
Code goes here
```

The 3 back-ticks must be the ONLY characters on the line. The back-tick character is located on the same keyboard key as the tilde character ~ (which is located below the Esc key - QWERTY keyboard).

Alternatively after you paste in your code, select that code block and click the </> button on the toolbar. This does the same thing as manually typing the 3 back ticks on the line above and below your code.

This also makes it easier for anyone assisting as they can copy the code and carry out some testing.

(edit)
Can you post your JSON code in a reply.

Hi,

I have as below (in ViewModels).

import Foundation

class Models: ObservableObject {
    
    @Published var models = [Model]()
    
    init() {
        
        self.models = DataService.getLocalData()
    }
}

I’ve made a few changes and just trying to get the horizontal menu to show, but I can’t work out how to give an instance to the previewer. This is the only error I have here. ARViewContainer doesn’t do anything at the moment. Any help much appreciated.

import SwiftUI
import RealityKit

struct ContentView : View {
    
    var menuModels: [Model]
    
    var body: some View {
        
        ZStack {
            
            // AR View
            ARViewContainer().edgesIgnoringSafeArea(.all)
            
            // MiR logo and menu
            
            VStack{
                // Logo
                Image("mylogo")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 200)
                
                // Space for view
                Spacer()
                
                // Menu
                
                ScrollView(.horizontal, showsIndicators: false){
                    HStack{
                        
                        ForEach(0..<self.menuModels.count) { index in
                            
                            Button(action: {
                                print ("DEBUG: selected \(self.menuModels[index].modelTitle)")
                            }) {
                                Image(self.menuModels[index].menuImage)
                            }
                        }
                    }
                    .frame(height:180)
                }
            }
        }
    }
}

struct ARViewContainer: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)
        
        // Load the "Box" scene from the "Experience" Reality File
        let boxAnchor = try! Experience.loadBox()
        
        // Add the box anchor to the scene
        arView.scene.anchors.append(boxAnchor)
        
        return arView
        
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {}
    
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        
        let model = Models()
        
        ContentView(menuModels: model.models[0])
    }
}
#endif

Your Models is an ObservableObject with a Published property of models

In your ContentView you need to declare an @ObservedObject so that the view can respond to changes in the array models.

In your ForEach you have not referred to the array so it should be:
ForEach(0..<self.menuModels.models.count) { index in

Here is an updated version of your ContentView

struct ContentView : View {
    
    @ObservedObject var menuModels = Model()
    
    var body: some View {
        
        ZStack {
            
            // AR View
            ARViewContainer().edgesIgnoringSafeArea(.all)
            
            // MiR logo and menu
            
            VStack{
                // Logo
                Image("mylogo")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 200)
                
                // Space for view
                Spacer()
                
                // Menu
                
                ScrollView(.horizontal, showsIndicators: false){
                    HStack{
                        
                        ForEach(0..<menuModels.models.count) { index in
                            
                            Button(action: {
                                print ("DEBUG: selected \(menuModels.models[index].modelTitle)")
                            }) {
                                Image(menuModels.models[index].menuImage)
                            }
                        }
                    }
                    .frame(height:180)
                }
            }
        }
    }
}

I think your naming convention is confusing you to some degree.

Hi Chris,

That’s perfect. Thanks. Much appreciated!