Swift学习笔记(一)--基础与操作符

前言

已经很久没有在上更新了, 最近一直在忙于开发业务, 实在没有太多时间来沉淀, 再机上比较懒, 所以就一直没有更新了. 好不容易看了一些和绘图性能相关的东西, 但是因为有的大牛已经讲的比较清楚了, 所以也不多赘述什么了, 有兴趣的可以去看YYKit作者写的iOS 保持界面流畅的技巧, 任何关注绘图性能的同学都应该仔细读读这一篇博客

原因

Swift目前已经到了2.1版, 总算是相对稳定了, 之前有关注, 但是并不打算快速切入, 毕竟只是初版, 之后改动的可能性也是很大的, 加之那个时候切入, 其他的小伙伴也不一定愿意接受, 到时候只能自己维护自己的代码, 还要去改别人的代码, 要切换思维, 还是很浪费时间且没有效率的事情.

稍微谈一下我被Swift吸引的地方吧, 一个是optional value, 一个是面向协议编程, 还有就是extension

我目前也在学习中, 资料是苹果自己出的资料包括iBooks里面的和WWDC的视频, 我也会跟着资料一篇篇讲下去, 讲一些我觉得比较关键的点或者是需要注意的地方. 到时候会持续更新, 欢迎大家一起探讨, 有误之处还请大家指正.

基本变化

  1. 语法风格完全脱离了ObjC, 与Java类似了
  2. 每一条语句不需要;结尾了, 但是结尾也不会报错, 大多数情况下;都没有什么用了, 还有就是对空格要求严格一些了, 有些地方必须要空格,不然会报错的
  3. 没有宏定义了
  4. 条件判断不需要括号包围了
  5. 增加了大量的关键字, 不用也可以, 但是用了会使得代码很简洁易懂
  6. 去掉了block, 引入了closure(闭包), 其实差不多的作用, 就是写法不同
  7. 没有了id类型, 换成了AnyObject
  8. switch的匹配更加灵活强大, 而不仅限于ObjC里面的整数, 而且对每个case都是自动添加break
    ...
    还是不一一列举了, 毕竟是一门全新的语言, 一直举下去也没什么意义, 还是直接切入正题吧. PS: 大家多用playground来测试代码吧 还是很方便的, 就是代码多了会慢一点

基础篇(The Basics)

  1. Swift中用var来声明变量, let来声明常量. 导致了Swift里面只有Array类型, 没有MutableArray类型(其它的集合类型也是一样), 因为var则代表可变, let则代表不可变. 例如:
var varArray: Array = [AnyObject]()  // 初始化一个空数组, 可以看到, AnyObject就代表着id
varArray.append(1)  // 插入一个整数, 注意, 这里不需要@1, 在Swift Int也是一个对象(不是int)
varArray.append("2") // 字符串也不需要@了
let constArray: Array = [1,2,3] // 不可变数组
constArray.append(3) // error: 不可以向不可变的数组插入元素
  1. 类型推导: 声明变量如果赋了初值, 那么就可以省略掉后面的类型, 例如:
    var number = 1 // 编译器通过 = 1来推导出number类型为Int

  2. 变量名支持Unicode编码字符, 这个我觉得没什么用, 应该没有人会真的用吧?

  3. 打印函数: print, 与C++类似, 支持重名函数, 所以print有多种用法, 但是都比较容易懂, playground实验一下就好, 个人感觉还是很方便的, 例如:

let name = "Ryan"
print("My name is \(name)") // 直接用\(variable)的方式直接代入变量
  1. 之前说了分号(;)很少用了, 代表还是有用的地方的, 比如你要在一行里面执行多条语句,就用分号(;)分割

  2. Bool值由YES,NO改为了更加常见的true和false, 同时整数0与非0不能再代表false和true了, 因为Int没有实现BooleanType协议, 这是苹果故意的, 因为你自己extension Int: BooleanType的话, 编译器会明确告诉你, 不允许这么干, 应该是苹果想开发者更显式的写明条件, 避免出现意外的错误

  3. 元组(Tuples)
    元组是一个很棒的东西, 以前在写C语言的时候, 因为返回值只能返回一个东西, 所以还要特意传入一个变量的地址来写入额外的信息, 或者返回一个结构体, OC里面也差不多是这样的, Swift引入了元组就更加强大了, 可以返回多个值, 用()包起来就可以了, 我估计其实是编译器帮我们实现了一个结构体, 例子:

let http404Error = (404, "Not Found") // 默认用http404Error.0/.1来访问404和"Not Found", 如果要指定, 则let http404Error = (code:404, reason:"Not Found"), 当然.0和.1还是可用的.
// 通过数据的访问形式, 我们的确是可以猜测其实就是编译器自己实现了一个结构体

Tip:元组在用法可不止这些, 还可以写出最简单的交换2个变量的值的代码. 以前我们都是, t = a, a = b, b = t 这种类型的写法, 整型还有更简单的写法, 但是用元素就是一行代码:
(a,b) = (b,a)

  1. Optionals: (我还是保持原文吧, 翻译为可选类型总是感觉很奇怪).
    这个东西其实和ObjC新引入nullable差不多, 就是告诉开发者这个东西可能是为nil, 你要好好判断一下, 如果不判断就用, 首先会有编译报错, 告诉你要用感叹号(!)来获得这个值(数据叫做Unwrapping), 然后你解决了这个问题, 但是它其实可能是为空的, 到时候就会导致runtime error, 直接给挂了. 所以, 苹果说Swift的安全, 这是其一, 例子:
var serverResponseCode: Int?
serverResponseCode = 1
//var code: Int = serverResponseCode // error: 要用!来取值

  if convertedNumber != nil {  // 先判断, 后使用
    print("convertedNumber has an integer value of \(convertedNumber!).")
}

至于optional binding, 其实就是赋值一次, 省略了感叹号(!)但是加了一个if let(if let得到的是常量, 所以也会有if var的), 如: // 1.30更新, 增加if var

var possibleNumber = "a12"
if let actualNumber = Int(possibleNumber) {
    print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {
    print("\'\(possibleNumber)\' could not be converted to an integer")
}

正如官方而言, Optional value是一个黑盒子, 在使用之前不之前里面是有东西还是空的, 这也就是是为什么你要用!来取值, 不然你取的就是这个盒子.
// 1.25日添加:
Optional还有一种加感叹号(!)的用法, 这种用法让你直接回到了ObjC的写法上了, 不需要额外去拆包, 但是很可惜, Swift对nil发送消息是会crash的, 所以要谨慎, 毕竟这种写法是不安全的. 例如:

var aStr: String!
//aStr.characters.count //runtime error
aStr = "123"
aStr.characters.count // print 3
  1. 错误处理:
    错误处理是一大块内容, 这里先点一下, 按照Swift的设计, 抛出异常在Swift里面应该会用的比ObjC更多, 一个函数通过throws来抛出异常, 调用函数的地方用do, try, catch来捕获, 如:
func makeASandwich() throws {
    // ...
}
 
  do {
    try makeASandwich()
    eatASandwich()
} catch Error.OutOfCleanDishes {
    washDishes()
} catch Error.MissingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

至于为什么要加个do, 而不是Java里面的直接try+catch, 我觉得应该是异常处理其实是比较影响性能的, 所以ObjC是不推荐用异常来处理错误的, 因为能少try的语句尽量少try, 所以上面的例子中, 实际上只对makeASandwich()进行了try, 而eatASandwich()则没有, 这样可以让尽量少的代码在try里面, 提高性能. 哈, 个人猜测...

  1. 断言:
    没什么特别的, 和之前的差不多, 例如:
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")

值得关注的是, 到底什么时候该用断言, 什么时候不该用? 苹果的说法是:
a.下标越界的时候用
b. 如果传入了一个无效的参数, 不满足函数的需求
c. 传入了nil, 但是函数本身需要一个非nil的参数

assertion可以在开发阶段就把问题通过crash的方式暴露出来, 而不是出现奇奇怪怪的结果, 然后一步步断点去查. 当然, 记得在Xcode中设置, release打包中去掉断言crash的选项...

这一部分值得说道的差不多就这么多了, 具体可以参考苹果的文档
里面对数值类型做了很多有意思的介绍, 比如老外喜欢千分位, 1000000要写成1,000,000, 在代码里面1000000不能一眼就看出来是多少, 所以有这样的写法:
var oneMillion = 1_000_000, 估计是编译器看到数值类型有_就直接删掉了.
还有很多有意思的tip, 但是用的地方可能不多就不多说了, 大家自己去探索吧.

基本运算符(Basic Operators)

其实这一章更加简单, 基本上没有差别, 只是Swift和C++一样, 也有也运算符重载, 可以丰富很多写法.
这里只记录一些区别的地方:

  1. 赋值语句不再有返回值, 所以以前在ObjC里面写的
if (self = [super init]) 
{
// ...
}

在Swift里面还这么玩就报错了, 其实这是对原本要写==写成=的一种保护吧

  1. 三目运算符:
    三目运算符不知道各位用的多不多, 我个人用的比较多, 比如我的block执行宏就是
#define RUN_BLOCK_IF_NONNIL(block,...) !(block)?:(block)(__VA_ARGS__);

这里对block进行为空判断, 为空则返回自身, 也就是nil, 否则传入参数执行之.
但是对于第一个参数返回自身省略的写法, Swift是这样的:

let defaultColorName = "red"
var userDefinedColorName: String?  // defaults to nil
var colorNameToUse = userDefinedColorName ?? defaultColorName

用??替换掉了?:
但是, 普通的用法, 也就是:前后都写的, 还是一样的

  1. 求余数(%):
    在C和ObjC里面, %都只能对整数使用, 但是Swift进行了拓展, 可以对浮点数使用了:
8 % 2.5   // 结果为 0.5
  1. 范围操作符:
    也就是表示范围的, 有两种写法: 1...3 代表1, 2, 3, 如果不想包含后面的数字, 就要写成1..<3. (话说之前的版本是用..来代表..<的, 在新版进行了修改)
    除此之外, Swift专门有个Range类型来表示之:
var range: Range = 1...3 // 会被编译器描述成1..<4

其它的操作符基本上的一直的, 想要查看细节可以看[苹果文档](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID60)

你可能感兴趣的:(Swift学习笔记(一)--基础与操作符)