Beginner question about Circles (SwiftUI)

Hello,

First off, not sure if this is the right place to post this question. I'm a newbie to Swift/iOS programming, but have some experience with other languages (Java, C/C++, etc.). If somebody could direct me to newbie resources, that would be awesome!!

I'm having some trouble understanding the Circle class and just class properties in general... say I have a view like so:

struct SunriseGraphic: View {
    var body: some View {
        Circle()
            .stroke(Color.orange, lineWidth: 4)
            .shadow(radius:10)
    }
}

This creates a circle with an orange border and a light shadow. Now if I want to add color to the center of the circle, I'm not sure what to do. I tried using .foregroundColor(.red) but nothing shows up. If I try adding this directly after the Circle() call, the other properties don't seem to be recognized anymore and I get the following errors:

Value of type 'some View' has no member 'stroke'

Protocol type 'Any' cannot conform to 'View because only concrete types can conform to protocols
Value of type 'Any' has no member 'shadow'
Cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members

I'm clearly doing something wrong and it's probably very simple but I'm not sure what to do. I tried looking at the Circle class in the Swift Developer docs provided by Apple but there doesn't seem to be much information.

I maybe wrong (Iā€™m not that familiar with SwiftUI), but a quick look at the docs for Circle shows that it conforms to the Shape protocol.

The Shape protocol has a function fill() which sounds like it maybe what you need. Incidentally, this is where the stroke() function is defined as well.

This is an example of Protocol Oriented Programming, which is a popular concept in Swift.

Shape Protocol docs

2 Likes

You are not wrong, Apple's API is wrong :laughing: :laughing: I'm kidding (or maybe not).

Circle is a Shape, you can do either stroke or fill to a Shape. But not both as you want to do. So the work around is to create two circles lay one on top of the other, apply stroke on one and fill on the other. I say Apple's API is wrong because why not allow both stroke and fill on a Shape?

You can see the solution here:

1 Like

There's a subtle, but important distinction between View and Shape.

  • View is something that you can draw onto the screen.
  • Shape distinguishes inside and outside.

Shape does draw onto the screen using a simple algorithm: fill everything inside with the foreground colour. That's why it also conforms to View.

You can do many things to Shape, offsetting them, transforming them around, etc. Many of these still retain the Shapeness of the data, a rotated Shape can still tell inside/outside and only that.

Now, if you're telling Circle to make an orange stroke of width 4, the object starts to concern much more than inside/outside, especially the orange part. It starts to become View. The same goes with filling, the object ceases to be Shape and become just View. View doesn't know how to do .stroke (it doesn't have concept of border) hence the error

Value of type 'some View' has no member 'stroke'

Anyhow, as @young suggest, you draw two Circles, one for filling, one for stroke.

1 Like

Can Shape do:

strokeAndFill(...) -> some View

adding all the permutation of stroke x fill?

It seems strokeAndFill is a common need. Why not having it on Shape?

1 Like

We'll probably need to wait for an authoritative answer.

Someone can probably file a request. Though this

somewhat concerns me.

1 Like

We do encourage questions like this that are strictly about using Apple frameworks to be asked at the Apple developer forums.

2 Likes

You are 100% right. Creating all permutations of strokAndFill(...) is a stupid idea, which makes me wonder why stroke(...) and fill(...) return some View? Why not return some kind of Shape like offset, scale or rotate?

1 Like

The Shape's main job isn't really to draw, and filling already goes well beyond that. The difference between orange Circle and red Circle would be questionable when used for hit-testing or clipping.

1 Like

Wow, this is excellent feedback! Thank you for the insight everybody. Lots more for me to learn. I'll post further questions on the Apple developer forums.