'CircularProgressView' initializer is inaccessible due to 'internal' protection level when calling my package

Viewed 1297

Im making a swiftUI package which can be found here

public struct CircularProgressView: View {
    
    var count: Int
    var total: Int
    var progress: CGFloat
    
    var fontOne: Font = Font.system(size: 75, weight: .bold, design: .rounded)
    var fontTwo: Font = Font.system(size: 25, weight: .bold, design: .rounded)

    var colorOne: Color = Color.primary
    var colorTwo: Color = Color.gray

    var fill = LinearGradient(gradient: Gradient(colors: [Color.green, Color.blue]), startPoint: .top, endPoint: .bottom)
    var lineWidth: CGFloat = 25.0
    
    public var body: some View {
        ZStack{
            Circle()
                .stroke(lineWidth: lineWidth)
                .opacity(0.3)
                .foregroundColor(Color.secondary)
            
            Circle()
                .trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
                .stroke(fill ,style: StrokeStyle(lineWidth: lineWidth, lineCap: .round, lineJoin: .round))
                .rotationEffect(Angle(degrees: 270.0))
                .animation(.linear, value: progress)

            VStack {
                Text("\(count)")
                    .font(fontOne)
                    .foregroundColor(colorOne)
                Text("/ \(total)")
                    .font(fontTwo)
                    .foregroundColor(colorTwo)
            }
        }
    }
}

Note the variables like FontOne and fill are meant to be optional parameters with a default value.

Here is the code for the view I'm trying to share in the package. My test case is successful and I tested it with this code

import XCTest
@testable import CircularProgress

import SwiftUI

final class CircularProgressTests: XCTestCase {
    func testExample() {
        let item = CircularProgressView(count: 5, total: 10, progress: 0.5)
        XCTAssertEqual(item.progress, 0.5)
    }

    static var allTests = [
        ("testExample", testExample),
    ]
}

I added the package to a test project however when I try to do the following

import SwiftUI
import CircularProgress

struct ContentView: View {
    var body: some View {
        CircularProgressView(count: 5, total: 10, progress: 0.5)
            .padding()
    }
}

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

I get an error at CircularProgressView(count: 5, total: 10, progress: 0.5). The error I get is "'CircularProgressView' initializer is inaccessible due to 'internal' protection level"

This is my first package and i'm not sure what I'm doing wrong.

Note: if you are going to import the package to test, use the main branch, the commit with the 1.0.0 tag is an older version.

1 Answers

In your CircularProgressView you need to define your own initialiser as the compiler cannot synthesize it. Something like this should do it:

public struct CircularProgressView: View {
    
    var count: Int
    var total: Int
    var progress: CGFloat

    // add the following to your CircularProgressView
    public init (count: Int, total: Int, progress: CGFloat) {
        self.count = count
        self.total = total
        self.progress = progress
    }

     // rest of code here
}

Update for initialiser with default parameters

If you have other parameters that you wish to be optional you can do so by setting the initialiser to have default values for the optional parameters. It can be done in the following way:

public struct CircularProgressView: View {

    var count: Int
    var total: Int
    var progress: CGFloat

    var fontOne: Font
    var fontTwo: Font

    var colorOne: Color
    var colorTwo: Color

    var fill: LinearGradient
    var lineWidth: CGFloat

    public init(count: Int,
                total: Int,
                progress: CGFloat,
                fontOne: Font = Font.system(size: 75, weight: .bold, design: .rounded),
                fontTwo: Font = Font.system(size: 25, weight: .bold, design: .rounded),
                colorOne: Color = Color.primary,
                colorTwo: Color = Color.gray,
                fill: LinearGradient = LinearGradient(gradient: Gradient(colors: [Color.green, Color.blue]), startPoint: .top, endPoint: .bottom),
                lineWidth: CGFloat = 25.0) {

        self.count = count
        self.total = total
        self.progress = progress
        self.fontOne = fontOne
        self.fontTwo = fontTwo
        self.colorOne = colorOne
        self.colorTwo = colorTwo
        self.fill = fill
        self.lineWidth = lineWidth
    }

    // remainder of code
}

This basically sets all your default values so you don't actually need to set them in your struct.

It also means that you don't need the first initialiser as this initialiser covers that case.

You can then use it like this:

CircularProgressView(count: 5, total: 6, progress: 0.7)
CircularProgressView(count: 5, total: 6, progress: 0.7, colorTwo: Color.red, lineWidth: 6)

Passing in only the parameters that you want to use, but obviously including the required parameters count, total, and progress.

Related