简述如何从Objective-C到Swift过渡

http://blog.csdn.net/dahuagogo/

本篇文章简述了如何从Objective-C向Swift过渡。话不多说,开门见山。

注意:本文讨论的开发环境为Xcode
6 beta 2版本。

单一文件结构 VS 接口-实现

最值得一提的一大改动便是在Objective-C中“[接口].h/[实现].m”这种文件结构被取缔了。

其实我本人是很支持这种文件结构的,因为通过接口文件来获取及共享类特性的方式相当安全而且简单,不过现在不得不面对它不复存在的现实了。

在Swift中并不存在接口与实现分割成两个文件的现象,我们仅需要依靠实现来构建一个类就行了(并且在写的时候甚至不可能添加关于可访问性的修改)。

如果对于这一改动感到无法忍受的话应注意以下事项:

最为明显的:靠直觉。

我们可以借助漂亮的文档来提高类的可读性。举个例子,我们可以把所有想作为public的要素全部挪到文件开头去,也可以采用扩展来区分public和private。

另一个很实用的办法就是在private的方法和变量命名前加一个下划线‘_‘作为前缀。

下面是混合了以上两种方案的示例:

01 // Public
02 extension DataReader {
03  
04     var data { }
05     func readData(){
06         var data = _webserviceInteraction()
07     }
08 }
09  
10 // Private implementation
11 class DataReader: NSObject {
12  
13     let _wsURL = NSURL(string: "http://theurl.com")
14  
15     func _webserviceInteraction()->String{
16         // ...
17     }
18 }

虽然我们没办法修改类中各元素的可见性,不过我们可以试着让某些访问变得“困难一些”。

一个特殊的方法就是使用嵌套类来把private部分隐藏起来(至少是自动的隐藏),下面是例子:

01 import UIKit
02  
03 class DataReader: NSObject {
04  
05     // Public ***********************
06     var data:String?{
07         get{return private.internalData}
08     }
09  
10     init(){
11         private = DataReaderPrivate()
12     }
13  
14     func publicFunction(){
15         private.privateFunc()
16     }
17  
18  
19     // Private **********************
20     var private:DataReaderPrivate
21  
22     class DataReaderPrivate {
23         var internalData:String?
24  
25         init(){
26             internalData = "Private data!"
27         }
28  
29         func privateFunc (){}
30     }
31 }

我们将private的实现放入一个private常量的实例中,然后用“正常”的类的实现来充当接口。不过private部分并非会真正的隐藏起来,只不过在访问的时候需要加上一个private关键字:

1 let reader = DataReader()
2 reader.private.privateFunc()

问题来了:仅是为了最后要将这些private的部分隐藏起来,就要把代码写得这样怪异值得吗?

我的建议是在可见性的修改出来之前(苹果正在忙这个事),我们还是采用详细的文档或者多少用一点扩展来完成这个事。

常量和变量

在写Objective-C的时候我会很少的使用到const关键字,甚至于我知道有的数据时不会变的。然而在Swift中苹果建议开发者们多花点心思在使用常量(let)而不是变量(var)上。所以请注意要弄明白你的变量的具体要做什么。你会使用常量的频繁度将是你从未想象过的。

更加简化的写法

来看一下下面的两行代码,比较一下有何不同:

1 let wsURL:NSURL = NSURL(string:"http://wsurl.com");
2 vs
3 let wsURL = NSURL(string:"http://wsurl.com")

在我最开始接触Swift的前两个星期,我强迫自己不要在每一行代码最后都添加分号(不过现在写Objective-C的时候我不会加分号了)。

类型推断可以直接根据变量的定义为其指派类型,相比较Objective-C这类冗杂的语言来说,在这里倒是可圈可点。

我们应该使用一致的命名方式,否则其他的开发者(包括你自己)就很难通过极其糟糕的命名来推测其类型:

1 let a = something()

更加合理的命名是这样的:

1 let a = anInt()

还有一个改动就是关于括弧号,他们不再需要配对了:

1 if (a > b){}
2      vs   
3 if a > b {}

不过请记住,我们在括号中间写入的部分会被认为是一个表达式,在这里并不代表这样写总是对的。在变量绑定时我们不能像下面这样使用括号:

1 if (let x = data){} // Error! 
2 if let x = data {} // OK!

使用类型判断和删除分号及括号并不完全必要,不过我们可以考虑一下用以上建议的方式来写Swift代码,这样的话会提高代码的可读性并且减少一些输入量。

可选值

有多少次我们困惑与函数的返回值该如何设置?我曾经使用过NSNotFound, -1, 0,自定义的返回值来表示返回为空。

现在可选值的出现很好的解决了返回值为空的问题,我们仅需要在数据类型的后面添加一个问号就可以了。

我们可以这样写:

01 class Person{
02     let name:String
03     let car:Car? // Optional value
04  
05     init(name:String){
06         self.name = name
07     }
08 }
09  
10 // ACCESSING THE OPTIONAL VALUE ***********
11  
12 var Mark = Person(name:"mark")
13  
14 // use optional binding 
15 if let car = Mark.car {
16     car.accelerate()
17 }
18  
19 // unwrap the value
20 Mark.car?.accelerate()

