トレイトコレクションにアクセスして「forceTouchCapability」を確認しようとしましたが、「forceTouchCapability」はデバイスがiOS9.0以降かどうかを確認するだけです。
つまり、これはiOS 9を搭載したすべてのデバイスで、感圧タッチが「利用可能」であることを意味します。ユーザーデバイス(iPhone 6s)で3D Touchが実際にサポートされているかどうかを確認する方法が必要です。また、ユーザー補助設定で3DTouchオプションが実際に有効になっていることを確認する必要があります。
誤ってforceTouchCapability
をBOOL
にキャストしていました(ブール値を返すように設定されたメソッドへの戻り値として使用していました)。 forceTouchCapability
がUIForceTouchCapabilityAvailable
と等しいかどうかを確認する必要がありました。
の代わりに:
return [[MyView traitCollection] forceTouchCapability];
私は欲しい:
return [[MyView traitCollection] forceTouchCapability] == UIForceTouchCapabilityAvailable;
これをUIViewController
に実装する場合、タイミングが重要になります。 viewDidLoad
をチェックインすると、ライフサイクルの後半でUnknown
が返されるときにAvailable
が返されます。
- (void)traitCollectionDidChange:(nullable UITraitCollection *)previousTraitCollection {
[self checkForForceTouch];
}
- (void)checkForForceTouch {
if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] &&
self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
NSLog(@"Force touch found");
}
}
場合によっては、今すぐforceTouchCapability
値を同期的に保持し、traitCollectionDidChange:
イベントを待ちたくないことがあります。その場合、次のようなかなりばかげた関数を使用できます。
public func forceTouchCapability() -> UIForceTouchCapability {
return UIApplication.sharedApplication().keyWindow?.rootViewController?.traitCollection.forceTouchCapability ?? .Unknown
}
_if ([MyView respondsToSelector:@selector(traitCollection)] &&
[MyView.traitCollection respondsToSelector:@selector(forceTouchCapability)] &&
MyView.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
return YES;
}
_
私のポイントは、iOS 7とiOS 8もサポートしている場合は、[MyView respondsToSelector:@selector(traitCollection)]
と[MyView.traitCollection respondsToSelector:@selector(forceTouchCapability)]
。
最初のチェックを続けると、アプリはiOS 7では正常に動作しますが、iOS8ではクラッシュします。基本的にAppleはiOS8でtraitCollection
プロパティを導入しましたが、iOS9でのみforceTouchCapability
プロパティを追加しました。
fromUITraitCollection.h:
_@property (nonatomic, readonly) UITraitCollection *traitCollection NS_AVAILABLE_IOS(8_0);
@property (nonatomic, readonly) UIForceTouchCapability forceTouchCapability NS_AVAILABLE_IOS(9_0);
_
PS:App Storeでアプリがクラッシュし始めた後、難しい方法でそれを学びました。
Swift4.0および4.1。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Check device supports feature
if self.traitCollection.forceTouchCapability == .available {
// Enable 3D Touch feature here
} else {
// Fall back to other non 3D feature
}
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
// Update the app's 3D Touch support
if self.traitCollection.forceTouchCapability == .available {
// Enable 3D Touch feature here
} else {
// Fall back to other non 3D feature
}
}
}
valentin Sherginに続いて、同期呼び出しが必要な場合はSwift 4.2に更新:
func forceTouchCapability() -> UIForceTouchCapability {
return UIApplication.shared.keyWindow?.rootViewController?.traitCollection.forceTouchCapability ?? .unknown
}
func hasForceTouchCapability() -> Bool {
return forceTouchCapability() == .available
}