Swift要点:从Objective-C开发者的角度看Swift

代码环境是Xcode6.3-Beta3.

Swift已经极大的改变了开发iOS应用的方式。本文中,我会列出Swift的几个重点,并且和Objective-C一一做出对比。

注意,本文不是Swift的入门指导。苹果发布了Swift Programming Language,强烈建议您读一读这本书。文本主要介绍Swift中比较酷炫的特性。

类型

Swift提供的第一个重大的改进是类型推断。使用了类型推断的编程语言,开发者不需要在声明中明确指定变量的类型。编译器会自动探知要赋给变量的值的类型。比如下面的例子,编译器会自动设定变量的类型为String:

// 类型推断
var str = "Hello World!"

// 明确定义类型,这里可以不这样
var swift: String = "Hello Swift"

和类型推断一起带来的是类型安全。在Swift中,编译器(一般来说全部,但是在很少的情况下)知道一个类型的全部类型。这样给编译器一个选择如何编译代码的机会,因为编译器有足够的信息。

这承托出了Objective-C的一个非常动态的本质。在Objective-C中,任何类型在编译期间都是未知的。这也是为什么你可以在运行时给已经存在的类添加方法,添加一个全新的类型,甚至于改变一个对象的类型。

看看Objective-C的代码:

Person *man = [[Person alloc] init];
[man sayHello];

当编译器看到对方法sayHello的调用的时候,它就会检查类型Person类的头文件中是否有一个叫做sayHello的方法。如果没有就报错。编译器就只可以做这些。这确实可以你可能引入的最初简单的bug:如拼写错误。但是,因为动态性,编译器不可能知道sayHello方法是否会在运行改变、甚至是否存在。这可能是一个协议中得optional方法。比如(还记得那些使用respondsToSelector的检查吗)。

由于缺乏强类型, 在Objective-C中调用方法的时候编译器几乎不能做什么优化。处理代码动态分发的方法是:objc_msgSend。我确定你在很多的时候见过这个方法。在这个方法中,寻找selector并调用。你不能说这没有增加复杂度。

再回头看看Swift的实现:

var p = Person()
p.sayHello()

在Swift中,编译器在调用方法的时候知道类型的更多信息。它准确的知道sayHell方法在哪里定义的。因此,Swift可以在方法调用的时候直接调转到方法定义的地方,而无需经过任何的动态分发过程。在其他的情况下,Swift也可以使用vtable风格的分发方式,比Objective-C的动态分发花费小得多了。这也是C++的虚方法使用的分发机制。

Swift的编译器也非常的有用。可以排除细微的类型相关的bug。它也能使你的代码运行的更快。

泛型

Swift带来的另一个很大的改变是泛型。如果你对C++很熟悉的花,那么你可以把这些和C++的template做类比。因为Swift是类型严格的,你必须方法可以接受的参数的类型。但是有的时候你的方法对于不同的类型来说作用是相同的。

比如,你希望把一对值存放在一起。你可以用Swift实现存放整型数值的结构:

struct IntPair {
    let a: Int!
    let b: Int!

    init(a: Int, b: Int){
        self.a = a
        self.b = b
    }

    func equal() -> Bool {
        return a == b
    }
}

let intPair = IntPair(a: 1, b: 1)
println("\(intPair.a)" + "\(intPair.b)" + " equal: \(intPair,equal())")

Sort of useful. But now you want this to work for floating point numbers as well. You could define aFloatPair class, but that would look awfully similar. This is where generics come in. Instead of declaring a whole new class, you could simply do
this:

有点用处,但是你也想让这个可以用于浮点数。你可以定义一个FloatPair类, 但是实在是太相似了。这个时候泛型就会发挥用处了。相对于定义一个全新的类型,你可以这样:

struct Pair<T: Equatable> {
    let a: T!
    let b: T!

    init(a: T, b: T){
        self.a = a
        self.b = b
    }

    func equal() -> Bool {
        return a == b
    }
}

let tempPair = Pair<Int>(a: 1, b: 1)
var tempA = tempPair.a
var tempB = tempPair.b
var tempEqual: Bool = tempPair.equal()

println("\(tempA) " + "\(tempB) " + "equal: \(tempEqual)")

let tempPair1 = Pair<Float>(a: 1.0, b: 1.0)
var tempA1 = tempPair1.a
var tempB1 = tempPair1.b
var tempEqual1: Bool = tempPair.equal()

println("\(tempA1) " + "\(tempB1) " + "equal: \(tempEqual1)")

请各位读者原谅我用了这么烂得命名方式啊。。。

非常有用!你可能不是很清楚你为什么需要泛型,但是相信我会有很多时候你会用到。你很快会发现在哪里可以使用这些代码。

容器

也许你觉得NSArray和NSDictionary和对应的可变类型都已经很好用了。但是你需要学习对应的Swift容器。幸运的是,他们非常相似。如:

let array = [1, 2, 3, 4, 5]
let dictionary = ["dog": 1, "elephant": 2]

这些对你来说已经非常熟悉了。瞅一眼就可以搞定的。在Objective-C中,数组和字典可hi包含你想要的任何类型。但是在Swift中数组和字典是强类型的。而且这些容器都是泛型类型的。

上面的两个变量可以使用类型表达式来重写(你不是必须要这么做),比如:

let array: Array<Int> = [1, 2, 3, 4, 5]
let dictionary: Dictionary<String, Int> = ["dog": 1, "elephant": 2]

Notice how generics are used to define what can be stored in the container. There is also a short form for these, which is slightly more readable, but essentially boils down to the same thing:

注意泛型是怎么定义什么可以放进容器中的。定义的方式也有简短的方式的,可读性更好。但是本质上来说是一样的:

let array: [Int] = [1, 2, 3, 4, 5]
let dictionary: [String, Int] = ["dog": 1, "elephant": 2]

注意,这个时候你无法给数组添加任何的不是Int类型的值。这看起来不好,但是非常有用。你不再需要在文档中专门指明属性返回的数组中存放的是什么类型的值。编译器会自动检测错误并优化代码的编译。

可变性

Swift容器的一个有意思的地方是他们都是可变的(mutable)。array和dictionary没有“mutable”的对应类型了。可变和不可变都由letvar关键字控制。let就是用来声明一个常量的关键字,var是用来声明一个变量的。let就像是C、C++或者Objective-C中得const关键字一样。

The way this relates to collections is that collections declared using let cannot change size. That is, they cannot be appended to, or removed from. If you try to, then you get an error like so:

使用let声明的集合不能再修改size,也就是不能再append或者remove。如果你这么做了,就会报错:

let array: [Int] = [1, 2, 3, 4, 5]
array.append(33)
//immutable value of type ‘[int]‘ only has mutating members named ‘append‘

字典也同样使用这个规则。这允许编译器推测出这一类型的集合并作出相应的优化。如果size不能修改,集合的存储实现不再需要重新分配新的空间容纳新的值。因此,经常使用let来定义不再改变的集合是一个很好的实践。

字符串

Objective-C的字符串非常难用。即使是简单的拼接字符串之类的都需要写很多的代码。比如:

Person *person = ...;

NSMutableString *description = [[NSMutableString alloc] init];
[description appendFormat:@"%@ is %i years old.", person.name, person.age];
if (person.employer) {
  [description appendFormat:@" They work for %@.", person.employer];
} else {
  [description appendString:@" They are unemployed."];
}

This is quite tedious and contains a lot of characters that are nothing to do with the data being manipulated. The same in Swift would look like this:

这样的写法非常的冗长,而且包含了与本次操作无关的其他字符。同样的功能在Swift里看起来是这样的:

var description = ""
description += "\(person.name) is \(person.age) years old."
if person.employer {
    description += " They work for \(person.employer)."
} else {
    description += " They are unemployed."
}

非常的清晰。更加清晰的创建一个字符串,你可以使用字符串拼接操作符+=。不再需要可变字符串和非可变字符串。

另一个Swift字符串的变化是”字符串的比较“。你知道在Objective-C中不能使用==来比较两个字符串的相等。你得用isEqualToString方法。这是应为==是比较的指针是否相等。Swift中可以直接使用==比较两个字符串。也就是说字符串可以在switch-case表达式中。更多相关请继续收看下一节内容。

Swift的字符串的另一个好东西是本地支持Unicode。你可以使用任意的Unicode字符,即使是在变量名和函数名中。如果你愿意你可以声明一个方法

时间: 2024-10-11 17:53:23

Swift要点:从Objective-C开发者的角度看Swift的相关文章

swift初探(供objective c开发者参考)