这是个用了可选值来描述“某人有一辆车”的例子,它表示car这一特征可以是没有的,因为这表示某人没有车。

然后我们可以用optional binding或者unwrap来取得它的值。

如果对于一个属性没有设定为可选值,我们又没有为其赋值的话,编译器会立马不爽快的。

一旦初始化了之后便没有设定非可选属性的机会了。

所以我们应该事先考虑一下类的属性与其它部分的关系,以及在类进行实例化的时候它们会发生什么变化。

这些改进彻底的改变了构思一个类的方式。

可选值的拆包

你会发现可选值这个东西难以理喻,因为你不会理解为什么编译器会提示你在使用之前对其进行拆包。

Mark.car?

我建议你把可选值当做一个结构体(当做结构体的话会好理解一些),其中包括了一个你所设定的值。不过外面包裹了其他东西(wrap)。如果里面的值有定义,你就可以进行拆包(unwrap)然后得到你所想得到的值。否则你就得到一个空值(nil)。

使用感叹号"!"来进行强制拆包而不管其中的值是否有定义,这样做是有风险的,因为如果里面的值没有定义的话应用会崩掉。

委托模式

经过多年的Objective-C和Cocoa代码编写,我想大部分人都对使用委托模式养成了一种嗜好。注意了!我们还是可以继续保留这种嗜好的,下面是一个非常简单的例子:

01 @objc protocol DataReaderDelegate{
02     @optional func DataWillRead()
03     func DataDidRead()
04 }
05  
06 class DataReader: NSObject {
07  
08     var delegate:DataReaderDelegate?
09     var data:NSData?
10  
11     func buildData(){
12  
13         delegate?.DataWillRead?() // Optional method check
14         data = _createData()
15         delegate?.DataDidRead()       // Required method check
16     }
17 }

这里我们使用了一个简单的@optional来替换了使用respondToSelector检测委托方法是否存在。

1 delegate?.DataWillRead?()

请注意我们在协议之前必须加@obj 前缀,因为后面使用了@optional。同时编译器也会在这里报一个警告的消息以防你没有加上@obj。

要实现协议的话,我们需要构建一个类来实现它然后用曾经在OC上用过的方式来指派。

01 class ViewController: UIViewController, DataReaderDelegate {
02  
03     override func viewDidLoad() {
04         super.viewDidLoad()
05  
06         let reader = DataReader()
07         reader.delegate = self
08     }
09  
10     func DataWillRead() {...}
11  
12     func DataDidRead() {...}
13 }

目标-动作模式

另一常用的设计模式:目标-动作模式。我们仍然同样可以像在OC中使用它那样在Swift中实现它。

01 class ViewController: UIViewController {
02  
03     @IBOutlet var button:UIButton
04  
05     override func viewDidLoad() {
06         super.viewDidLoad()
07  
08         button.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
09     }
10  
11     func buttonPressed(sender:UIButton){...}
12 }

这里唯一不同的地方就是如何定义一个selector选择器。我们可以变形使用像下面这样的字符串来写方法原型:

1 Selector("buttonPressed:")

单件模式

简直又爱又恨。单件模式依旧是设计模式中最为常用的模式之一。

我们可以用GCD和dispatch_once来实现它,当然还可以用let关键字来实现线程安全。

01 class DataReader: NSObject {
02  
03     class var sharedReader:DataReader {
04  
05         struct Static{
06             static let _instance = DataReader()
07         }
08  
09         return Static._instance
10     }
11 ...
12 }

我们来快速浏览一下这段代码:

1、sharedReader是一个静态的复合属性(我们也可以替换为方法)。

2、静态属性不允许在类被实现的时候重构,所以由于内部类型是被允许的,我们可以再这里加入一个结构体。

3、_instance是一个常量,它不会被重写而且保证线程安全。

可以参考下面DataReader单例的用法:

1 DataReader.sharedReader

结构和枚举

Swift中的结构和枚举简直神乎其神,你根本不会在其他的语言里面找到像它们这样的。

它们支持方法:

01 struct User{
02     // Struct properties
03     let name:String
04     let ID:Int
05  
06     // Method!!!
07     func sayHello(){
08         println("I‘m " + self.name + " my ID is: \(self.ID)")
09     }
10 }
11  
12 let pamela = User(name: "Pamela", ID: 123456)
13 pamela.sayHello()

如你所见在这里的结构体使用了初始化,而且这个是Swift自动创建的(我们可以添加一些自定的实现)。

枚举类型的语法比起我们用过的会稍难。

它的定义需要用到关键字case:

1 enum Fruit { 
2   case orange
3   case apple
4 }

而且枚举并不局限于int型:

1 enum Fruit:String { 
2   case .orange = "Orange"
3   case .apple = "Apple"
4 }

而且还可以用的更复杂一些:

