Search code examples
swift-playgroundswift5ipad-playgrounds

How to change struct properties in Swift


I’m trying out Swift playgrounds and I cannot find a way to change value of a struct. Below I want to change properties of Shadow from default values.

I’ve tried the initialiser and dot syntax but I get ‘field is inaccessible due to internal protection level.

let circle = Circle()
circle.draggable = true
//var shadow = Shadow(color: #colorLiteral(red: 0.9529411764705882, green: 0.6862745098039216, blue: 0.13333333333333333, alpha: 1.0), offset: Point(3,-3), blurRadius: 5, opacity: 1)
var shadow = Shadow()
shadow.color = .red
circle.dropShadow = shadow

Solution

  • You’re apparently using the “Shapes” playground.

    So, view the source by clicking on “...” » “Advanced” » “View Auxiliary Source Files” » “Contents” » “Modules” » “Book.playgroundmodule” » “Sources” » “PlaygroundAPI”.

    If you look at the Shadow struct, none of those properties are declared as public. That means that you don’t have access to them outside of that module.

    In contrast, if you look at the Circle declaration in contrast, radius is public. And if you look at AbstractDrawable, dropShadow is public, too.

    In the absence of an explicit access qualifier (e.g., public), a property gets the internal access qualifier, only accessible within that module. (See The Swift Programming Language: Access Control.) And your code in that playground is not within the same module as where Shadow was defined. Thus you don’t have access to it.

    So, bottom line, your warning is just telling you that you cannot access this internal property of the Shadow struct.


    This begs the question as to why they declared Shadow such that you can’t customize the nature of the shadow. I suspect it is just an oversight on their part. For example, I opened up this playground workbook in Xcode and replaced the init method for Shadow with the following:

    public init(offset: Point = Point(x: 1, y: -1), blurRadius: Double = 1, opacity: Double = 0.3, color: Color = .black) {
        self.offset = offset
        self.blurRadius = blurRadius
        self.opacity = opacity
        self.color = color
    }
    

    Then I could reopen this playground on my iPad and do things like:

    let circle = Circle(radius: 30)
    circle.dropShadow = Shadow(opacity: 0.9, color: .green)
    

    And that yielded:

    big circle green shadow