swift4.1 系统学习二十六 特性、编译标志与检查API的可用性

/*
特性、编译标志与检查API的可用性

本节的内容都属于编译时行为。swift与C、C++、OC不同,它没有预处理器这个概念,所以不存在任何预处理时的概念。
我们可以认为swift源码的解析和处理都包含在编译时。

扩展:什么是预处理?
预处理是C语言的一个重要功能,它由预处理程序负责完成。当对一个源文件进行编译时,系统将自动引用预处
理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。
C语言提供多种预处理功能,主要处理#开始的预编译指令,如宏定义(#define)、文件包含(#include)、
条件编译(#ifdef)等。合理使用预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。
*/

/*

  1. swift中的特性

swift语言的特性(attribute)与GNU C语言中的 sttribute非常类似,用于修饰一个对象、函数和类型,
用于指定所修饰对象的某些特定编译时的行为。

@attribute(args)
func foo() {

}

swift可以叠加多个特性,我们只需要将多个特性做一般的叠加即可,特性之间没有任何先后顺序。
*/

class A {
    
    
    @inline(__always)
    @available(macOS 12.0, *)
    func foo() {
        print("特性学习")
    }
}

// 一起学习swift有哪些常用特性
/*
(1) available

available特性用于指明一个对象、函数或者类型的可用性。这个特性常用于指明ios的版本号,因为有些
方法只有新版本才能使用,为了兼容,加上特性标识。

当前Apple用于自家平台的Swift支持以下平台:
iOS、iOSApplicationExtension、macOS、macOSApplicationExtension、watchOS、
watchOSApplicationExtension、tvOS、tvOSApplicationExtension、swift。
*/

class B {
    
    /*
     available限定了MyTest函数只能用于iOS 10.0或者更高版本;
     macOS 10.13或者更高版本
     这里的 * 表示出了ios10.0以及macOS 13.0之外,其他更高版本以及其余平台也可用。
     */
    @available(iOS 10.0, macOS 10.13, *)
    func MyTest() {
        print("Hello china")
    }
    
    @available(swift 3.0)
    @available(iOS 10.0, macOS 10.12, *)
    struct MyStruct {
        
    }
}

let b = B()
b.MyTest()

_ = B.MyStruct()

/*
几个常用参数:
introduced: 从哪个版本开始引入;
deprecated: 从哪个版本开始废弃;
obsoleted: 从哪个版本开始被移除,被移除的实体在当前环境中将无法访问。
message: 当我们使用了已经废弃或者移除的接口的时候引发的编译警告或者错误。

这几个参数在苹果的API文档中经常出现。我们在使用某个方法的时候,有时候会出现一道删除线在方法上面,
就是因为这个方法已经标识为废弃。
*/

class C {
    
    @available(macOS 10.10, *)
    @available(*, introduced: 10.10, deprecated: 10.12, message: "方法不可用啦")
    func hello() {
        print("哈哈哈哈哈")
    }
}

let c = C()
// 'hello()' is deprecated: 方法不可用啦
c.hello()

/*
(2) discardableResult

此特性一般用于修饰带有返回值的函数或方法,以指明当前函数或方法的返回值可被缺省。
*/

class D {
    
    @discardableResult
    func foo(a: Int) -> Int {
        return a * 2
    }
    
    func boo() -> String {
        print("好孩子是什么?")
        return "boo"
    }
}

let d = D()
/*
 这里调用foo,而不必管它的返回值,也不会引发警告
 */
d.foo(a: 10)
// 调用boo,就会出现警告:
// Result of call to 'boo()' is unused
d.boo()

/*
(3) objc

这个特性只能用于Apple自家平台。表示一个类型或者方法可用于OC中的相关类型或方法来表示。
其实这个特性还是挺常用的,尤其是在#selector()事件的方法外面,都要加一个objc标识。
*/

@objc
protocol MyProt {
    // 此方法必须实现
    func method()
    
    // 这里方法不是必须实现
    @objc
    optional func foo()
}

class E: MyProt {
    
    // 这个方法是必须实现的
    func method() {
        print("你好")
    }
}

/*
(4) autoclosure

这个特性可以让一个表达式自动封装成一个不带参数的闭包。
*/

/*
(5)convention

此特性用于修饰一个函数对象的类型,以指定其调用约定。swift共有三种调用约定:
1》swift:表示该函数对象为一个swift函数的引用。
2》block:表示该函数与OC的Block引用相兼容。
3》c: 用于指示该函数对象是一个C函数的引用。也就是说该函数引用不带任何执行上下文,并且直接使用C语言
函数调用约定。
*/

class F {
    
