maximumPossibleForce in 3D Touch

I am using force property to enable 3D Touch functionality on iPhone 6S. Everything is working fine so far, but I am not sure about maximumPossibleForce.


I understand its purpose. However, since the value is passed as an extra property of UITouch and not like lets say a constant or UITraitCollection param.

I was wondering why it is defined like that. The fact it is returned per touch suggests it can change per touch. Is it just an inconsistency in the API or it is a deliberate and there is a purpose why it is returned per UITouch?


Is it likely that certain touches can return a different value of maximumPossibleForce thorough the lifetime of my app? Should I be checking it constantly everytime I process a touch event, or I can assume it will always be 6.67 (or whatever I read when processing the first touch).


Also is it likely that this is device specific things? I mean different devices will have different maximumPossibleForce?

Accepted Reply

For any given source of a touch, the maximumPossibleForce remains the same for all touches produced by that souce. However, there currently exist 2 sources of force for a touch – the screens built into the iPhone 6S and 6S Plus, and the Apple Pencil. These two devices have different maximumPossibleForce values simply due to the different limits of the hardware.


As such, the value of maximumPossibleForce (along with other touch properties) is primarily for you to determine the general capabilities of the hardware as it is messaging you. It is unfortunate that you need to wait for a touch to get this information, and we are aware of how that can make coding around that akward.

Replies

3D Touch capability is defined in the UITraitCollection class for easy checking if the system (or your app) has 3D Touch enabled, or if the phone even supports it.


The UITraitCollection only is meant to store information such as screen size, and screen options (for now, just 3D Touch capability). It wasn't designed to hold the constants of system features.


maximumPossibleForce doesn't really do anything, the only real use for it is to know the percentage of how hard the user is touching. It makes more sense to call

touch.force/touch.maximumPossibleForce

than

touch.force/self.view.traitCollection.maximumPossibleForce


I assume maximumPossibleForce can in fact change, because you can change the amount of force required to interact with 3D Touch in Settings > General > Accessibility > 3D Touch.


Simply a design choice it seems. The trait collection will give you the bool as to whether you should even listen to 3D Touch events at viewDidLoad time, and then each touch will tell you the maximum force to look for since that can change on a user's whim

For any given source of a touch, the maximumPossibleForce remains the same for all touches produced by that souce. However, there currently exist 2 sources of force for a touch – the screens built into the iPhone 6S and 6S Plus, and the Apple Pencil. These two devices have different maximumPossibleForce values simply due to the different limits of the hardware.


As such, the value of maximumPossibleForce (along with other touch properties) is primarily for you to determine the general capabilities of the hardware as it is messaging you. It is unfortunate that you need to wait for a touch to get this information, and we are aware of how that can make coding around that akward.

In general you should not normalize the touch force by dividing touch.force by touch.maximumPossibleForce. The primary reason for this is that touch.force is already a normalized value, where touch.force == 1.0 is the force of a typical touch.


If you renormalize the touch force by dividing it by its maximum possible value, then you are going to make any functionality you base on that value require different levels of "normal" force based on the hardware producing the force value. For example, if a future device increased the maximumPossibleForce to 12, and you used a threshold of "0.5" based on your re-normalized touch value, then now a user has to press nearly twice as hard to activate the same functionality as they did on previous hardware.


Instead you would define your feature to require a force of "3", and we would calibrate the value of touch.force such that its approximately the same value accross all devices.

This actually seemed to work fine for iPhones in iOS 9, in the sense that you could simply allocate a new `UITouch` independent of everything else, and its `maximumPossibleForce` value was appropriately set to 6.67. I'm not sure if it behaved the same way on an iPad with the Pencil, but it seems to have changed in the iOS 10 betas, which is now breaking an app that I've been working on 😟