After serval hours’ digging in the Contact App, I have figured out how it works.
ABNewPersonViewControlle invoke some class in ToneLibrary framework to do this.
The call stack looks like this:
0 CoreFoundation 0x3359a1d4 CFGetTypeID + 0
1 CoreFoundation 0x33596396 __CFPropertyListIsValidAux + 46
2 CoreFoundation 0x33517090 CFPropertyListCreateData + 124
3 AudioToolbox 0x38ac255a AudioServicesPlaySystemSoundWithVibration + 158
5 ToneLibrary 0x35a7811a -[TLVibrationRecorderView vibrationComponentDidStartForVibrationRecorderTouchSurface:] + 38
6 ToneLibrary 0x35a772b2 -[TLVibrationRecorderTouchSurface touchesBegan:withEvent:] + 342
7 UIKit 0x3610f526 -[UIWindow _sendTouchesForEvent:] + 314
8 UIKit 0x360fc804 -[UIApplication sendEvent:] + 376
After search “AudioServicesPlaySystemSoundWithVibration” on the web , I found nothing.
So I decide to look into it myself. It’s a private function in AudioToolbox framework.
the declaration of the function is like
void AudioServicesPlaySystemSoundWithVibration(SystemSoundID inSystemSoundID,id arg,NSDictionary* vibratePattern)
“inSystemSoundID” is SystemSoundID .just like “AudioServicesPlaySystemSound”, pass “kSystemSoundID_Vibrate”.
“arg” is not important, pass nil to it , everything will still work fine.
“vibratePattern” is a pointer of “NSDictionary”, the Contact App pass into
{
Intensity = 1;
OffDuration = 1;
OnDuration = 10;
} for recording user input.
But only call this function will make a vibration never stop. So I have to found some function to stop it.
The answer is “AudioServicesStopSystemSound”. It’s also a private function in AudioToolbox framework.
the declaration of the function is like
void AudioServicesStopSystemSound(SystemSoundID inSystemSoundID)
I guess the Contact App use AudioServicesPlaySystemSoundWithVibration in touchesBegan method, and AudioServicesStopSystemSound in touchEnd method to reach this effect.
TLVibrationController will manager a vibrate pattern object to record the process you input.
At last it generate a dictionary to pass into AudioServicesPlaySystemSoundWithVibration to replay the whole process like below:
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
NSMutableArray* arr = [NSMutableArray array ];
[arr addObject:[NSNumber numberWithBool:YES]]; //vibrate for 2000ms
[arr addObject:[NSNumber numberWithInt:2000]];
[arr addObject:[NSNumber numberWithBool:NO]]; //stop for 1000ms
[arr addObject:[NSNumber numberWithInt:1000]];
[arr addObject:[NSNumber numberWithBool:YES]]; //vibrate for 1000ms
[arr addObject:[NSNumber numberWithInt:1000]];
[arr addObject:[NSNumber numberWithBool:NO]]; //stop for 500ms
[arr addObject:[NSNumber numberWithInt:500]];
[dict setObject:arr forKey:@"VibePattern"];
[dict setObject:[NSNumber numberWithInt:1] forKey:@"Intensity"];
AudioServicesPlaySystemSoundWithVibration(4095,nil,dict);
So if you want a custom vibrations in iOS. Use AudioServicesPlaySystemSoundWithVibration and AudioServicesStopSystemSound.