http://blog.csdn.net/dahuagogo/
本篇文章简述了如何从Objective-C向Swift过渡。话不多说,开门见山。
注意:本文讨论的开发环境为Xcode
6 beta 2版本。
单一文件结构 VS 接口-实现
最值得一提的一大改动便是在Objective-C中“[接口].h/[实现].m”这种文件结构被取缔了。
其实我本人是很支持这种文件结构的,因为通过接口文件来获取及共享类特性的方式相当安全而且简单,不过现在不得不面对它不复存在的现实了。
在Swift中并不存在接口与实现分割成两个文件的现象,我们仅需要依靠实现来构建一个类就行了(并且在写的时候甚至不可能添加关于可访问性的修改)。
如果对于这一改动感到无法忍受的话应注意以下事项:
最为明显的:靠直觉。
我们可以借助漂亮的文档来提高类的可读性。举个例子,我们可以把所有想作为public的要素全部挪到文件开头去,也可以采用扩展来区分public和private。
另一个很实用的办法就是在private的方法和变量命名前加一个下划线‘_‘作为前缀。
下面是混合了以上两种方案的示例:
02 |
extension DataReader { |
06 |
var data = _webserviceInteraction() |
10 |
// Private implementation |
11 |
class DataReader: NSObject { |
15 |
func _webserviceInteraction()->String{ |
虽然我们没办法修改类中各元素的可见性,不过我们可以试着让某些访问变得“困难一些”。
一个特殊的方法就是使用嵌套类来把private部分隐藏起来(至少是自动的隐藏),下面是例子:
03 |
class DataReader: NSObject { |
05 |
// Public *********************** |
07 |
get{return private.internalData} |
11 |
private = DataReaderPrivate() |
14 |
func publicFunction(){ |
19 |
// Private ********************** |
20 |
var private:DataReaderPrivate |
22 |
class DataReaderPrivate { |
23 |
var internalData:String? |
26 |
internalData = "Private data!" |
我们将private的实现放入一个private常量的实例中,然后用“正常”的类的实现来充当接口。不过private部分并非会真正的隐藏起来,只不过在访问的时候需要加上一个private关键字:
1 |
let reader = DataReader() |
2 |
reader.private.privateFunc() |
问题来了:仅是为了最后要将这些private的部分隐藏起来,就要把代码写得这样怪异值得吗?
我的建议是在可见性的修改出来之前(苹果正在忙这个事),我们还是采用详细的文档或者多少用一点扩展来完成这个事。
常量和变量
在写Objective-C的时候我会很少的使用到const关键字,甚至于我知道有的数据时不会变的。然而在Swift中苹果建议开发者们多花点心思在使用常量(let)而不是变量(var)上。所以请注意要弄明白你的变量的具体要做什么。你会使用常量的频繁度将是你从未想象过的。
更加简化的写法
来看一下下面的两行代码,比较一下有何不同:
在我最开始接触Swift的前两个星期,我强迫自己不要在每一行代码最后都添加分号(不过现在写Objective-C的时候我不会加分号了)。
类型推断可以直接根据变量的定义为其指派类型,相比较Objective-C这类冗杂的语言来说,在这里倒是可圈可点。
我们应该使用一致的命名方式,否则其他的开发者(包括你自己)就很难通过极其糟糕的命名来推测其类型:
更加合理的命名是这样的:
还有一个改动就是关于括弧号,他们不再需要配对了:
不过请记住,我们在括号中间写入的部分会被认为是一个表达式,在这里并不代表这样写总是对的。在变量绑定时我们不能像下面这样使用括号:
1 |
if (let x = data){} // Error! |
2 |
if let x = data {} // OK! |
使用类型判断和删除分号及括号并不完全必要,不过我们可以考虑一下用以上建议的方式来写Swift代码,这样的话会提高代码的可读性并且减少一些输入量。
可选值
有多少次我们困惑与函数的返回值该如何设置?我曾经使用过NSNotFound, -1, 0,自定义的返回值来表示返回为空。
现在可选值的出现很好的解决了返回值为空的问题,我们仅需要在数据类型的后面添加一个问号就可以了。
我们可以这样写:
03 |
let car:Car? // Optional value |
10 |
// ACCESSING THE OPTIONAL VALUE *********** |
12 |
var Mark = Person(name:"mark") |
14 |
// use optional binding |
15 |
if let car = Mark.car { |
20 |
Mark.car?.accelerate() |
这是个用了可选值来描述“某人有一辆车”的例子,它表示car这一特征可以是没有的,因为这表示某人没有车。
然后我们可以用optional binding或者unwrap来取得它的值。
如果对于一个属性没有设定为可选值,我们又没有为其赋值的话,编译器会立马不爽快的。
一旦初始化了之后便没有设定非可选属性的机会了。
所以我们应该事先考虑一下类的属性与其它部分的关系,以及在类进行实例化的时候它们会发生什么变化。
这些改进彻底的改变了构思一个类的方式。
可选值的拆包
你会发现可选值这个东西难以理喻,因为你不会理解为什么编译器会提示你在使用之前对其进行拆包。
Mark.car?
我建议你把可选值当做一个结构体(当做结构体的话会好理解一些),其中包括了一个你所设定的值。不过外面包裹了其他东西(wrap)。如果里面的值有定义,你就可以进行拆包(unwrap)然后得到你所想得到的值。否则你就得到一个空值(nil)。
使用感叹号"!"来进行强制拆包而不管其中的值是否有定义,这样做是有风险的,因为如果里面的值没有定义的话应用会崩掉。
委托模式
经过多年的Objective-C和Cocoa代码编写,我想大部分人都对使用委托模式养成了一种嗜好。注意了!我们还是可以继续保留这种嗜好的,下面是一个非常简单的例子:
01 |
@objc protocol DataReaderDelegate{ |
02 |
@optional func DataWillRead() |
06 |
class DataReader: NSObject { |
08 |
var delegate:DataReaderDelegate? |
13 |
delegate?.DataWillRead?() // Optional method check |
15 |
delegate?.DataDidRead() // Required method check |
这里我们使用了一个简单的@optional来替换了使用respondToSelector检测委托方法是否存在。
1 |
delegate?.DataWillRead?() |
请注意我们在协议之前必须加@obj 前缀,因为后面使用了@optional。同时编译器也会在这里报一个警告的消息以防你没有加上@obj。
要实现协议的话,我们需要构建一个类来实现它然后用曾经在OC上用过的方式来指派。
01 |
class ViewController: UIViewController, DataReaderDelegate { |
03 |
override func viewDidLoad() { |
06 |
let reader = DataReader() |
07 |
reader.delegate = self |
10 |
func DataWillRead() {...} |
12 |
func DataDidRead() {...} |
目标-动作模式
另一常用的设计模式:目标-动作模式。我们仍然同样可以像在OC中使用它那样在Swift中实现它。
01 |
class ViewController: UIViewController { |
03 |
@IBOutlet var button:UIButton |
05 |
override func viewDidLoad() { |
08 |
button.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside) |
11 |
func buttonPressed(sender:UIButton){...} |
这里唯一不同的地方就是如何定义一个selector选择器。我们可以变形使用像下面这样的字符串来写方法原型:
1 |
Selector("buttonPressed:") |
单件模式
简直又爱又恨。单件模式依旧是设计模式中最为常用的模式之一。
我们可以用GCD和dispatch_once来实现它,当然还可以用let关键字来实现线程安全。
01 |
class DataReader: NSObject { |
03 |
class var sharedReader:DataReader { |
06 |
static let _instance = DataReader() |
09 |
return Static._instance |
我们来快速浏览一下这段代码:
1、sharedReader是一个静态的复合属性(我们也可以替换为方法)。
2、静态属性不允许在类被实现的时候重构,所以由于内部类型是被允许的,我们可以再这里加入一个结构体。
3、_instance是一个常量,它不会被重写而且保证线程安全。
可以参考下面DataReader单例的用法:
1 |
DataReader.sharedReader |
结构和枚举
Swift中的结构和枚举简直神乎其神,你根本不会在其他的语言里面找到像它们这样的。
它们支持方法:
08 |
println("I‘m " + self.name + " my ID is: \(self.ID)") |
12 |
let pamela = User(name: "Pamela", ID: 123456) |
如你所见在这里的结构体使用了初始化,而且这个是Swift自动创建的(我们可以添加一些自定的实现)。
枚举类型的语法比起我们用过的会稍难。
它的定义需要用到关键字case:
而且枚举并不局限于int型:
2 |
case .orange = "Orange" |
而且还可以用的更复杂一些:
http://c.tieba.baidu.com/p/3392933442
http://c.tieba.baidu.com/p/3392940474
http://c.tieba.baidu.com/p/3392948214
http://c.tieba.baidu.com/p/3392954889
http://c.tieba.baidu.com/p/3392961801
http://c.tieba.baidu.com/p/3392968280
http://c.tieba.baidu.com/p/3392974353
http://c.tieba.baidu.com/p/3392980509
http://c.tieba.baidu.com/p/3392986542
http://c.tieba.baidu.com/p/3392992535
http://c.tieba.baidu.com/p/3392998666
http://c.tieba.baidu.com/p/3393004740
http://c.tieba.baidu.com/p/3393010920
http://c.tieba.baidu.com/p/3393016880
http://c.tieba.baidu.com/p/3393021482
http://c.tieba.baidu.com/p/3393017531
http://c.tieba.baidu.com/p/3393011388
http://c.tieba.baidu.com/p/3393027106
http://c.tieba.baidu.com/p/3393053976
http://c.tieba.baidu.com/p/3393027106
http://c.tieba.baidu.com/p/3393060946
http://c.tieba.baidu.com/p/3393068852
http://c.tieba.baidu.com/p/3393060946
http://c.tieba.baidu.com/p/3393074635
http://c.tieba.baidu.com/p/3393075936
http://c.tieba.baidu.com/p/3393053976
http://c.tieba.baidu.com/p/3393082662
http://c.tieba.baidu.com/p/3393088289
http://c.tieba.baidu.com/p/3393093781
http://c.tieba.baidu.com/p/3393099259
http://c.tieba.baidu.com/p/3393104841
http://c.tieba.baidu.com/p/3393110118
http://c.tieba.baidu.com/p/3393115345
http://c.tieba.baidu.com/p/3393120475
http://c.tieba.baidu.com/p/3393125593
http://c.tieba.baidu.com/p/3393130563
http://c.tieba.baidu.com/p/3393135504
http://c.tieba.baidu.com/p/3393078933
http://c.tieba.baidu.com/p/3393075936
http://c.tieba.baidu.com/p/3393091871
http://c.tieba.baidu.com/p/3393093781
http://c.tieba.baidu.com/p/3393098093
http://c.tieba.baidu.com/p/3393098093
http://c.tieba.baidu.com/p/3393102566
http://c.tieba.baidu.com/p/3393085191
http://c.tieba.baidu.com/p/3393108962
http://c.tieba.baidu.com/p/3393113979
http://c.tieba.baidu.com/p/3393118658
http://c.tieba.baidu.com/p/3393124867
http://c.tieba.baidu.com/p/3393129650
http://c.tieba.baidu.com/p/3393135103
http://c.tieba.baidu.com/p/3393155246
时间: 2024-10-05 20:07:34