When directly accessing the instance variable (the storage location) there is no way other code can be notified of this change and do something about this. Using the property (using the dot syntax) is nothing more than a message send to the setter.
self.carSpeed = speed;
is exactly the same as
[self setCarSpeed: speed];
For once this enables automatic KVO to work, observers for this property will be notified that it changed.
Also since this is a regular message send the regular message dispatch happens. So you can override the setter in a subclass to change it’s behavior. Or you can change the implementation of the getter and setter to use some other kind of storage for the value instead of an instance variable without having to change any code that needs to change or read that property value.
Before we had ARC another important reason to use the accessors everywhere was that they are supposed to take care of memory management.