Having optional GC but integrated GC does lead to a schism in API libraries (see C#, D, etc.). From my experience it's hard to go no-GC in C# because a lot of libraries depend on GC.
I have been out of C# programming for over a decade now, but in Swift most guidance actually discourage use of classes, while a lot of types in the stdlib use a "Copy on Write" pattern where a struct contains a class that acts as a backing store. This gives the type value semantics but guarantees assignments will be cheap, only when the backing data is modified and the reference count is not unique is the data copied.
In Rust you do so via borrow checker or explicit Rc/Weak wrappers. In Swift you do that via additional weak annotations (strong being the implicit default).
It doesn't care about ownership either. Apart from some Swift specific optimizations iiuc.
Full GC I mentioned is more of mark and sweep variety.
See Reference counting. Note lack of malloc/free.
See this excellent comment: https://news.ycombinator.com/item?id=32277088
You can start here,
https://www.udemy.com/course/essentials-of-garbage-collector...