Swift初见
Swift基本类型
Swift的类型是在C和OC的基础上发展而来的,Int是整型;Double和Float是浮点型;Bool是布尔型;String是字符串。类似OC,Swift也提出了三个集合类型:Array、Set、Dictionary;
除了上述比较熟悉的类型,Swift还增加了OC中没有的类型,比如元组(Tuple);Swift还增加了可选(Optional)类型。
Swift是一个类型安全的语言(甚至以此著称),可选(Optional)就是一个很好的例子。Swift可以让你清除地知道值的类型。如果你的代码期望得到一个String,你却不小心传入一个Int,Swift的类型安全机制会在开发阶段发现这个问题,避免在runtime出错。
常量和变量
在OC以及C中,一个值类型或引用类型数据是常量还是变量由关键字const
决定。在Swift中,在没有const这一说喽。
let和var
Swift使用let来声明常量,使用var来声明变量;
声明
Swift在声明一个变量或者常量可以携带类型信息,也可以不携带。
P.S:声明变量/常量时,不指明类型而让Swift编译器隐式处理的这种行为被称为『类型推测』(Type Inference),后文有更详细介绍。
赋值
本来常量和变量是编程语言里非常基础的概念,没啥好讲的,但Swift世界里,有些许不同,在赋值过程中,需要注意:
- 无论是常量还是变量,在定义时都可以没有右值(即没有初始化值,譬如
var a: Int
或let b: NSObject
),在其他语言中,系统往往会在这种情况下为它们分配一个默认值,譬如OC会设置默认值0或者nil;但这在Swift的世界里是不可能的,Swift不会为它们设置任何默认值,无论是在什么时候; - 无论是常量还是变量,在第一次使用(访问)之前必须要保证有与类型匹配的值(譬如,
var a:Int; print("a = \(a)")
是不合法的); - 和其他语言一样,常量只能进行一次赋值,变量可以进行任意多次赋值;但无论何时,赋值时右值都必须与其定义时的类型匹配,Swift不会帮你做任何转换;
第3点意味着:
let aInt: Int = 0; aInt = 5
不合法,常量只能进行一次初始化;var aObject: NSObject; aObject = nil
不合法,右值nil
与NSObject类型不匹配;var aInt: Int; aInt = 0.0
不合法,右值0.0
与Int类型不匹配;
说明:
- 常量/变量使用之前没有初始化/赋值在Xcode的编译错误通常是:『Variable variableName used before being initialized』;
- 常量/变量赋值时类型不对的编译错误是:『Cannot assign a value of type WrongType to a value of type CorrectType』;
总之,一定要深刻理解到Swift是一门类型安全的语言,《The Swift Programming Language》是这么说的:
Swift is a type safe language. A type safe language encourages you to be clear about the types of values your code can work with. If part of your code expects a
String
, you can not pass it anInt
by mistake.
类型推测(Type Inference)
显然,『类型推测』在处理引用类型时非常便利,这会使得代码更简洁;但是在处理值类型时可能会有些许麻烦,譬如1.0推断为float还收double?在这种记忆力不是特别牢靠(不太确认)的情况下最好还是显式写出变量/常量的类型吧。
静态局部变量、静态全局变量、全局变量
「静态局部变量」、「静态全局变量」、「全局变量」这些是C语言里的概念,在Swift似乎不存在。
可选类型(Options)
正如上文所阐述的,Swift是一门『类型安全』的语言,在对对象赋值时,左值类型和右值类型必须匹配,否则无法通过编译;但在OC中,有非常非常多的机会与nil指针打交道,譬如:
- 某个方法/函数返回nil指针,表示返回的对象不存在;
- 某个方法/函数的某个传入参数为nil,表示传入空值;
- 某个strong类型指针赋值nil,表示不再持有原对象;
Swift的创建是基于Objective-C的,何况还得保证与之兼容,必然考虑到了这个问题,Swift中能够赋值nil的类型叫「可选类型」(optional
)。
理解optionals
C和OC中并没有可选这个概念。在OC的对象世界里,一个指针要么对应这一个对象,要么对应着nil;很多时候我们不知道这个指针到底是空指针,还是有一个有效的对象与之对应,所以我们在OC中经常会写大量大量的if
语句判断某个指针是否为空。而在Swift中,不需要这么麻烦,因为它是一门类型安全的语言,NSObject类型变量在运行时一定有一个NSObject对象与之对应,不可能是nil值。想想这个就激动,想象一下,以前在OC中调用具有返回值的方法时经常需要对返回值进行判断,因为必须要考虑它可能返回nil啊,譬如:
NSMutableArray *aArray = [NSMutableArray array];
NSString *aStr = [self aFuckMethod]; // aFuckMethod的实现代码不可见,不知道一定会返回一个NSString
if (aStr) {
[aArray addObject:aStr];
}
如果在Swift中,aFuckMethod的
原型为func aFuckMethod() -> String
,则清晰表明了aFuckMethod方法一定会返回一个非String类型对象,那么上面一段代码就可以省掉那个if语句了;对比Swift,确实感觉到了OC是一个门太落后的语言,太罗嗦了!
回过头来阐述Swift的optional
。简而言之:
You use
optionals
in situations where a value may be absent. An optional says:* There is a value, and it equals x
or* There is not value at all
相对于OC,Swift的optionals
对值类型(譬如整型、结构体)和引用类型(类对象)的处理更具一致性
。在OC中,一个方法要不返回一个对象要不返回nil,后者表示『缺乏一个合法的对象』;然而,这只对对象起作用;对于结构体、基本的C类型或者枚举都不起作用,处理这些类型,OC方法一般会返回一个特殊值(譬如NSNotFound)来暗示值缺失,这种方法会假设方法的调用者知道并有意识对特殊值进行判断。然而,Swift的optionals
可以让你暗示任意类型的缺失,并不需要一个特殊值。
P.S:稍微体会一下,就会意识到Swift的optional
高明多了。
使用optionals
Optional类型默认值
在OC中,若声明一个对象(指针)但不赋值,系统会默认将之设置为nil;在Swift中也类似,对于一个optional,若不对其赋值,则默认为nil,这可不是我瞎说,文档有说明:
If you define an optional variable without providing a default value, the variable is automatically set to nil for you.
P.S:似乎这是Swift唯一为变量/常量设置默认值的时机。
简而言之,你可以对一个optional变量赋值nil,也可以赋值相应的对象。
在OC中,我们经常需要对一个类类型指针进行判断,判断它是否为nil;在Swift中使用optional也不省心,也常常需要写if语句判断,只是Swift中提供了更多丰富的处理方式。
强制解析(Foreced Unwrapping)符!
You can use an if
statement to find out whether an optional contains a value by comparing the optional against nil
. You perform this comparison with the ==
or !=
.
当你确定可选包确实含值之后,你可以在可选的名字后面加一个感叹号!
来获取值。这个惊叹号表示『我知道这个可选有值,请使用它』,这被称为可选值的强制解析
(forced unwrapping),如下:
let strNumber = "42"
var convertNumber: Int?
convertNumber = strNumber.toInt()
if convertNumber != nil {
println("转换后的结果为:\(convertNumber!)")
}
值得注意的是,使用!
来获取一个不存在的可选值会导致runtime error。因此使用!
强制解析前,一定要确定optional
包含一个非nil的值。
总之,一定要记住,惊叹号!
对于optional
而言是『强制解析符』,而不是仅仅是『解析符』,这可不是咬文嚼字,虽然只有两字之差,但意思差远了。
可选绑定(Optional Binding)
使用可选绑定(optional binding)来判断optional
是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在if
和while
语句中来对可选的值进行判断并把值赋给一个常量或者变量,如下:
let strNumber = "42"
if let actualNumber = strNumber.toInt() {
println("转换后的结果为:\(actualNumber)")
}
这段代码可以理解为:
如果strNumber.toInt()
返回的optional
包含一个Int值,则创建一个叫actualNumber的新常量(actualNumber为Int类型)并将可选包含的值赋给它。
这段『可选绑定』的代码显然比前一段『强制解析』的代码要简短一些,可是,我总觉得Swift的这一部分设计不好,晦涩难懂。首先,
下意识里,let actualNumber = strNumber.toInt()
等价两句代码:let temp = strNumber.toInt()
和let actualNumber = temp
,得到的actualNumber应该是一个optional啊,怎么文档给出的解释暗示actualNumber是一个Int类型变量呢?Fuck!
Implicitly Unwrapped Optionals
『隐式解析可选』作为右值?
『隐式解析可选』似乎比普通optional更安全,既然这么好,为什么不放弃前面的普通optional呢?似乎是不行的,文档这么说:
Do not use an implicitly unwrapped optional when there is a possibility of a variable becoming
nil
at a later point. Always use a normal optional type if you need to check for anil
value during the lifetime of a variable.
元组(Tuple)
元组概述
元组(tuples)早已经是很多高级语言(譬如Python)的中重要组成成分了,它用来把多个值组合成一个复合值,而这些值可以是任意类型(无所谓变量还是常量,无所谓值类型还是引用类型,无所谓optional还是non-optional),并不要求是相同类型。
使用元组
分解元组(Decompose Tuple)
Swift中的元组分解(decompose)和Python中差不多,你可以使用如下语法将一个元组分解成单独的常量和变量:
let http404Error = (404, "Not Found")
// http404Error的类型是(Int, String),值是(404, "Not Found") var (status, statusMessage) = http404Error
在decompose时,如果只需要一部分元组信息,使用_
来标记要忽略的部分。
Tuple支持下标操作
可以使用下标访问一个元组中指定的元素,譬如http404Error.0
表示访问上述元组http404Error的第一个元素(值为404的Int型)。
给Tuple元素命名
使用下标访问Tuple元素难免不够完美,毕竟数字太冰冷了;Swift的Tuple还支持给Tuple元素命名,譬如:
let http404Error = (status: 404, message:"Not Found")
println("状态码:\(http404Error.status), 信息:\(http404Error.message)")
理解元组
根据我的理解,Tuple并不算一种类型(事实上Swift中也不存在所谓的Tuple
类型),它更应该看成是Swift所支持的一种语言特性(语法)。Tuple看起来像数组,但显然不同于数组,数组可是一种数据类型,数组包括大量的功能方法,「元组」是不存在所谓的方法的。也正因为如此,元组的使用场景比较单一,一般用来临时组织数据(譬如组织函数/方法的返回值和参数)。
Swift初见的更多相关文章
- Swift 初见
http://numbbbbb.gitbooks.io/-the-swift-programming-language-/chapter1/02_a_swift_tour.html 本页内容包括: 简 ...
- 【Swift初见】Swift词典
顾名思义.当我们仰望的时候,我们将基于索引查找我们需要找到的资源.在swift这同样适用,每个对象包括字典key和value.我们key为了找到当前这个key相应的value.与数组不同的是,字典项字 ...
- 【Swift初见】SourceKitService Terminated
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/weasleyqi/article/details/36162085 心血来潮想试试最新的Xcode6 ...
- 从今天开始学习Swift -- Swift 初见 (转)
原文地址:http://www.cocoachina.com/newbie/basic/2014/0604/8675.html Swift系列文章由CocoaChina翻译小组翻译自苹果的官方文档 ...
- 【Swift初见】Swift数组(二)
在苹果的开发文档中对Array还提供了其它的操作算法: 1.Sort函数: 对数组进行排序.依据指定的排序规则,看以下的代码: var array = [2, 3, 4, 5] array.sort{ ...
- Swift语言快速入门
Swift语言快速入门(首部同步新版官方API文档和语法的Swift图书,确保代码可编译,作者专家在线答疑,图书勘误实时跟进) 极客学院 编著 ISBN 978-7-121-24328-8 201 ...
- Swift语言的基础详解
1.1.关于swift · Swift 是一种适用于 iOS 和 OS X 应用的全新编程语言,它建立在最好的 C 和 Objective-C 语言之上,并且没有 C 语言的兼容性限制.Swift 采 ...
- Swift UI
概述 Apple近日发布了Swift编程语言,Swift是供iOS和OS X应用编程的新编程语言.相信很多开发者都在学习这门新语言. 废话不多说,下面我就来学习使用Swift创建一个简单的UI应用 ...
- Swift -- 中文版两大官方文档汇总
Swift官方文档由CocoaChina翻译小组精心翻译制作而成,目前两本文档中文版已全部完成!在此,我们对所有参与的译者.组织人员以及工作人员表示衷心的感谢!本文为您提供两本文档的在线阅读以及下载! ...
随机推荐
- squirrelsql安装
官网下载安装,第一次安装mac上,失败,后续重启mac看下.重启完后,还是起不来,估计和某些环境冲突,或者缺少环境 使用squirrelsql如何连接hive? http://lxw1234.com/ ...
- C#使用反射机制获取类信息[转]
http://www.cnblogs.com/zhoufoxcn/archive/2006/10/31/2515873.html 1.用反射动态创建类实例,并调用其公有成员函数. //新建一个类库项目 ...
- phonegap工程中修改app的名字
针对phonegap比较高的版本,我的是6.4.0. 在phonegap工程中,当添加了iOS和android平台或多个平台后,工程进行了开发,然后觉得app的名字想修改一下(比如在手机上显示的app ...
- SolidEdge 工程图中如何给零件添加纹理或贴图
格式-检视-勾选纹理 选中一个零件之后,点击格式-面,在纹理选项卡中找到纹理的贴图 最后效果如下图所示,如果不勾选检视纹理,则虽然的确贴图了,但是不显示出来给你看.如果贴图文件没了,也不会显示 ...
- bootstrap3分页
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"% ...
- Odoo车辆管理
odoo车辆管理用于管理公司用车,可以记录以下信息 车辆 车辆的服务合同 车辆的里程 车辆的服务记录 车辆的成本 使用之前,先要进行基本设置 基础设置 维护车辆型号 即维护车辆 ...
- spl_autoload_register的使用
class Loader{ static function loadClass($class) { $class = $class.'.php'; if(file_exists($class)) { ...
- android IPC通信(上)-sharedUserId&&Messenger
看了一本书,上面有一章解说了IPC(Inter-Process Communication,进程间通信)通信.决定结合曾经的一篇博客android 两个应用之间的通信与调用和自己的理解来好好整理总结一 ...
- kubernetes之PDB
系列目录 上一节我们讲到了由于一些人为的或者不可避免的原因,pod可能会中断,而使用Pod Disruption Budget可以最大限度地保证在pod中断发生时集群仍然保持能够接受的状态. 一句话, ...
- H5 手机横竖屏判读
$.fn.screenCheck = function() { var pDiv = $('<div></div>'); pDiv.addClass("screenC ...