Learn Courses My Dashboard

Module2 lesson9 optional challange

Hello,

The instructions in the challange tell me to write optional check on my optional array in the View, under the buttons. But I’m getting lots of errors like : the Type can not conform to View, and I am not using any structs here just typing in the View under the buttons. variables are getting out of scope cause they are in the conditional braces. The circus of red errors came home :slight_smile: Can you give me a small hint I do not want to look to solutions before i solve it. greetings Ewa

@ewaperl

Hi Ewa,

Can you post your code so that we can see what you are trying to do.

Paste your code in as text, rather than providing a screenshot.

Place 3 back-ticks ``` on the line above your code and 3 back-ticks ``` on the line below your code so that it is formatted nicely. The back-tick character is located on the same keyboard key as the tilde character ~.

This also makes it easier for anyone assisting as they can copy the code and carry out some testing rather than having to type the code in from an image.

1 Like
//
//  ContentView.swift
//  OptionalArray
//
//  Created by Ewa Boer on 22/04/2021.
//

import SwiftUI

struct ContentView: View {
    
    
    @State var arrayOfStrings:[String]?
    @State var x = ["cat", "dog", "panda"]
    @State var text = " "
    
    var body: some View {
        
        VStack {
            
            List(arrayOfStrings!, id:\.self) {
                arrayElement in Text(arrayElement)
            }
            Text(text)
            HStack {
                
                Button(action: {
                    //tapOtherButton
                     arrayOfStrings = nil
                        
                }, label: {
                    Text("Nil")
                })
                Button(action: {
                    pets()
                }, label: {
                    /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
                })
                
                // when I try to check here if the array is nil I get errors
                //text variable is out of scope here i can not uodate it from here
               
                
            }
          }
        func pets() {
            arrayOfStrings?.append(contentsOf: x)
            text = " "
        }
       
        
        
        
        struct ContentView_Previews: PreviewProvider {
            static var previews: some View {
                ContentView()
            }
        }
    }
}

@ewaperl

Hi Ewa,

There are missing closing braces } in your code so that’s one of the problems you need to solve. Tap on each opening brace { to reveal where the matching brace is and you should be able to identify where the missing closing brace } should be.

Try to name your @State properties in a meaningful way. Rather than declare

@State var x = ["cat", "dog", "panda"]

name it this so that it describes what the array contains

@State var myPets = ["cat", "dog", "panda"]

The challenge says to place the 2 buttons at the top and the List below it controlled by an If statement.

The if statement is to check if the arrayOfStrings is equal to nil. If it is then display a message to say something like “Tap on the Add button” otherwise (the else clause) display the arrayOfStrings in a List.

Hi thank you, it seems so straight forward but im getting only errors that i do not conform to view, just trying to write if else statement under the button in the view i tried all kinds of optionals check, I was thinking to put list into if else statement, i did it once, more errors, i tried IF LET optional check too.
sorry for missing braces i was trying so many ways yesterday that the code got butchered, one more hint please :slight_smile:

//
//  ContentView.swift
//  MyPets
//
//  Created by Ewa Boer on 24/04/2021.
//

import SwiftUI

struct ContentView: View {
    
    @State var arrayOfStrings:[String]?
    @State var text = " "
    @State var myPets = ["cat", "dog", "panda"]
    