01 enum Fruit{

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

简述如何从Objective-C到Swift过渡的相关文章

Objective中调用Swift代码

原创Blog,转载请注明出处 http://blog.csdn.net/hello_hwc 步骤比较简单: 1.在Objective C工程中,创建新文件(command+N),选择Swift文件 2.选择创建bridge-header,后会生成两个文件,一个是bridge-header(这个暂时没用,这个文件是用来将objective c中的接口暴露给swift),一个是swift文件 3.在swift中想要暴露给objective C中的类或者方法前加上@objc关键字(@objc关键字的一

【转载】谷歌酝酿将苹果Swift作为安卓APP主要开发语言

TNW中文站 4月8日报道 安卓操作系统的软件开发语言是Java,而在过去几年中,有关Java的版权,谷歌(微博)和甲骨文之间发生了长期的诉讼.最新外媒消息称,谷歌正在考虑将苹果开发的Swift作为未来安卓软件开发的“一级”语言,此外Facebook.Uber等公司也开始越来越重视Swift的使用. 据美国科技新闻网站TheNextWeb引述知情人士报道,此前苹果Swift转变为开放源码语言,而谷歌.Facebook.和Uber三家公司的代表曾经在英国伦敦开会,专门讨论Swift语言,谷歌决定逐

Object-C与Swift混合开发

Object-C作为Apple的iOS App开发语言服务了许多个年头,2014年Apple推出了新的编程语言Swift,更高效更安全的口号再次吸引了一大批非iOS开发程序员进入,小编认为Swift取代Object-C只是时间问题,在神州这片土地上,毕竟技术普及有些落后,但再有两年左右时间Swift产品链将形成,第三方支持框架逐步完善,Swift必将成为iOS开发主流.目前来看,激进派的现状Swift与Object-C混合开发. Object-C中调用Swift 下面就给大家分享下Object-

swift语言常见的问题和回答

1.如果我是个刚入门的iOS开发者,选swift学习呢,还是选objective-c学习,还是两个都学? 这个可以根据两种情况来决定:1.我想进入公司担任iOS开发的职位    2.我只想做个独立开发者,自己开发app发布. 第一种情况的话,你必须要学Objective-C,现在市面上绝大部分的app都是用oc开发的,从oc到Swift过渡是要很长一段时间的. 当然swift最好也同时要学会. 第二种情况:你不考虑兼容性(iOS7以下版本,后面会提到)的情况下,完全可以只学习swift.不过ob

总结swift语言常见的20个问题和回答

1.如果我是个刚入门的iOS开发者,选swift学习呢,还是选objective-c学习,还是两个都学? 这个可以根据两种情况来决定:1.我想进入公司担任iOS开发的职位    2.我只想做个独立开发者,自己开发app发布. 第一种情况的话,你必须要学objective-c,现在市面上绝大部分的app都是用oc开发的,从oc到swift过渡是要很长一段时间的. 当然swift最好也同时要学会. 第二种情况:你不考虑兼容性(iOS7以下版本,后面会提到)的情况下,完全可以只学习swift.不过ob

Swifter:100个Swift开发必备Tip——互动出版网

这篇是计算机类的优质推荐>>>><Swifter:100个Swift开发必备Tip> Swift实践先行者|Line顶尖iOS开发专家onevcat/喵神重磅力作 MacTalk池建强作序推荐 全实战纯技巧好经验 100招通向高手殿堂 编辑推荐 Swift的易学难精体现在其实际项目暗坑无数,需要同时具备知识.技巧和经验的一定储备,本书试图让你快速到达这一境界. onevcat亲赴WWDC见证Swift发布,是全球第一批研究和实践者.对Swift的理解和运用,既能洞悉全局

六一笔记

一.ajax AJAX的概念就是页面互动无刷新的效果. 例如:你做一个注册页面,因为用户一般都是唯一的,这个时候你就可以选择一个比较人性化的做法,就是使用AJAX技术,当填完信息鼠标移开txtUserName这个文本框的时候 触发一个事件,然后这个事件调用一个JS方法.JS方法里面使用xmlHttpRequest这个对象.就可以异步的调用后来 来完成一个 查询并且判断的过程. 最后返回一个结果 在前面来判断输入的 "用户名是否在!". 二.表单验证 表单验证是javascript中的高

使用vue.js仿一个链家

Vue全家桶+localstorage+socket.io简单仿一个链家 在线预览地址首先上项目和预览地址 https://luxroid.com/lianjia/#/Github地址 https://github.com/mixihome/lianjia 注意 如果要在本地运行安装完依赖之后如果报错请手动使用淘宝镜像安装node-sass和sass-loader 确保可以运行建议使用F12移动端模式预览???? 使用到的技能点Vue.js : 前端页面展示Vuex : 全局状态通信axios

使用Xamarin实现跨平台移动应用开发(转载)

刚在朋友圈看到张善友,转发的一条分享“使用Xamarin实现跨平台移动应用开发”,写的确实很详细得体,从收费到开源,这段时间xamarin受到不少质疑,如此文http://blog.csdn.net/aofengdaxia/article/details/41891945/.当然这篇随笔也是转载的(如果不写成随笔,大伙可能看不到这篇文章).希望那些已经入坑xamarin的开发者能有一个新的认识 原文链接:http://www.infoq.com/cn/articles/mobile-cross-