我們經(jīng)常將一個(gè)函數(shù)作為參數(shù)傳入另一個(gè)函數(shù)钞护。
那么在iOS上能作為一個(gè)函數(shù)參數(shù)的東西有哪些呢
- c的函數(shù)指針
- oc的block
- swift的閉包(closures)
ok回歸正題,先說(shuō)下@convention是干什么的。
他是用來(lái)修飾閉包的捂敌。他后面需要跟一個(gè)參數(shù):
- @convention(swift) : 表明這個(gè)是一個(gè)swift的閉包
- @convention(block) :表明這個(gè)是一個(gè)兼容oc的block的閉包
- @convention(c) : 表明這個(gè)是兼容c的函數(shù)指針的閉包轰胁。
class Person:NSObject {
func doAction(action: @convention(swift) (String)->Void, arg:String){
action(arg)
}
}
let saySomething_c : @convention(c) (String)->Void = {
print("i said: \($0)")
}
let saySomething_oc : @convention(block) (String)->Void = {
print("i said: \($0)")
}
let saySomething_swift : @convention(swift) (String)->Void = {
print("i said: \($0)")
}
let person = Person()
person.doAction(action: saySomething_c, arg: "helloworld")
person.doAction(action: saySomething_oc, arg: "helloworld")
person.doAction(action: saySomething_swift, arg: "helloworld")
為啥今天要寫這個(gè)呢?因?yàn)槲以谟胷untime的imp_implementationWithBlock這個(gè)函數(shù)時(shí)不知道咋傳參數(shù)如绸。我用swift的閉包怎么都不對(duì)嘱朽,看完@convention之后就知道該怎么辦了。
class Person:NSObject {
//數(shù) 數(shù)字
dynamic func countNumber(toValue:Int){
for value in 0...toValue{
print(value)
}
}
}
//現(xiàn)在我們要替換數(shù)數(shù)函數(shù)的實(shí)現(xiàn)怔接,給他之前和之后加上點(diǎn)廣告語(yǔ)搪泳。
//拿到method
let methond = class_getInstanceMethod(Person.self, #selector(Person.countNumber(toValue:)))
//通過(guò)method拿到imp, imp實(shí)際上就是一個(gè)函數(shù)指針
let oldImp = method_getImplementation(methond!)
//由于IMP是函數(shù)指針扼脐,所以接收時(shí)需要指定@convention(c)
typealias Imp = @convention(c) (Person,Selector,NSNumber)->Void
//將函數(shù)指針強(qiáng)轉(zhuǎn)為兼容函數(shù)指針的閉包
let oldImpBlock = unsafeBitCast(oldImp!, to: Imp.self)
//imp_implementationWithBlock的參數(shù)需要的是一個(gè)oc的block岸军,所以需要指定convention(block)
let newFunc:@convention(block) (Person, NSNumber)->Void = {
(sself, toValue) in
print("數(shù)之前, 祝大家新年快樂(lè)")
oldImpBlock(sself, #selector(Person.countNumber(toValue:)), toValue)
print("數(shù)之后瓦侮, 祝大家新年快樂(lè)")
}
let imp = imp_implementationWithBlock(unsafeBitCast(newFunc, to: AnyObject.self))
method_setImplementation(methond!, imp)
let person = Person()
person.countNumber(toValue: 50)
/**
輸出將是
數(shù)之前艰赞, 祝大家新年快樂(lè)
0
1
3
。肚吏。方妖。
。罚攀。党觅。
49
50
數(shù)之后雌澄, 祝大家新年快樂(lè)
*/