    var body: some View {
        
        Button(action: {
            arrayOfStrings = nil
           
        }, label: {
            /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
        })
        
        Button(action: {
            for _ in myPets {
                arrayOfStrings?.append(contentsOf: myPets)
            }
            text = "it's ok I have pets"
        }, label: {
            /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
        })
      
        if arrayOfStrings == nil {
            text = "tap the other button"
        } else { //anything I do here tells me it doesnt conforms to view, text is out of scope
            
        }
        
        Text(text)
        List(arrayOfStrings! , id:\.self) {arrayElement in Text(arrayElement)
            
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

You need to use a VStack or HStack

The variable body retunes “some view” which is singular, you can only return one view like a single VStack. It’s inside the VStack that you can begin nesting views

“Does not conform to view” means you aren’t putting the right things inside your view

so how can I update text from the conditional, its just changing color to white like its not available

//
//  ContentView.swift
//  MyPets
//
//  Created by Ewa Boer on 24/04/2021.
//

import SwiftUI

struct ContentView: View {
    
    @State var arrayOfStrings:[String]?
    @State var text = " "
    @State var myPets = ["cat", "dog", "panda"]
   
    var body: some View {
        
        VStack {
            
            
            HStack {
                
                Button(action: {
                   arrayOfStrings = nil
                   
                }, label: {
                    /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
                })
                
                Button(action: {
                    for _ in myPets {
                        arrayOfStrings?.append(contentsOf: myPets)
                        
                    }
                    text = "it's ok I have pets"
                },
            label: {
                    /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
                })
               
            }
            Text(text)
            if arrayOfStrings == nil {
                
                text = "tap other button"
            } else {
                
                let nonoptional = arrayOfStrings
                List(nonoptional! , id:\.self) {arrayElement in Text(arrayElement)
                    
                }
            }
            
        }
        
       
        
        
    }
   
   
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


when I had vstacks it was saying too that i can not do it in views

This is where the problem is.

You cannot have an if statement that does not return a “View” of some sort. Change it to this:

if arrayOfStrings == nil {
    Text("tap other button") 
} 

Text() is a view and takes a string parameter.

1 Like

Hi, Thank you, please have a look, errors dissapeared I understand now better the thing about views, however now when I run print check on the second button nothing is appended to the array its jus nil on nil. Thank you it looks bad but im learning a lot from it :slight_smile:

 //
//  ContentView.swift
//  MyPets
//
//  Created by Ewa Boer on 24/04/2021.
//

import SwiftUI

struct ContentView: View {
    
    @State var arrayOfStrings:[String]?
    @State var text = " "
    @State var myPets = ["cat", "dog", "panda"]
    
    var body: some View {
        
        VStack {
            
            
            Button(action: {
                arrayOfStrings = nil
                
            }, label: {
                /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
            })
            
            
            
            Button(action: {
                arrayOfStrings?.append(contentsOf: myPets)
                text = "it's ok I have pets"
                print(arrayOfStrings ?? "there is nothing")
            },
            label: {
                /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
            })
            
            if arrayOfStrings == nil {
                Text("Tap the other button")
            }
          
            
            if  let nonoptional = arrayOfStrings {
                List(nonoptional , id:\.self) {arrayElement in Text(arrayElement)
                    
                }
            }
            
            
            
            
        }
        
        
        
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
}

Hi Ewa,

See the following code which is basically your code but fixed so that it works. Have a look through it. I have added comments to explain what is going on. If there is anything that you do not understand then let me know.

struct ContentView: View {

    @State var arrayOfStrings:[String]?
    @State var text = " "  //  This is populated but is not read so serves no purpose.
    @State var myPets = ["cat", "dog", "panda"]

    var body: some View {

        VStack {

            Button(action: {
                arrayOfStrings = nil
            }, label: {
                Text("Delete Records")
            })

            Button(action: {
                //  Initialise the array to an empty array because you cannot append records to an Optional array that has not been initialised.
                arrayOfStrings = []
                //  Append the contents of myPets
                arrayOfStrings?.append(contentsOf: myPets)
                text = "it's ok I have pets"  //  This line serves no real purpose so should be removed.
                //  This will only print if you run the code on a Simulator.  It does not print in Preview Mode
                print(arrayOfStrings ?? "there is nothing")
            },
            label: {
                Text("Add")
            })

            //  If the arrayOrStrings is nil
            if arrayOfStrings == nil {
                //  then place text on the screen to suggest Adding to the arrayOfStrings
                Text("Tap the other button")
            } else {
                //  Otherwise List the contents of the arrayOfStrings
                //  It is safe to force unwrap since you know at this point that the array contains data.
                List(arrayOfStrings! , id:\.self) { arrayElement in 
                    Text(arrayElement)
                }
            }

            //  This Spacer pushes the elements in the View to the top.
            Spacer()
        }
    }
}
1 Like

thank you, I realise that I did not understand initialising of optional array, I thought once its declared its initialised. I didn’t know i can not append things to non initialised array, I will read about this than bit more. Thank you for your kind help.

No problem. Like I said, if there is anything else that you are not sure about, let me know.

1 Like