9 Replies
      Latest reply on Mar 26, 2020 6:53 AM by Lantua
      bobandsee Level 1 Level 1 (0 points)

        Hi,

         

        I have a problem with passing arguments over to a View when calling it. I have this View

         

        struct GoodsItemFilterView: View {
          @Environment(\.presentationMode) var presentationMode
          @EnvironmentObject private var goodsItemFilter: GoodsItemFilter
        
          @State var ref1Array: [String] = []
          @State var ref2Array: [String] = []
          @State var ref3Array: [String] = []
        
        ...
        

         

        and when I call it I can pass over the values of the arrays as arguments:

         

        GoodsItemFilterView(ref1Array: ["MAX100", "MAX101", "MAX102"], ref2Array: ["REF2_100", "REF2_101"], ref3Array: ["REF3_100", "REF3_101"])

        Now I have another view which is basically a copy of this one with a few changed names etc

         

        struct OrderHeaderFilterView: View {
          @Environment(\.presentationMode) var presentationMode
          @EnvironmentObject var settingStore: SettingStore
          @EnvironmentObject private var itemFilter: WarehouseOrderFilter
        
          @State var orderTypeArray: [String] = []
          @State var carrierArray: [String] = []
        
        ...
        

         

        and when I call it, it is not prompting me to pass over the arrays as arguments:

         

        OrderHeaderFilterView()

         

        What is the difference between those 2 views that the one is asking for arguments on initilization and the other one isn't? To be clear, in the end I want to pass over the arguments, so GoodsItemFilterView() is doing exactly what I need.

         

        Max

        • Re: Passing arguments over to View is not always available
          Claude31 Level 8 Level 8 (9,145 points)

          Difference is that

            @EnvironmentObject var settingStore: SettingStore

          is not private.

            • Re: Passing arguments over to View is not always available
              bobandsee Level 1 Level 1 (0 points)

              Ok, I have changed it to

               

              struct OrderHeaderFilterView: View {
                @Environment(\.presentationMode) var presentationMode
              
                @EnvironmentObject private var itemFilter: WarehouseOrderFilter
                @EnvironmentObject private var settingStore: SettingStore
              
                @State var orderTypeArray: [String] = []
                @State var carrierArray: [String] = []
              
              ...
              

               

              but the result is still the same. When I try something like

               

              OrderHeaderFilterView(orderTypeArray: [])

               

              I get

               

              "Argument passed to call that takes no arguments" as error.

               

              What difference does it make whether that environment object is private or not to the arguments?

                • Re: Passing arguments over to View is not always available
                  OOPer Level 8 Level 8 (6,115 points)

                  As far as I tried with your code (with or without `private`),

                  this

                      OrderHeaderFilterView(orderTypeArray: [])

                  compiles without error.

                   

                  Something in the hidden parts of your code may be affecting.

                  Please show full code to reproduce the same issue.

                    • Re: Passing arguments over to View is not always available
                      bobandsee Level 1 Level 1 (0 points)

                      Hi,

                       

                      Below the two files

                       

                      //
                      //  GoodsItemFilter.swift
                      //  WMS Toolbox
                      //
                      //  Created by Max on 2020-02-05.
                      //  Copyright © 2020 Max. All rights reserved.
                      //
                      
                      import SwiftUI
                      
                      struct GoodsItemFilterView: View {
                        @Environment(\.presentationMode) var presentationMode
                      
                        @State var ref1Array: [String] = []
                        @State var ref2Array: [String] = []
                        @State var ref3Array: [String] = []
                      
                        @State var stockStatusArray: [String] = []
                        @State var zoneArray: [String] = []
                      
                        @State var selectorRef1 = 0
                        @State var selectorRef2 = 0
                        @State var selectorRef3 = 0
                        @State var selectorStockStatus = 0
                        @State var selectorZone = 0
                      
                        var body: some View {
                        NavigationView {
                        Form{
                        Section(header: Text("Zone"), content: {
                        Picker(selection: $selectorZone, label:
                        Text("Zone")) {
                        ForEach(0 ..< zoneArray.count, id:\.self) {
                        Text(self.zoneArray[$0])
                        }
                        }
                        })
                      
                        Section(header: Text("References"), content: {
                        Picker(selection: $selectorRef1, label:
                        Text("Reference 1")) {
                        ForEach(0 ..< ref1Array.count, id:\.self) {
                        Text(self.ref1Array[$0])
                        }
                        }
                      
                        Picker(selection: $selectorRef2, label:
                        Text("Reference 2")) {
                        ForEach(0 ..< ref2Array.count, id:\.self) {
                        Text(self.ref2Array[$0])
                        }
                        }
                      
                        Picker(selection: $selectorRef3, label:
                        Text("Reference 3")) {
                        ForEach(0 ..< ref3Array.count, id:\.self) {
                        Text(self.ref3Array[$0])
                        }
                        }
                        })
                      
                        Section(header: Text("Status"), content: {
                        Picker(selection: $selectorStockStatus, label:
                        Text("Condition")) {
                        ForEach(0 ..< stockStatusArray.count, id:\.self) {
                        Text(self.stockStatusArray[$0])
                        }
                        }
                        })
                      
                        Button(action: {
                        self.selectorZone = 0
                        self.selectorRef1 = 0
                        self.selectorRef2 = 0
                        self.selectorRef3 = 0
                        self.selectorStockStatus = 0
                        }, label: {
                        HStack(){
                        Spacer()
                        Image(systemName: "return")
                        Text("Reset filters")
                        Spacer()
                        }
                      
                        })
                      
                        }.navigationBarTitle("Filter")
                        .navigationBarItems(leading: (
                        Button(action: {
                        self.presentationMode.wrappedValue.dismiss()
                        }, label: {
                        Text("Cancel")
                        }
                        )
                        ), trailing: (
                        Button(action: {
                      
                        self.presentationMode.wrappedValue.dismiss()
                        }, label: {
                        Text("Done")
                        }
                        )
                        ))
                        }.onAppear{
                        self.ref1Array.insert("***ALL***", at: 0)
                        self.ref2Array.insert("***ALL***", at: 0)
                        self.ref3Array.insert("***ALL***", at: 0)
                      
                        self.stockStatusArray.insert("***ALL***", at: 0)
                        self.zoneArray.insert("***ALL***", at: 0)
                      
                      
                        }
                        }
                      }
                      
                      struct GoodsItemFilter_Previews: PreviewProvider {
                        static var previews: some View {
                        GoodsItemFilterView(ref1Array: ["MAX100", "MAX101", "MAX102"], ref2Array: ["REF2_100", "REF2_101"], ref3Array: ["REF3_100", "REF3_101"])
                        }
                      }
                      
                      

                       

                       

                      //
                      //  OrderHeaderFilter.swift
                      //  WMS Toolbox
                      //
                      //  Created by Max on 2020-01-24.
                      //  Copyright © 2020 Max. All rights reserved.
                      //
                      
                      import SwiftUI
                      //import Combine
                      
                      struct OrderHeaderFilterView: View {
                        @Environment(\.presentationMode) var presentationMode
                      
                        @State var orderTypeArray: [String] = []
                        @State var carrierArray: [String] = []
                      
                        @State var fromStatus2 = UserDefaults.standard.string(forKey: "view.orderHeaderFilter.fromStatus")
                        // @State private var fromStatus2 = "040"
                      
                        @State private var direction = ""
                        @State private var fromStatus = ""
                        @State private var toStatus = ""
                        @State private var orderType = ""
                      
                      
                        @State var selectorOrderType = 0
                        @State var selectorCarrier = 0
                      
                        @State private var selectorIndex = 1
                        @State private var fromStatusSelectorIndex = 6
                        @State private var toStatusSelectorIndex = 2
                      
                        @State private var directions = ["Inbound","Outbound","Both"]
                      
                        private var orderStatusFromArray: [String] = ["005", "010", "022", "025", "030", "035", "040", "045", "046", "047", "060"]
                        private var orderStatusToArray: [String] = ["005", "010", "022", "025", "030", "035", "040", "045", "046", "047", "060"]
                      
                        @State var orderStatus = OrderStatus.s05
                      
                        enum OrderStatus: String, CaseIterable, Identifiable {
                        case s05 = "005"
                        case s10 = "010"
                        case s22 = "022"
                        case s25 = "025"
                        case s30 = "030"
                        case s35 = "035"
                        case s40 = "040"
                        case s45 = "045"
                        case s46 = "046"
                        case s60 = "060"
                      
                        var id: String { rawValue }
                        }
                      
                      
                      
                      
                        enum Direction: String, CaseIterable{
                        case outbound = "1"
                        case inbound = "2"
                        case both = "3"
                      
                        init(type: String) {
                        switch type {
                        case "1": self = .outbound
                        case "2": self = .inbound
                        case "3": self = .both
                        default: self = .both
                        }
                        }
                      
                        var text: String {
                        switch self {
                        case .outbound: return "Outbound"
                        case .inbound: return "Inbound"
                        case .both: return "Both"
                        }
                        }
                        }
                      
                        init(){
                        //nothing here
                        }
                      
                        var body: some View {
                      
                        return NavigationView{
                        Form{
                        HStack{
                        Text("Direction")
                        Spacer()
                        Picker(selection: $direction, label:
                        Text("Direction")) {
                        ForEach(directions, id:\.self) {
                        status in
                        Text(status)
                        }
                        }
                        .pickerStyle(SegmentedPickerStyle())
                        }
                      
                        Picker(selection: $fromStatus, label:
                        Text("From Status")) {
                        ForEach(orderStatusFromArray, id:\.self) {
                        status in
                        Text(status)
                        }
                        }
                      
                        Picker(selection: $toStatus, label:
                        Text("To Status")) {
                        ForEach(orderStatusFromArray, id:\.self) {
                        status in
                        Text(status)
                        }
                        }
                      
                        }.navigationBarTitle("Filter")
                        .navigationBarItems(leading: (
                        Button(action: {
                        self.presentationMode.wrappedValue.dismiss()
                        }, label: {
                        Text("Cancel")
                        }
                        )
                        ), trailing: (
                        Button(action: {
                      
                      
                        self.presentationMode.wrappedValue.dismiss()
                        }, label: {
                        Text("Done")
                        }
                        )
                        ))
                      
                        }.onAppear{
                      
                        self.direction = UserDefaults.standard.string(forKey: "view.orderHeaderFilter.direction")!
                        self.fromStatus = UserDefaults.standard.string(forKey: "view.orderHeaderFilter.fromStatus")!
                        self.toStatus = UserDefaults.standard.string(forKey: "view.orderHeaderFilter.toStatus")!
                      
                        self.orderTypeArray.insert("***ALL***", at: 0)
                        self.carrierArray.insert("***ALL***", at: 0)
                      
                      
                      
                        }
                        }
                      }
                      
                      struct OrderHeaderFilter_Previews: PreviewProvider {
                        static var previews: some View {
                        OrderHeaderFilterView()
                        }
                      }
                      
                      
                • Re: Passing arguments over to View is not always available
                  Lantua Level 1 Level 1 (0 points)

                  `ref1Array` has default argument `= []`. That's why you don't need to supply argument.

                  Also, initializing `@State` only works the first, the next time you access the view, it'll retain the old state, even if you supply different argument.

                  If that's not what you want, use normal `let` instead.

                  • Re: Passing arguments over to View is not always available
                    bobandsee Level 1 Level 1 (0 points)

                    Found the issue(s):

                    I had this piece in the code

                    init(){ //nothing here }

                    This needs to be removed, otherwise it will not ask for any variables.

                    The other issue is the one I don't understand:

                    private var orderStatusFromArray: [String] = ["005", "010", "022", "025", "030", "035", "040", "045", "046", "047", "060"]
                    private var orderStatusToArray: [String] = ["005", "010", "022", "025", "030", "035", "040", "045", "046", "047", "060"]

                    If I change the var to let, it works as expected. Another option is to remove the private at the beginning. So it looks like as soon as you have a

                    private var ...

                    in your code, all arguments become private. Maybe I am missing something here but that seems like a bug to me.

                      • Re: Passing arguments over to View is not always available
                        Lantua Level 1 Level 1 (0 points)

                        Right, if you have implemented initializers, Swift will not generate member-wise one for you (which also answers your previous response, so I'm not gonna reply to that).

                        Also, the arguments in the memberwise follow initializer follows the variable's access control. If you have private variable, you can only specify it with private initializer, not from different file.

                         

                        Could you also elaborate the "work as expected" version? If you change var to let, you can't supply it as an argument, which iirc, is not what you want.


                        PS

                         

                        I'd suggest that you try to make the code as small as possible when asking. It's not easy looking through 300+ lines of code just to reply to a forum, especially when a large part of them is irrelevant. Like this one, the only important thing is that you don't have the initializer you want. You may want to create new playground to experiment the rule surrounding initializer using a mock class (like Foo). You may even figure it out on your own by doing that. And if your question pertains only the swift language, not particular framework, you may want to try http://forums.swift.org