Swift-从OC到Swift 一
MARK, TODO, FIXME
- //MARK: 类似于OC中的 #pragma mark
- //MARK: - 类似于OC中的 #pragma mark -
- //TODO:用于标记未完成的任务
- //FIXME:用于标记待修复的问题
条件编译
1 | // 操作系统:macOS\iOS\tvOS\watchOS\Linux\Android\Windows\FreeBSD |
打印
1 | //自定义Log输出格式 |
系统版本检测
1 | // 对于iOS平台,只在iOS10及以上版本执行 |
API可用性说明
1 | @available(iOS 10, macOS 10.15, *) |
iOS程序的入口
- 在AppDelegate上面默认有个@UIApplicationMain标记,这表示
- 编译器自动生成入口代码(main函数代码),自动设置AppDelegate为APP的代理
- 也可以删掉@UIApplicationMain,自定义入口代码:新建一个main.swift文件
1 | import UIKit |
Swift调用OC
- 新建1个桥接头文件,文件名格式默认为:**{targetName}-Bridging-Header.h**
- 在
{targetName}-Bridging-Header.h文件中 #import OC需要暴露给Swift的内容- TARGETS -> Build Settings -> briding
1 | #import "***.h" |
示例
1 | //Person.h文件 |
Swift调用OC – @_silgen_name
- 如果C语言暴露给Swift的函数名跟Swift中的其他函数名冲突了
- 可以在Swift中使用 @_silgen_name 修改C函数名
1 | // C语言 |
OC调用Swift
Xcode已经默认生成一个用于OC调用Swift的头文件,文件名格式是:
{targetName}-Swift.h- TARGETS -> Build Settings -> generated interface
Swift暴露给OC的类最终继承自NSObject
使用
@objc修饰需要暴露给OC的成员使用
@objcMembers修饰类- 代表默认所有成员都会暴露给OC(包括扩展中定义的成员)
- 最终是否成功暴露,还需要考虑成员自身的访问级别
1 | import Foundation |
OC调用Swift,OC文件中的代码示例:
1 | #import "_Swift-Swift.h" |
OC调用Swift – @objc
- 可以通过
@objc重命名Swift暴露给OC的符号名(类名、属性名、函数名等)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25@objc(MyCar)
@objcMembers class Car: NSObject {
var price: Double
@objc(name)
var band: String
init(price: Double, band: String) {
self.price = price
self.band = band
}
@objc(drive)
func run() { print(price, band, "run") }
static func run() { print("Car run") }
}
extension Car {
@objc(exec:v2:)
func test() { print(price, band, "test") }
}
MyCar *c = [[MyCar alloc] initWithPrice:10.5 band:@"BMW"];
c.name = @"Bently";
c.price = 108.5;
[c drive]; // 108.5 Bently run
[c exec:10 v2:20]; // 108.5 Bently test
[MyCar run]; // Car run
选择器(Selector)
- Swift中依然可以使用选择器,使用
#selector(name)定义一个选择器 - 必须是被
@objcMembers或@objc修饰的方法才可以定义选择器1
2
3
4
5
6
7
8
9
10
11
12@objcMembers class Person: NSObject {
func test1(v1: Int) { print("test1") }
func test2(v1: Int, v2: Int) { print("test2(v1:v2:)") }
func test2(_ v1: Double, _ v2: Double) { print("test2(_:_:)") }
func run() {
perform(#selector(test1))
perform(#selector(test1(v1:)))
perform(#selector(test2(v1:v2:)))
perform(#selector(test2(_:_:)))
perform(#selector(test2 as (Double, Double) -> Void))
}
}
只能被Class继承的协议
- @objc 修饰的协议,还可以暴露给OC去遵守实现
1
2
3
4
5protocol Runnable1: AnyObject {}
protocol Runnable2: class {}
@objc protocol Runnable3 {}
可选协议
- 可以通过 @objc 定义可选协议,这种协议只能被 class 遵守
1
2
3
4
5
6
7
8
9
10
11
12
13
14@objc protocol Runnable {
func run1()
@objc optional func run2()
func run3()
}
class Dog: Runnable {
func run3() { print("Dog run3") }
func run1() { print("Dog run1") }
}
var d = Dog()
d.run1() // Dog run1
d.run3() // Dog run3
dynamic
- 被 @objc dynamic 修饰的内容会具有动态性,比如调用方法会走 runtime 那一套流程
1
2
3
4
5
6
7class Dog: NSObject {
@objc dynamic func test1() {}
func test2() {}
}
var d = Dog()
d.test1()
d.test2()
参考
李明杰老师课件
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ivan's Blog!
评论









