20

After user does force touch, I want to vibrate phone just like default behaviour.

Is it haptic? If so, how shall I do?

Amit Verma
  • 40,709
  • 21
  • 93
  • 115
Khant Thu Linn
  • 5,905
  • 7
  • 52
  • 120

5 Answers5

16

Example in Swift (for iPhone 6S)

import AudioToolbox

AudioServicesPlaySystemSound(1519) // Actuate `Peek` feedback (weak boom)
AudioServicesPlaySystemSound(1520) // Actuate `Pop` feedback (strong boom)
AudioServicesPlaySystemSound(1521) // Actuate `Nope` feedback (series of three weak booms)

Just in case - here're examples for iPhone 7/7+.

As for the force touch - you need to detect if it's available first:

func is3dTouchAvailable(traitCollection: UITraitCollection) -> Bool {
    return traitCollection.forceTouchCapability == UIForceTouchCapability.available
}

and then in touch events, it will be available as touch.force

func touchMoved(touch: UITouch, toPoint pos: CGPoint) {
    let location = touch.location(in: self)
    let node = self.atPoint(location)

    //...
    if is3dTouchEnabled {
        bubble.setPressure(pressurePercent: touch.force / touch.maximumPossibleForce)
    } else {
        // ...
    }
}

Here's my blog with a more detailed example with code samples:
http://www.mikitamanko.com/blog/2017/02/01/swift-how-to-use-3d-touch-introduction/

Pang
  • 9,564
  • 146
  • 81
  • 122
Mikita Manko
  • 1,133
  • 9
  • 9
13

Starting with iOS 10, there is a new public API for handling haptic feedback: UIFeedbackGenerator.

let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.success)

It is suggested to call .prepare() before using the generator and sending the feedback as there is a slight delay between the two due to the feedback hardware requiring a "wakeup". This could be done in viewDidLoad() or something comparable if you are expecting the feedback to be given shortly after.

See this blog for a good explanation of the new API and the available feedbacks:
https://www.hackingwithswift.com/example-code/uikit/how-to-generate-haptic-feedback-with-uifeedbackgenerator

For iOS 9 and older, you could use AudioToolBox as outlined in the other posts.

import AudioToolbox

private let isDevice = TARGET_OS_SIMULATOR == 0

func vibrate() {
    if isDevice {
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Frederik Winkelsdorf
  • 4,383
  • 1
  • 34
  • 42
  • 2
    Additional haptic classes in iOS 10: [UIImpactFeedbackGenerator](https://developer.apple.com/documentation/uikit/uiimpactfeedbackgenerator) and [UISelectionFeedbackGenerator](https://developer.apple.com/documentation/uikit/uiselectionfeedbackgenerator) – bendytree Aug 10 '17 at 00:06
  • @bendytree Thanks for adding the new subclasses, I don't always have a look at older posts here :) – Frederik Winkelsdorf Aug 10 '17 at 09:34
6

There are different feedback types. Try each one to figure out what is better for your needs:

// 1, 2, 3
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.error)
generator.notificationOccurred(.success)
generator.notificationOccurred(.warning)

// 4
let generator = UIImpactFeedbackGenerator(style: .light)
generator.impactOccurred()

// 5
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccurred()

// 6
let generator = UIImpactFeedbackGenerator(style: .heavy)
generator.impactOccurred()

// 7
let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()
Pang
  • 9,564
  • 146
  • 81
  • 122
Timur Bernikovich
  • 5,660
  • 4
  • 45
  • 58
1

I think that you are talking about the new Taptic Engine.

From apple.com: iPhone 6s gives you real-time feedback both onscreen and in the form of subtle taps from the Taptic Engine. These responses correspond to how deeply you’re pressing the display, and they let you know what actions you’re performing and what you can expect to happen.

As I know actually there is no public API for that. I've only found this tutorial for implementing the Taptic feedback via private API.

//ATTENTION: This is a private API, if you use this lines of code your app will be rejected

id tapticEngine = [[UIDevice currentDevice] performSelector:NSSelectorFromString(@"_tapticEngine") withObject:nil];
[tapticEngine performSelector:NSSelectorFromString(@"actuateFeedback:") withObject:@(0)];
Pang
  • 9,564
  • 146
  • 81
  • 122
andreacipriani
  • 2,519
  • 26
  • 23
0

You can use custom logic to achieve this:

  • Detect a force applied on the screen by a user, by using force and maximumPossibleForce properties of UITouch class.
  • Depending upon the force amount, you can vibrate device after particular level.

Example:

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];

    UITouch *touch = [touches anyObject];

    CGFloat maximumPossibleForce = touch.maximumPossibleForce;
    CGFloat force = touch.force;
    CGFloat normalizedForce = force/maximumPossibleForce;
    NSLog(@"Normalized force : %f", normalizedForce);

    if (normalizedForce > 0.75)
    {
         NSLog(@"Strong");
        // Vibrate device
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
    }
    else
    {
        NSLog(@"Weak");
    }
}
  • Also, you can try to set different vibration duration for different force level with custom logic.

Example:

// Vibrate device
NSTimer * vibrationTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(vibrateDevice) userInfo:nil repeats:YES];


- (void) vibrateDevice
{
    if(duration == 2) // duration is a public variable to count vibration duration
    {
          // Stop the device vibration
          [vibrationTimer invalidate];
          return;
    }

    duration++;
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Mahesh K
  • 373
  • 2
  • 8