If the version of Xcode changes, the implementation may vary.
See https://forums.swift.org/t/se-0258-property-wrappers-third-review/26399 for a thread on the Property Wrapper.

SwiftUI’s min SDK is iOS13, it is difficult to apply it to existing project.
However, some of techniques needed to implement SwiftUI are included in Swift5.1.
So we can implement similar SwiftUI on UIKit This article show you how to implement binding in MVVM with PropertyWrappers(SE-0258), Rx.

I wrote about (KR)MVVM패턴에 대하여. In that article I mentioned the difficulty of binding. When you use Rx, View is easy to bind but Implementing ViewModel is difficult.
Because all the properties of the ViewModel are Observable, it is difficult to modify or configure the values.
Also If you give property as Subject, View can change Data.
I want to solve problems with PropertyWrapper and Rx.

I used BaseSubject <Element> as the projectedValue to prevent direct access to the internal properties of the SubjectProperty in View.
View only be able to access attributes of ObservableType, ObserverType(BaseSubject).
if there is a change in the PropertyWrapper, it does not receive the event through the didSet in the ViewModel, so we implement it by placing a delegate.

ObservableProperty used Observable because it flows in one direction.

When the value of the property changes, you can receive the event via didChanged and change the value.
If you use _ to access a property, you can access it as a SubjectProperty Type.
If you use $to access a property, you will access it with projectedValue Type. so, the ViewModel has access to all the public interfaces of the SubjectProperty. Finally, you can bind these properties in the Controller. View is accessing properties with$, it can be used as Observer, Observable type.
View can not access its properties as an access level in _.
so You can only expose the interface you want to expose in View.

You can create a ViewModel of the form Properties + Action (Commaned) as above.
Repos, which is a List, uses ObservableProperty because it is a one-way stream.
You can access Observable from the outside, but you can still change the value by accessing [Repo] type inside.

I have seen a simple example that makes it easier to implement bindings with PropertyWrapper.