BlueTurtle
BlueTurtle

Reputation: 383

Argument passed to call that takes no arguments when using init() method

I am trying to assign default values to the pickers. Initially I am finding the index that matches a string ("Tesco") but when this works I will replace the string with the product.product_name that is passed into the ProductDetail struct. If I remove the init() method (and uncomment the relevant variables) then the error disappears and it works as normal. I have tried moving the var product = Product_ declaration into the init() but that causes different errors. I feel I am just trying every combination without knowing why they aren't working. I am sure at some point it'll work but I won't know why.

I am getting a Argument passed to call that takes no arguments. Error occurs in the ProductDetail_Previews struct.

struct ProductDetail: View {
    // Define product as a constant that takes on the values for one specific product
    var product: Product_
    
    // Define a constant for the available brands
    //let all_brands = ["Asda", "Tesco", "Sainsbury's", "M&S"]
    
    
    @State var all_brands: [String]
    //State var currentBrand = 2
    @State var currentBrand: Int

    init(){
        self.all_brands = ["Asda", "Tesco", "Sainsbury's", "M&S"]
        
        // Find the first index in the list of all_brands where the string is present
        self.currentBrand = all_brands.firstIndex(of: "Tesco") ?? 0

    }
        
    var body: some View {
        
        
        //This is the main stack that contains everything
        VStack(alignment: .leading){
                        
        //Create a form to hold the Picker(s)
        Form{
        Text(product.product_name)
            .fontWeight(.bold)
            .font(.title)
            .padding()
            
        HStack{
        Text("EAN Code:")
        Text(product.code).padding()
              }
            
        // Picker for Brand
        Picker(selection: $currentBrand, label: Text("Brand")){
            ForEach(0 ..< all_brands.count){
                Text(self.all_brands[$0])
            }}
                            }
               }
}
        }//Closing bracket for main VStack
    


struct ProductDetail_Previews: PreviewProvider {

    static var previews: some View {
        ProductDetail(product: products[2])
    }
}

Thanks.

Upvotes: 0

Views: 271

Answers (2)

vadian
vadian

Reputation: 285270

There is an inconsistency. The init method takes no arguments (that's what the error says) but product is not being initialized.

As the initial values of the @State variables are constants anyway and you cannot initialize @State properties this way I'd recommend to omit the init method and assign the values literally.

struct ProductDetail: View {
    // Define product as a constant that takes on the values for one specific product
    var product: Product_
    
    @State private var all_brands = ["Asda", "Tesco", "Sainsbury's", "M&S"]
    @State private var currentBrand = 1

    var body: some View { ...

And please stop using those underscore characters and snake_case names. That's pretty unswifty

Upvotes: 1

David Pasztor
David Pasztor

Reputation: 54785

Your initialiser is wrong, it should take a Product input argument.

When initialising a State based on input arguments, you need to assign to the State property by accessing it using the _ prefix and assigning State(initialValue:).

struct ProductDetail: View {
    private let product: Product
    
    
    @State private var allBrands: [String]
    //State var currentBrand = 2
    @State private var currentBrand: Int

    init(product: Product) {
        self.product = product
        let brands = ["Asda", "Tesco", "Sainsbury's", "M&S"]
        self._allBrands = State(initialValue: brands)

        // Find the first index in the list of all_brands where the string is present
        self._currentBrand = State(initialValue: brands.firstIndex(of: "Tesco") ?? 0)
}

Unrelated to your question, but all @States should be declared as private, since they should never be mutated from outside the view. Also, you should conform to the Swift naming convention, which is lowerCamelCase for variable names and UpperCamelCase for type names.

Upvotes: 2

Related Questions