    func test() {
        var x = 100
        
        /// 它可以对捕获局部对象的闭包进行引用
        let ref1: @convention(swift)(Int) -> Void  = {
            (a: Int) -> Void in
            
            x += a
        }
        
        /// ref2具有block调用约定,可以直接与OC中的Block进行交互,也可以作为OC的对象引用
        let ref2: @convention(block) (Int) -> Void  = {
            (a: Int) -> Void in
            x -= a
        }
        
        let ref3: @convention(c) (Int) -> Void = {
            (a: Int) -> Void in
            print("a = \(a)")
        }
        
        ref1(10)
        ref2(5)
        ref3(1)
        
        print("x = \(x)")
    }
}

let f = F()
f.test()

/*
(6) escaping

该特性用于修饰一个函数或方法的形参类型,指明该形参将会在稍后执行,因而要被存放一下。这意味着该形参
的生命周期将延伸到此函数或方法调用结束之后也不会消失。
*/

/*
(7). inline

inline特性暗示该函数或方法可以被内联或不被内联。它有一个参数用于指明所修饰的函数或方法是否可被内联。
__always: 总是被内联;
never: 表示该函数无论什么时候都不应该被内联。

什么是内联?
函数的实现是在另一个函数内部。
*/

class G {
    
    @inline(never)
    func noInlineFunc() {
        print("永不内联")
    }
    
    @inline(__always)
    func alwaysInlineFunc() {
        print("总被内联的函数")
    }
    
    /*
     注意:
     一般情况下,swift编译器会根据上下文环境决定某一函数是否需要内联,所以我们一般无需使用@inline(__always)。
     */
}

/*
(8). _silgen_name

_silgen_name特性可用于指明当前所引用的函数是一个遵循C语言标准API的函数。
此特性可以让我们直接在swift中引用一个具有外部链接的全局C函数,即便该函数没有桥接头文件中声明。
*/

/*
关于swift的特性部分,已经差不多学习完了,真的具有好多特性啊。这些特性属于小知识点,比较零碎,不容易记忆。
不过只要有印象,当我们在某个情境下需要的时候,能够回过头来找到这些特性运用就可以了。
*/

/*

  1. 编译标志

swift编译器同C语言编译器类似,可以设置一些编译选项。

if ... #else ... #endif

注意:
swift下的编译标志不能像C语言那样加 “-D FLAG = 1”这种。因为swift再用#if判定的时候已经假定了每个
标志都是一个布尔类型。只要该标志被定义了,就是true,反而,就是false。

我们定义编译标志是在 xcode的
Build Settings ——》 Swift Compiler - Custom Flags ——》Other Swift Flags 中进行设置。
设置格式是:
“-D”"标识名字"

这也是项目中经常使用的,debug模式下的打印与release下的不同时,常常这样设置。
*/

@inline(__always)
func debug_log(str: String) {
    
    #if DEBUG
       print("嘎嘎嘎嘎嘎嘎")
    #else
       print(str)
    #endif
}

debug_log(str: "好不好啊")

/*

  1. 检查API的可用性

swift是一门趋于静态编译的编程语言,尽管它也能被解释执行,但是从设计上,它没有像OC那样具有众多的
动态特性。这反而使它在运行时变得高效。

*/

class H: NSObject {
    
    override init() {
        super.init()
        
        Timer.scheduledTimer(timeInterval: 1.0,
                             target: self,
                             selector: #selector(timerHandler(timer:)),
                             userInfo: nil,
                             repeats: false)
    }
    
    @objc func timerHandler(timer: Timer) {
        print("哈哈哈哈哈哈哈哈")
    }
}

if #available(iOS 10, macOS 10.12, *) {
    
    /*
     Timer这个类型方法只有在iOS10.0以及macOS 10.12开始才能用
     */
    Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { (timer) in
        print("开始执行呗")
    }
} else {
    
    _ = H()
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_x阅读 15,967评论 3 119
  • 情绪忽然不好,抽张牌,疲惫二字直击内心,画面上两个人看似并排走,但是她们之间没有情感交流和能量的传递,在身边的人,...
    韩昀希阅读 119评论 0 0
  • 昨天5月20日霍建华宣布了与林心如在一起,心情沉痛下名正言顺的放纵了一天。两日阴雨绵绵,沉闷压抑本想再放一晚,奈何...
    二星瓢虫侠阅读 336评论 2 3
  • 一个苦行的人;一个可怜的人;一个用功的人;一个无聊的人;一个无情的人;一个卑微的人;一个痛苦的人;一个无用的人.....
    三心白阅读 296评论 0 0
  • 妈妈已经七十多岁了,行动不再麻利,还有点儿哮喘。 4月6号十点多,约老妈去濮阳绿色庄园玩,妈妈不想去。 ...
    自律的小丁儿阅读 1,810评论 2 15