Search code examples
swiftuiswift-package-manager

SwiftUI View and Swift Package Manager


I am trying to create a Swift Package that is basically a single SwiftUI View. I have created a sample here to display what is happening. What the packaged does, doesn't matter, I have just included some @State and @Binding variables in the View so that I get the same error I get in my real package. The View struct is this.

import SwiftUI

public struct SampleView: View {
    @Binding var myNum:Int
    @State var fixedText:String = ""
    var myText = ""
    var optional: String?


   public  var body: some View {
        VStack {
            if optional != nil {
                Text(optional!)
            }
            Text(myText)
            Text("Parent number: \(myNum)")
            Text("\(fixedText)")
            Button("Increment num") {
                self.myNum += 1
            }.foregroundColor(.blue)
            Button("Change Parent Text") {
                self.fixedText = "Only Changes Child"
            }.foregroundColor(.blue)
        }.background(Color.red)
            .foregroundColor(.white)
    }
}

When I add the package and import it into one of the views in my project, I should be able to use Do something like this as I can do if the View is not part of a Swift Package:

 SampleView(myNum: $myNum,
             fixedText: parentText,
             myText: "Display Text Passed from parent")

However, I get no code completion and I get the error:

'SampleView' initializer is inaccessible due to 'internal' protection level

I have tried all sorts of initializations on the SampeView struct, but keep getting all sorts of different errors. I just don't understand how to fix the access levels here. Can anyone help? Screenshot is here also. enter image description here


Solution

  • Here is expected declaration in Package (tested with Xcode 11.2.1 / iOS 13.2.2). Please note that @State are not allowed to be used outside of View, so all you need to make in sync should be passed via Binding:

    public struct SampleView: View {
        @Binding var myNum:Int
        @Binding var fixedText:String
        var myText: String
        var optional: String?
    
        public init(myNum: Binding<Int>, fixedText: Binding<String>, 
                    myText: String = "", optional: String? = nil) {
            self._myNum = myNum
            self._fixedText = fixedText
            self.myText = myText
            self.optional = optional
        }
        
        public var body: some View {
            VStack {
                if optional != nil {
                    Text(optional!)
                }
                Text(myText)
                Text("Parent number: \(myNum)")
                Text("\(fixedText)")
                Button("Increment num") {
                    self.myNum += 1
                }.foregroundColor(.blue)
                Button("Change Parent Text") {
                    self.fixedText = "Only Changes Child"
                }.foregroundColor(.blue)
            }.background(Color.red)
                .foregroundColor(.white)
        }
    }
    

    and usage:

    @State private var myNum: Int = 1
    @State private var parentText = "Test"
    var body: some View {
        SampleView(myNum: $myNum,
                   fixedText: $parentText,
                   myText: "Display Text Passed from parent")
    }