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()