First of all, reference counting only happens for values of class type, plus closures and probably things I don't know about. Though, since copying a struct copies its fields, copying a struct containing a class-typed field will also produce reference counting; that includes String, Array, and Dictionary.
But also, shared mutability only exists for fields of classes (regardless of the field's type). When Swift decides to pass structs by pointer, those pointers are shared xor writable, similar to Rust; so if you have a pointer to a struct containing a string, the compiler can assume the string will stay untouched even if you run some arbitrary other code (as long as you don't mutate it yourself). Of course, unlike Rust, Swift doesn't let the programmer decide whether to pass structs by pointer or value (even with `inout`/`mutating` it's not guaranteed to use a pointer)...
Swift does it with all fields. (Unless by “class” you really meant “any of Swift’s aggregate types, including structs”.) For many value types Swift will actually provide CoW for you.