Property Wrappers exhibit strange behaviour in Playground

After installing the latest Xcode Version 11.7 (11E801a), and stepping through the examples in the Property Wrappers section of the Language Guide at https://docs.swift.org/swift-book/LanguageGuide/Properties.html#ID259.

The code in my playground is as follows:

    @propertyWrapper
struct TwelveOrLess {
    private var number: Int
    init() { self.number = 0 }
    var wrappedValue: Int {
        get { return number }
        set { number = min(newValue, 12) }
    }
}

struct SmallRectangle {
    @TwelveOrLess var height: Int
    @TwelveOrLess var width: Int
}


var rectangle = SmallRectangle()
print(rectangle.height)

The console displays the correct value of "0" indicating that the rectangle instance was initialised correctly.

rectangle.height = 10

// Prints "error: Properties.xcplaygroundpage:355:11: error: 'height' is inaccessible due to 'internal' protection level"

If I re-initialise the rectangle instance the same error is displayed.

However, if I continue to the next part of the example that wraps the properties of SmallRectangle in the TwelveOrLess structure explicitly, instead of writing @TwelveOrLess as an attribute the expected results appear without any other code amendments as follows:

    struct AnotherSmallRectangle {
    private var _height = TwelveOrLess()
    private var _width = TwelveOrLess()
    var height: Int {
        get { return _height.wrappedValue }
        set { _height.wrappedValue = newValue }
    }
    var width: Int {
        get { return _width.wrappedValue }
        set { _width.wrappedValue = newValue }
    }
}

var anotherRectangle = AnotherSmallRectangle()
anotherRectangle.height
print(anotherRectangle.height)

anotherRectangle.height = 10
print(anotherRectangle.height)

anotherRectangle.height = 24
print(anotherRectangle.height)

Why is this happening?

This entire thing runs fine on Playground 3.3.1 both iOS and macOS, and in a single main.swift file on an Xcode (11.7) project:

@propertyWrapper
struct TwelveOrLess {
    private var number: Int
    init() { self.number = 0 }
    var wrappedValue: Int {
        get { return number }
        set { number = min(newValue, 12) }
    }
}

struct SmallRectangle {
    @TwelveOrLess var height: Int
    @TwelveOrLess var width: Int
}

var rectangle = SmallRectangle()
print(rectangle.height)
// Prints "0"

rectangle.height = 10
print(rectangle.height)
// Prints "10"

rectangle.height = 24
print(rectangle.height)
// Prints "12"

Which version of Playground are you using? Do you have other codes than the above mentioned?


PS

You can put code inside triple tick mark:

```
Like this
```

so that it'll be rendered

like this

Thank you for your reply.

The code is currently being run in a playground file within Xcode 11.7. It is very strange that it should be working as described. I will try it in a project now and update you shortly.

The tip about the triple tick marks is very helpful. :wink:

Ok. I can verify that it does work from the command line now that the developer tools directory has been updated... :joy:
Now, I will see if it will work in my Xcode playground file...

Xcode playground still displays the same error as above... Even when the code is in it own playground file.

@propertyWrapper
struct TwelveOrLess {
    private var number: Int
    init() { self.number = 0 }
    var wrappedValue: Int {
        get { return number }
        set { number = min(newValue, 12) }
    }
}

struct SmallRectangle {
    @TwelveOrLess var height: Int
    @TwelveOrLess var width: Int
}

var rectangle = SmallRectangle()
print(rectangle.height)
// Prints "0"

rectangle.height = 10

error: wrappers.playground:24:11: error: 'height' is inaccessible due to 'internal' protection level
rectangle.height = 10
          ^~~~~~

wrappers.playground:16:23: note: 'height' declared here
    @TwelveOrLess var height: Int

I just tried Xcode 11.7 playground (not to be confused with Playground app), it still works fine for me.

A quick clarification, is all of the following correct?

  • This is a macOS playground (you can specify platform when creating playground).
  • There is only one file, with no import, and everything is in that file.
  • You created a new playground, then just added the code above.

Thank you again for your reply.

A new Xcode 11.7 macOS playground file has been created - previously, a new playground page created in the playground file downloaded from the official A Swift Tour was used (it would seem that the official playground file is not created explicitly for macOS since it does not include import Cocoa ).

There is only the one playground file, no additional playground pages, no imports (I removed the import Cocoa that was automatically added), and all of the code is located in this single playground file.

The following screenshot is from the newly created macOS playground file complete with exactly the same error as described previously.

The code is as follows (copied directly from the new file):

struct TwelveOrLess {
    private var number: Int
    init() { self.number = 0 }
    var wrappedValue: Int {
        get { return number }
        set { number = min(newValue, 12) }
    }
}

struct SmallRectangle {
    @TwelveOrLess var height: Int
    @TwelveOrLess var width: Int
}

var rectangle = SmallRectangle()
print(rectangle.height)
// Prints "0"

I have also tried the same code from the command line using a separate main.swift file as in the following screenshot.

Executing this file from the command line with the command:
swift main.swift
produces the expected results as shown in the screenshot below.

Screenshot 2020-09-09 at 10.57.52
It is as though there are different compilers for each method (Xcode, Xcode playground, and REPL)... It would be nice to understand why the code refuses to cooperate in playgrounds (on my Mac) but, it is good to know that if the code should work (logically) and it doesn't in Xcode, that a sanity check can be done from Terminal. :exploding_head:

Good that you now know it should work. :innocent:

*Scratch Head* hmm, it does look like a bug. I'd suggest that you report it. Since this is Xcode, it should be over https://feedbackassistant.apple.com/. Though I can't even replicate it, so I don't know how effective it'll be.