6月初的wwdc苹果推出了一门新的开发语言swift.系统10.9.3以上安装xcode6 beta版即可体验swift. 苹果公司做了尽可能多的努力让这门语言迅速成为一个工业级的实用编程语言,而不是华而不实的花瓶. 通过xcode6查看文档,可以发现之前现存的接口都多了swift适配,举例如下(以下都从苹果官方文档中摘录): 简单方法适配: swift: func UIImageJPEGRepresentation(_ image: UIImage!, _ compressionQuality

【阿里云产品公测】以开发者角度看ACE服务『ACE应用构建指南』

?;ZnD(4?   评测介绍 1V-sibE   j|LOg 评测产品: 云引擎ACE服务 开发语言: PHP 评测人: mr_wid 评测时间: 2014年10月13日-19日 XV1XzG#C   .>p.k*vU   评测概要 9]:F!d/   fYlqaO4[   非常有幸能够申请到ACE的公测资格, 在本篇评测中, 笔者将以一个开发者的角度来对云引擎ACE服务进行介绍与使用.在本篇评测中, 您将看到: ACE能够做些什么 ACE应用的创建与发布 应用的配置与调试 ACE扩展服务的使

Swift 3.0首个开发者预览版将在5月12日释出

关于Linux的学习,请参考书籍<Linux就该这么学> swift团队在博客中宣布Swift 3.0语言首个开发者预览版将于5月12日释出,正式版将在4-6周之后推出.开发者预览阶段并无确定的更新周期和计划,不过Swift团队称努力将其控 制在4-6周内.按此计划,Swift 3.0将错过WWDC发布窗口,团队计划于年底随新版本Xcode升级版一起发布. Swift的GitHub库也将被分为三个分支:主流分支.Swift 3.0预览分支.和Swift 3.0分支.基于Swift的开发将被限定

从一个开发者的角度评价编程语言

这其实是一个比较老的话题了,关于各种语言的好坏选择网上怎么说的都有,有趣的是所有的争论占据伤风的总是一些脑残粉,对于编程语言的选择不同的人有不同的看法,我大致分为以下几类: 1.搞开发的 2.搞教育的 3.搞科研/学术的 4.业余的 5.其它 我是做开发的,这篇文章主要是从开发者的角度,根据多年来各种语言的使用经验来谈谈主流的编程语言,这些语言包括(C.C++.D.Go.Java.C#.Delphi.VB.PHP.Python),没有列出的语言表示我没用过,所以也不好评价. 我认为一个好的编程语

从开发者的角度解释网上看视频出现的各种问题

本文从开发者的角度给大家用通俗的语言来解释一下有关音视频播放的问题. 1. 为什么在视频网站上播放1080P视频有时候不是特别清晰? 1080P代表视频的分辨率是1920x1080,对于图像而言,分辨率越高,清晰度也越高:但是视频不同,视频是由多帧图像组成的,为了减少存储空间.便于传播,视频中的图像都是经过了一定的算法压缩,而压缩则必然导致失真. 在视频压缩算法中,有一个衡量压缩比率的参数,叫做:码率.它代表一秒钟的视频数据大小,例如:10Mb/s,代表1秒钟有10M bit的视频数据,对于YU

从开发者的角度分析iOS应如何省电

从开发者的角度分析iOS应如何省电 说明 网上关于iPhone如何省电的文章很多.但是基本没有讲原理.而在生活中,很多人在使用iPhone中有着明显的错误的省电习惯. 本文从iOS开发者的角度,对iOS的各项功能和技术进行说明,得出合理的省电技巧,以供大家参考. 如果你对省电原理没有兴趣,请直接到文章最后,查看如何省电的方法. 哪些功能(硬件)是耗电大户 网络下载 wifi和4G都是耗电大户,但是要知道手机上的网络模块并不是一直在高速工作状态.一般认为下载时耗电多,如果不是处于下载状态,耗电较少

从一个程序员的角度看——微信小应用

前言: 最近初步了解了一下微信小应用,APP端的同事也非常感兴趣,于是在公司内部做了一个小小的分享,分享的过程中有很多讨论内容,大家也是非常感兴趣和有自己的看法,当时"混乱"的场面好几次我都没有把持住.以下内容部分来自于内部分享所用ppt.文章对微信小应用的使用做了展示性介绍,并简单介绍了代码结构.后端交互方法.最后提出一些总结和疑问.文章内容比较主观,有不对的地方欢迎大家指出纠正. 前段时间微信小应用公开内测,在朋友圈火了一把,各种阐述疯狂蔓延,干掉APP之类的说法比较突出,确实达到

从一个程序员的角度看——微信小应用(第二弹 见解)

最近公司的小程序刚通过了代码审核(待发布状态),从最初对它的学习 到开发 到小程序待发布 再到28日微信公开课,也算一步步的了解了微信小程序吧. 28日微信pro公开课张小龙针对小程序进行了一些答疑,之后行业的同僚都很关注,似乎大家还是有很多疑惑.之前初学后写过博客 从一个程序员的角度看--微信小应用(第一弹 初学),今天决定再写一篇小程序的小文,所以此篇谈谈我对小程序的理解吧. 说说张小龙回答的8个问题 1.小程序的入口在哪里?张小龙给出的答案是:小程序在微信没有入口. 2.小程序会不会有类似

从一个程序员的角度看——微信小应用(含直播视频)

前言: 最近初步了解了一下微信小应用,APP端的同事也非常感兴趣,于是在公司内部做了一个小小的分享,分享的过程中有很多讨论内容,大家也是非常感兴趣和有自己的看法,当时"混乱"的场面好几次我都没有把持住.以下内容部分来自于内部分享所用ppt.文章对微信小应用的使用做了展示性介绍,并简单介绍了代码结构.后端交互方法.最后提出一些总结和疑问.文章内容比较主观,有不对的地方欢迎大家指出纠正. 前段时间微信小应用公开内测,在朋友圈火了一把,各种阐述疯狂蔓延,干掉APP之类的说法比较突出,确实达到