首先我必须说清楚的是,本文的重点不是讲如何通过Swift实现持续震动这个功能,而是通过实现这个功能来学习在Swift中如何把一个c函数作为另一个函数的参数。之所以选这个功能,也是百度了一下,发现并没有用swift实行的博客(要么语法过时,要么编译不过)。如果仅仅只是关注功能的实现,可以直接拉到底部。
如果你有OC使用经验,一定知道先要注册一个震动的回调:
let temp :UnsafeMutablePointer =nil
AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate,nil,nil,soundCompleteCallback(kSystemSoundID_Vibrate, temp),nil)
然后实现soundCompleteCallback这个回调函数:
上面这段代码的意思就是2秒震动一次,结下来当你使用
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
我们预计的结果是回调到soundCompleteCallback函数,然后2秒后再次震动,然后又回调,2秒后再震动....这样就实现了持续震动。
然而,事实是Xcode会报一个异常:
Cannot convert value of type '()' to expected argument type 'AudioServicesSystemSoundCompletionProc' (aka '@convention(c) (UInt32, UnsafeMutablePointer<()>) -> ()')
大意就是参数不对,我们再看看swift源码
AudioServicesAddSystemSoundCompletion这个函数的第个4个参数是一个继承AudioServicesSystemSoundCompletionProc的c函数,看到这里我也是不得要领,欢迎大神在评论区指点。不过当我用oc那样只传函数名的时候,Xcode给了我一点提示:
A C function pointer can only be formed from a reference to a'func' or a literal closure
回调函数只能是一个指针指向一个C函数
在Swift中你只能通过一个全局函数或闭包(不能值捕获,如果你对swift中的闭包或者值捕获不了解,请参考:swift闭包(中文翻译)),不能使一个实例方法。于是我换成下面这种写法:
用闭包完美解决了这个“2秒一次,持续震动”的问题。但是,对于全局函数这种方式我也尝试了多次,发现始终解决不了。
水平有限,说错了的地方希望大神补充。