//TODO: 用于標(biāo)記未完成的任務(wù)
// FIXNE: 用于標(biāo)記待修復(fù)的問題
//#warning("todo") 警告
條件編譯
//操作系統(tǒng)
#if os(macOS) || os(iOS)
//CPU架構(gòu)
#elseif arch(x86_64) || arch(arm64)
//swift版本
#elseif swift(<5) && swift(>=3)
//模擬器
#elseif targetEnvironment(simulator)
//可以導(dǎo)入某模塊
#elseif canImport(Foundation)
#else
#endif

強(qiáng)制斷言.png
#if DEBUG
DEBUG 模式
#else
release 模式
#endif
如果需要自己自定義編譯器模式 那么可以
第一種方法

WeChat0515ae36c50635b683ea74b2c317dff1.png
在DEBUG 后面加空格再加上自己的編譯器模式
第二種方法

WeChatd1616ca286b55d8900a2cfbd09956e69.png
在里面填寫-D 自己的自定義編譯器模式
打印
func log<T>(_ msg: T,
file: NSString = #file,
line: Int = #line,
fn: String = #function) {
#if DEBUG
let prefix = "\(file.lastPathComponent)_\(line)_\(fn):"
print(prefix, msg)
#endif
}
系統(tǒng)版本檢測
if #available(iOS 10,macOS 10.12, *){
//對與ios平臺 只在ios10以及以上版本執(zhí)行
//對于macOS平臺 只在macOS 10.12及以上版本執(zhí)行
//最后的* 表示在其他所有平臺都執(zhí)行
}
API可用性
struct Student {
//study_不可用 改名為study
@available(*,unavailable,renamed: "study")
func study_() {
}
func study() {
}
@available(iOS, deprecated: 11)
//macOS 的10.12開始 這個(gè)run方法不可用
@available(macOS, deprecated: 10.12)
func run() {
}
}
var stu = Student()
stu.run()

錯(cuò)誤.png
ios程序入口
1.在AppDelegate上面默認(rèn)有個(gè)@UIApplicationMain標(biāo)記 表示
編譯器自動(dòng)生成入口代碼(main函數(shù)代碼) 自動(dòng)設(shè)置AppDelegate為App的代理
2.也可以刪除@UIApplicationMain 自定義入口代碼 新建一個(gè)main.swift文件
import Foundation
import UIKit
class MyApplication: UIApplication {
}
UIApplicationMain(CommandLine.argc,
CommandLine.unsafeArgv,
NSStringFromClass(MyApplication.self),
NSStringFromClass(AppDelegate.self))
Swift調(diào)用OC
- 新建一個(gè)橋接頭文件 文件名格式默認(rèn)為 {targetName}-Bridging-Header.h
- 在相應(yīng)的位置寫入橋接頭文件的位置

寫入橋接頭文件的位置.png
如果C語言暴露給Swift的函數(shù)跟Swift的函數(shù)沖突了 可以在swift中使用@_silgen_name 修改C函數(shù)名
@_silgen_name("sum")
func swift_sum(_ v1: Int32,_ v2: Int32) -> Int32
@_silgen_name 函數(shù)必須是存在的
OC調(diào)用Swift
- 默認(rèn)生成一個(gè)橋接頭文件 文件名格式默認(rèn)為 {targetName}-Swift.h

文件存放的位置.png
Swift里面的類要想暴露給OC 必須繼承于NSObject 要用@objc 修飾需要暴露給OC的成員和方法
可以使用@objcMembers 修飾Swift里面的類 使得整個(gè)類所有內(nèi)容暴露給OC
Xcode會根據(jù)Swift代碼默認(rèn)生成相對應(yīng)的OC代碼 放在{targetName}-Swift.h中
可以使用@objc () 的方法重命名暴露給OC的類名 屬性名 函數(shù)名等
Selector 選擇器
使用#selector(name )定義一個(gè)選擇器
必須是被@objc 或者 @objcMembers 修飾的方法才可以定義選擇器
因?yàn)檫x擇器依賴于Runtime 而Runtime只在OC中有 Swift里面沒有 所以 必須暴露給OC 才可以選擇器

方法調(diào)用.png
為什么swift 中的暴露給OC的類最終要繼承自NSObject
OC依賴于Runtime Runtime要求有isa指針 isa指針一定要繼承自NSObject
OC的初始化alloc 也要繼承自NSObject
Swift調(diào)用OC中的內(nèi)容 底層是怎么調(diào)用的 返回來 OC調(diào)用Swift底層又是如果調(diào)用的
純Swift 調(diào)用方法是虛表 也就是一個(gè)call一個(gè)假地址 然后尋找到真正的地址去調(diào)用方法
- Swift調(diào)用OC中方法是走的msg_send方法
- OC調(diào)用Swift方法是runtime流程 msg_send
如果swift類繼承自NSObject 使用@objcMembers修飾 那么在swift里面調(diào)用swift方法走的是swift的方式 不走OC的msg_send流程
當(dāng)你想走OC的msg_send流程 的時(shí)候 那么在方法前加dynamic進(jìn)行修飾