0%

从 OC 到 Swift 你要知道的事

枚举

概述

Swift 中枚举和结构体也上升到对象的位置,但是却不具备完整的对象特征,比如说他们不能继承。

在 OC 中枚举本质其实是整数类型,只是给他们取了一些意义直观的名称而已,而 Swift 完全摆脱以前的思想的束缚编的更自由,拥有了以下特征。

  • 类型更广,不限于整形,可以是 CharacterStringFloatDouble 等,这些叫做原始值
  • 可以拥有自己的静态成员变量来储存一些常量
  • 可以拥有自己的方法和变量
  • case 条件匹配可以定义参数,可以使用 where 来过滤
  • 通过 rawValue 可以拿到枚举的原始值

原始值

如果提供了原始值,就可以在 case 声明成员时提供默认值,这样跟 OC 的枚举在结构上一些类似

1
2
3
4
5
6
7
enum WeekDays : Int {
case Monday = 0
case Tuesday = 1
case Wednesday = 2
case Thursday = 3
case Friday = 4
}

1.声明一个枚举值

1
let monday = WeekDays.Monday

2.获取原始值

1
let rawVlaue = WeekDays.Tuesday.rawValue

3.通过原始值构造某个枚举变量

1
let wednesday = WeekDays.init(rawValue: 2)

相关值

和 C 的联合体有点类似

1.声明

1
2
3
4
enum Figure {
case Rectangle(Int, Int)
case Circle(Int)
}

2.使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func printFigure(figure: Figure) {
switch figure {
case .Rectangle(let width, let height):
print("width:\(width), height:\(height)")
case .Circle(let radius):
print("the circle's radius is:\(radius)")
}
}


var figure = Figure.Rectangle(1024, 768)
printFigure(figure)

figure = .Circle(600)
printFigure(figure)

OC 与 Swift 中 Options 枚举的不同定义

OC 版本 NS_OPTIONS

1
2
3
4
5
6
7
8
9
typedef NS_OPTIONS(NSUInteger, NSVolumeEnumerationOptions) {
/* The mounted volume enumeration will skip hidden volumes.
*/
NSVolumeEnumerationSkipHiddenVolumes = 1UL << 1,

/* The mounted volume enumeration will produce file reference URLs rather than path-based URLs.
*/
NSVolumeEnumerationProduceFileReferenceURLs = 1UL << 2
}

Swift 版本 OPTIONS

1
2
3
4
5
struct NSVolumeEnumerationOptions : OptionSetType {
init(rawValue rawValue: UInt)
static var SkipHiddenVolumes: NSVolumeEnumerationOptions { get }
static var ProduceFileReferenceURLs: NSVolumeEnumerationOptions { get }
}

使用

1
2
3
4
5
UIView.animateWithDuration(0.3,
delay: 0.0,
options: [.CurveEaseIn, .AllowUserInteraction],
animations: {},
completion: nil)

结构体

Swift 中加强了结构体的能力,可以定义和使用属性,方法,下标,构造器等,但是不能被继承,没有强制类型抓换,使用析构器和引用计数等能力

通常使用结构体来充当数据模型,常量可以使用静态关键词 static 标示

循环引用

Swift 中解决循环强引用的方式

  • 弱引用 – weak * 无主引用 – unowned ## 解决闭包中循环引用

[unowned 捕获对象]或者
[weak 捕获对象]

使用实例

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
26
27
class Person {
let name: String

// 写法 1
// lazy var printName: () ->() = {
// [weak self] in if let strongSelf = self {
// print("The name is \(strongSelf.name)")
// }
// }

// 写法 2
lazy var printName: () ->() = {
[unowned self] in print("The name is \(self.name)")
}

init(personName: String) {
name = personName
}

deinit {
print("Person deinit \(self.name)")
}
}

var xiaoMing: Person? = Person(personName: "xiaoMing")
xiaoMing!.printName
xiaoMing = nil

二者的区别

如果我们可以确定在整个过程中 self 不会被释放的话,我们可以将上面的 weak 改为 unowned,这样就不再需要 strongSelf 的判断。但是如果在过程中 self 被释放了而 printName 这个闭包没有被释放的话 (比如 生成 Person 后,某个外部变量持有了 printName,随后这个 Persone 对象被释放了,但是 printName 已然存在并可能被调用),使用 unowned 将造成崩溃。在这里我们需要根据实际的需求来决定是使用 weak 还是 unowned。

OC 和 Swift 中常用数据类型

字符串

  • OC: NSString, NSMutableString
  • Swift: String

NSString 和 String 的关系:在 Swift 中,使用字符串可以使用 Foundatio 中的 NSString 和 Swift 中的 String。

Swift 在底层能够将 String 与 NSString 无缝地桥接起来,String 可以调用 NSString 的全部 API。

数组类

  • OC: NSArray, NSMutableArray
  • Swift: Array [AnyObject]

NSArray 和 Array 的关系:Swift 能在底层将他们自动桥接起来,一个 NSArray 对象桥接后的结果是[AnyObject]。

字典

  • OC: NSDictionary, NSMutableDictionary
  • Swift: Dictionary [Object: AnyObject]

NSDictionary 和 Dictionary 的关系: 底层自动桥接,一个 NSDictionary 对象桥接后的结果是[Object: AnyObject]。

类型转换

类的转换使用 as 数据类型加括号 Int() OC 使用 (新的类型)原来的变量 # 类型判断

is 关键词

相当于 OC 的 isKindofClass: # 辅助命令

  • #file –> _FILE_
  • #line –> _LINE_
  • #function –> _func_ 或者 _FUNCTION_

退出程序

  • C: exit(0)
  • Swift: fatalError() 或者 fatalError(message: String)

断言

  • OC: NSAssert * Swift: assert()