Swift——不为人知的淫技

过去总是遇到一些看不太懂的代码,或者是一些开源的源码,或者是看到别人写代码,看起来好有逼格,有些因为好奇也就网上搜了一下,发现既然有这么一系列的东西我们虽然有用到,或者有看到,但是根本没有去了解他是什么?有什么用?或者苹果为什么要给个这样的特性?

@dynamic

dynamic 可以让类里面的函数使用消息机制派发. 使用 dynamic, 必须导入 Foundation 框架, 里面包括了 NSObject 和 Objective-C 的运行时. dynamic 可以让声明在 extension 里面的函数能够被 override. dynamic 可以用在所有 NSObject 的子类和 Swift 的原声类.

@objc

使用 @objc 的典型例子就是给 selector 一个命名空间 @objc(abc_methodName), 让这个函数可以被 Objective-C 的运行时调用. @nonobjc 会改变派发的方式, 可以用来禁止消息机制派发这个函数, 不让这个函数注册到 Objective-C 的运行时里.

总结

@objc 和 @nonobjc 显式地声明了一个函数是否能被 Objective-C 的运行时捕获到.

@objc是用来将Swift的API导出给Objective-C和Objective-C runtime使用的,如果你的类继承自Objective-c的类(如NSObject)将会自动被编译器插入@objc标识。 加了@objc标识的方法、属性无法保证都会被运行时调用,因为Swift会做静态优化。要想完全被动态调用,必须使用dynamic修饰。使用dynamic修饰将会隐式的加上@objc标识。

@inline

这个特性为编译器提供了内联提示。可以理解为告诉编译器可以使用直接派发.

@asmname

该属性给出了函数、方法或属性实现的符号名称。如果已经知道对应的函数参数及其类型,那么就可以直接调用Swift的内部标准库函数,甚至不用头文件,也可以方便地调用C语言编写的函数:@asmname(“function”) func f()

@semantics

这又是另一个谜。参数看起来像是array.mutate_unknown或array.init这样的字符串数组。想必这是要告诉编译器(或静态分析器)函数是如何工作的。

@unsafe_no_objc_tagged_pointer

上面这个仍然是个谜,但据猜测,它是在告诉Swift与objective-C联系的时候不要使用tagged pointer。

对象在内存中是对齐的,它们的地址总是指针大小的整数倍,通常为16的倍数。对象指针是一个64位的整数,而为了对齐,一些位将永远是零。

Tagged Pointer利用了这一现状,它使对象指针中非零位有了特殊的含义。在苹果的64位Objective-C实现中,若对象指针的最低有效位为1(即奇数),则该指针为Tagged Pointer。这种指针不通过解引用isa来获取其所属类,而是通过接下来三位的一个类表的索引。该索引是用来查找所属类是采用Tagged Pointer的哪个类。剩下的60位则留给类来使用。

@availability

这个特性可以用来标识某些函数只在某些平台或版本上可用。第一个参数是平台,可以用星号(*)代表一切可用,还可以是iOS或OS X。因为如果需要针对不同的平台,就要指定多个@availability属性。

@available放在函数(方法),类或者协议前面。

@available(iOS 9, *)
func myMethod() {
// do something
}

#available

用在条件语句代码块中,判断不同的平台下,做不同的逻辑处理,

if #available(iOS 8, *) {
// iOS 8 及其以上系统运行
}

总结

网上有这么一段话:@available是编译期间判断的,而#available是运行时行为。

@transparent

该特性会导致编译器在管道(pipeline)中更早地将函数内联。它用于“像+(Int, Int)这样非常原始的函数”,而“不应该用于独立函数”。
甚至在没有优化设置的调试模式下,@transparent特性函数就会被内联,所以在调用“1+1”这样的函数时候并不会特别慢,另外这个特性与@inline(__always)非常类似。

@warn_unused_result

在Swift 2.x的时候,带返回的方法我们如果在调用的时候后面使用到返回的参数,编译器不会有任何的警告,想要编译器给出警告的话需要自己在方法前面添加属性 @warn_unused_result , 如

@warn_unused_result func doSomething() -> Bool {
return true
}

这个关键字的含义:如果某个函数使用了这个关键字,那么函数在被调用的时候,要检查或者使用返回值,某则编译器会进行警告。
使用场合:在把一些功能封装起来(或者SDK的编写)时候,如果对返回值的使用比较重要,那么使用这个关键字提醒编译器要检查返回值是否被利用。

这时候调用这个方法没有使用返回参数的情况下编译器就会给出警告:

Result of call to ‘doSomething()’ is unused

@discardableResult

Swift 3.0 的时候@warn_unused_result已经不需要了,默认情况下编译器就是会去检查返回参数是否有被使用,没有的话就会给出警告。如果你不想要这个警告,可以自己手动加上 @discardableResult ,如:

@discardableResult func doSomething() -> Bool {
return true
}

这样一来一切又恢复正常了。

@warn_unqualified_access

extension SortedArray {
    /// 返回集合里的最小值 /// /// - Complexity: O(1).
    @warn_unqualified_access public func min() -> Element? { return first }
    /// 返回集合里的最大值 /// /// - Complexity: O(1).
    @warn_unqualified_access public func max() -> Element? { return last }
}

当你在类型的内部实现中调用这些函数,却没有显式地写明 self. 的前缀时,@warn_unqualified_access 会告诉编译器抛出一个警告。这样可以帮助你避免混淆了这些函数与全局函数 min(::) 和 max(::) 。

@convention

@convention 特性是在 Swift 2.0 中引入的,用于修饰函数类型,它指出了函数调用的约定。用在以下几个地方:

修饰 Swift 中的函数类型,调用 C 的函数时候,可以传入修饰过 @convention(c) 的函数类型,匹配 C 函数参数中的函数指针。
修饰 Swift 中的函数类型,调用 Objective-C 的方法时候,可以传入修饰过 @convention(block) 的函数类型,匹配 Objective-C 方法参数中的 block 参数。

拓展

__attribute__((constructor)) //确保此函数在 在main函数被调用之前调用

__attribute__((destructor)) // 确保此函数在 在main函数被调用之后调

__attribute__((cleanup())) 用于修饰一个变量,在它的作用域结束时可以自动执行一个指定的方法

后期如果有遇到或者发现其他更多相关的我也会随时更新,如果你有遇到不错的也可以联系我,我们一起交流讨论…….

坚持原创技术分享,您的支持将鼓励我继续创作!