swift3学习基础教程摘要:

1、OC中nil是指向一个不存在对象的指针。swift中表示任何值的缺省。
2、条件判断的时候,可选行不能为nil;条件不能为false。这样才成立:

    if let f = Int("4"),let s = Int("42"), f < s && s < 100 {print(f)}

3、如果想判断一个非可选型(没有?声明)变量是否为nil。那么就可以把这个声明为隐式解析可选类型(带!)。这时候就可以对变量进行是否为nil判断了。

    var assumedStr:String! = "xxx"if assumedStr != nil {assumedStr.appendContentsOf("xx")}

4、函数可以通过在声明中添加throws关键字抛出错误信息:(错误处理)

    do {try canThrowAnError()}catch{}func canThrowAnError() throws {   }

5、断言,主要用于调试使用:触发断言会终止应用继续执行:

    let a = -1assert(a>=0,"error")

6、 swift中赋值不会返回任何值,所以就避免了oc里有人在if条件里把’==’写成’=’;
swift中的’+’可以对字符串进行操作:”hello”+”world” = “helloworld”;
swift没有了’++’、’–’运算符,用’+=’、’-=’代替,但是有一个需要注意:’a+=1’其实是’a=a+1’的简写,而赋值运算符’=’是没有返回值的,所以swift中’let b = a += 1’是错误的,’a=a+1’没有返回值,即不会给b赋值;
swift中比较运算,元组也可以进行比较,当然Bool值是不允许比较的,所以带Bool值的元组不可以进行比较,元组的比较也是逐个元素进行比较的;
swift中空合运算符’??’是专门针对可选型的三目运算符,’a ?? b’是’a != nil ? a! : b’ 的简写,但是有一点需要非常清楚,a一定要是可选型,不然这个运算符就没有意义了,因为理论上非可选型的值是永远不会为nil的,也就没有这种判断的必要了。
swift还有一个坑需要说明一下的就是’|’运算符。我们在OC里经常会用到这个运算符,尤其是枚举类型的时候,比如设置navigationBar的样式。swift是没有这个运算符的,但是在需要用到多个值修饰的时候,直接使用’[]’就好了: self.navigationController!.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.whiteColor(),..]
7、swift数组,两个数组相加创建一个新的数组,但是这两个数组类型必须得一样;swift多了一个Set集合类型;
8、 swift3 for循环只能使用for in;
新的repeat..while和do..while 作用是一样的,且swift3没有了do..while;
swift3中,switch中case不需要显示地使用break跳出,但是每个case都必须有一条语句,否则就是无效的。所以case也可以同时满足多个条件(复合匹配),每个条件用逗号隔开;case里也可以是元组,这个时候就可以表示点、面积了:

    let point = (1,1)switch point {case (0,0):print("原点")case (_,0):print("x轴")case (0,_):print("y轴")case (-2...2,-2...2):print("在[4*4]的面积里")default:print("\(point)")}

case里也可以进行值绑定,将匹配的值绑定到一个临时的常量或者变量里,在case分支内就可以对其进行操作:

    let anotherPoint = (2,0)switch anotherPoint {case (var x, 0):x += 2print("x轴:\(x)")case (0, var y):print("y轴:\(y)")default:print("\(point)")}print("\(point)")

case里的判断也可以使用where进行一些额外的条件判断:

    let yetAntherPoint = (1,-1)switch yetAntherPoint {case let(x,y) where x == y:print("在x==y的分角线上")case let(x,y) where x == -y:print("在x==-y的分角线上")default:print("\(point)")}

switch中case不需要使用break让它跳出case,但是也可能需要执行下一个case的情况。所以新的关键字:fallthrough就是用来处理这种情况的;
swift中除了if条件判断外,新的guard也是条件判断,guard语句总是带一个else从句。如果条件为false则执行else里的语句,为true则跳过执行后续语句
9、检测API可用性:后面那个*是必须的

    if #available(iOS 10, *) {print("可用")}

10、多重返回值函数:返回值可以是可选型

func minMax(array:[Int])->(min:Int,max:Int)? {if array.isEmpty {return nil}var currentMin = array[0]var currentMax = array[0]for value in array[1..<array.count] {if value < currentMin {currentMin = value}else if value > currentMax {currentMax = value}}return (currentMin,currentMax)
}
if let bounts = minMax(array: [9,-2,1,3,1000,29,-12]) {print("min:\(bounts.min),max:\(bounts.max)")
}

11、可变参数函数:可变参数的传入值在函数中为此类型的一个数组,一个函数最多只有一个可变参数:

func averageNum(_ numbers:Double...)->Double {var total:Double = 0for number in numbers {total += number}return total/Double(numbers.count)
}print("\(averageNum(1,2,3,4,5))")

12、输入输出参数:是指传入的参数在函数体内被修改了,修改后的结果在函数体外仍有效果,注意传入的参数必须是var类型的,函数形参用inout关键字修饰:

var someInt = 3
var antherInt = 107func swapTwoInts(_ a: inout Int,_ b: inout Int) -> Int{let temparam = aa = bb = temparamreturn a+b
}
let result = swapTwoInts(&someInt, &antherInt)
print("\(result),\(someInt),\(antherInt)")

13、函数类型:像其他基础类型一样的类型,如普通参数一样使用:

func add(_ a:Int,_ b:Int) -> Int {return a + b
}var mathFunc:(Int,Int)->Int = add
print("\(mathFunc(1,2))")
//mathFunc的类型就是:(Int,Int)->Int.

函数类型作为参数:

func printMathFunc(_ mathFunc1:(Int,Int)->Int,_ a:Int,_ b:Int){print("\(mathFunc1(a,b))")
}
printMathFunc(add, 3, 4)

函数类型作为返回值:

func stepForward(_ input:Int)->Int{return input+1
}
func stepBackward(_ input:Int)->Int{return input-1
}
func chooseStepFunc(back:Bool) -> (Int) -> Int {return back ? stepBackward : stepForward
}

14、嵌套函数:即函数里面嵌套函数:

func chooseStepFunc2(back:Bool) -> (Int) -> Int {func stepForward2(_ input:Int)->Int{return input+1}func stepBackward2(_ input:Int)->Int{return input-1}return back ? stepBackward2 : stepForward2
}

15、闭包http://blog.csdn.net/u012297622/article/details/51533130
16、枚举:

enum CompassPoint {case northcase southcase eastcase west
}

swift的枚举成员与OC不同,创建时不会被赋予一个默认的整型值。CompassPoint的成员的类型就是CompassPoint类型,枚举成员本身就是完备的值。但是它们也有隐式原始值,当使用字符串作为枚举类型的原始值,每个枚举成员的隐式原始值为该枚举成员的名称:
CompassPoint.west.rawValue 值为 “west”
17、结构体是值类型,类是引用类型。将一个结构体声明为一个常量,则结构体里的属性都是常量;将一个类声明为常量,类的属性不会都成为常量,而是保持原来的存储属性。
lazy延迟属性:必须是变量,因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成前必须要有初始值,因此无法声明成延迟属性。
计算属性:是提供了getter和一个可选的setter的属性。setter可以使用默认的newValue。计算属性必须用var定义。
属性观察器:每次属性被设置值的时候都会调用属性观察器:willSet、didSet
static:在class里也可以用class关键字代替,其实就相当于类方法一样的效果。
18、mutating:实例方法中修改值类型(主要是结构体和枚举),因为默认情况下,值类型的属性不能在它的实例方法中被修改;给隐含的self赋值:

struct Point {var x = 0.0,y = 0.0mutating func moveBy(x:Double,y:Double){self.x += xself.y += y}
}
var somePoint = Point(x:1.0,y:1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("point:\(somePoint.x),\(somePoint.y)")
enum TriStateSwitch {case off,low,highmutating func next() {switch self {case .off:self = .lowcase .low:self = .highcase .high:self = .off}}
}
var overLight = TriStateSwitch.low
overLight.next()
overLight.next()

19、类型方法:在func关键字前面加上static,来指定类方法。类还可以用关键字class来允许子类重写父类的方法实现:

struct LevelTracher {static var high = 1var current = 1static func unlock(_ level:Int){if level > high {high = level}}static func isUnlocked(_ level:Int)->Bool{return level<=high}@discardableResult //可以忽略返回值mutating func advance(to level:Int)->Bool{if LevelTracher.isUnlocked(level) {current = levelreturn true}else{return false}}
}

20、下标语法:下标定义使用subscript关键字,它通过指定一个或多个输入参数和返回类型;与实例方法不同的是下标可以设定为只读或读写。分别由getter和setter实现,同样setter有一个参数newValue,当然也可以不指定参数,它就会有一个默认的newValue,而如果是只读的话,get关键字也是可以省略的:

struct TimesTable{var multipliter:Intsubscript(index:Int)->Int{return multipliter * index}subscript(index:Int,index2:Int)->Int{get{return multipliter * index * index2}set{print("newValue:\(newValue)")multipliter = newValue}}
}var m = TimesTable(multipliter: 2)
m[0]
m[1,2]
m[0,1] = 6

21、继承:
可以将继承来的只读属性重写成读写属性,提供getter和setter。但是,不可以将继承来的读写属性重写为一个只读属性;
不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。因为这些值是不可以被设置的;
此外,不可以同时提供重写的setter和重写的属性观察器;
防止重写,可以通过把方法、属性或下标标记为final来防治被重写,被final标记了的class是不可以被继承的。
22、为存储型属性设置默认值或在构造器中赋值时,它们的值是被直接设置的,不会触发任何属性观察器。构造过程可以给常量复制,一旦构造过程结束,那么它将不可被修改。结构体有逐一成员构造器。
23、引用计数:每一次赋值,引用计数加一:

class Person {let name:Stringinit(name:String) {self.name = nameprint("\(name) is being initialized")}deinit {print("\(name) is being deinitialized")}
}var refrence1:Person?
var refrence2:Person?
var refrence3:Person?
//当创建一个类的新实例的时候,ARC会分配一块内存来存储该实例信息
refrence1 = Person(name: "John") //引用计数1
refrence2 = refrence1 //引用计数2
refrence3 = refrence1 //引用计数3
refrence1 = nil //引用计数2
refrence2 = nil //引用计数1
refrence3 = nil //引用计数0 释放内存

实例间的循环强引用:

class Person {let name:Stringinit(name:String) {self.name = name}var apartment:Apartment?deinit {print("\(name) is being deinitialized")}
}
class Apartment{let unit:Stringinit(unit:String) {var tenant:Person?deinit {print("Apartment\(unit) is being deinitialized")}
}
//这样赋值之后,产生循环强引用。
var john = Person(name: "John")
var unit4 = Apartment(unit: "4A")
john.apartment = unit4
unit4.tenant = john

解决实例之间的循环强引用——用无主引用和弱引用:相互之间的两个属性的值都允许为nil,并会潜在的产生循环强引用。这种场景最适合弱引用来解决;而一个属性的值允许为nil,而另一个属性的值不允许为nil,这也可能产生循环强引用。这种场景最适合无主引用来解决。

//弱引用
class Apartment{let unit:Stringinit(unit:String) {weak var tenant:Person? //注意这里的Person和Apartment都是可选性的。deinit {print("Apartment\(unit) is being deinitialized")}
}

然而还有一种场景,两个属性都必须有值,并且初始化后永远不会为nil。这种场景下,需要一个类使用无主属性,另外一个类使用隐式解析可选属性。
24、可选型:访问可选类型下标?是在[]之前:test[“dave”]?[0]
25、错误处理:在返回箭头->前添加throws关键字表示该函数、方法或构造器可以抛出错误,并将错误传递到函数被调用时的作用域,并且可以一直传下去。但是在每个调用的位置前添加try关键字。然后在最后用do-catch处理:

enum VendingMachineError:Error {case invalidSelection   //选择无效case insufficientFunds(coinsNeeded:Int) //金额不足case outofStock //缺货
}
struct Item{var price:Intvar count:Int
}class VendingMachine{var inventory = ["Candy Bar":Item(price: 12, count: 7),"Chips":Item(price: 10, count: 4),"Pretzels":Item(price: 7, count: 11)]var coinsDeposited = 0func dispenseSnack(snack:String){print("Dispensing \(snack)")}func vend(itemNames name:String) throws {guard let item = inventory[name] else {throw VendingMachineError.invalidSelection}guard item.count > 0 else {throw VendingMachineError.outofStock}guard item.price <= coinsDeposited else {throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)}coinsDeposited -= item.pricevar newItem = itemnewItem.count -= 1inventory[name] = newItemprint("Dispensing \(name)")}
}
let favoriteSnacks = ["Alice":"Chips","Bob":"Licorice","Eve":"Pretzels",
]
func buyFavoriteSnack(person:String,vendingMachine:VendingMachine) throws {let snackName = favoriteSnacks[person] ?? "Candy Bar"try vendingMachine.vend(itemNames: snackName)
}var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection {print("invalidSelection")
} catch VendingMachineError.outofStock {print("outofStock")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {print("\(coinsNeeded) coins")
}

可用try?通过错误转换成一个可选值来处理错误。可用try!来禁止错误传递。
指定清理操作:defer语句是在即将离开当前代码块时执行一系列语句。

let file = open(f)
defer {close()
}

26、类型转换:类型检查用(is)来检查一个实例是否属于特定子类型;可以用类型转换符(as? 或 as! )向下转型;
两个特殊的不确定类型:
. Any : 可以表示任何类型,包括函数类型
. AnyObject : 可以表示任何类类型的实例

var things = [Any]()
things.append(0)
things.append(0.0)
things.append(42)
things.append(3.1415926)
things.append("hello")
things.append((3.0, 5.0))
things.append(Person(name: "fcf"))
things.append({(name:String)->String in "hello"})for thing in things {switch thing {case 0 as Int:print("zero as an Int")case 0 as Double:print("zero as a Double")case let someInt as Int:print("an integer value of \(someInt)")case let someDouble as Double where someDouble > 0 :print("a positive double value of \(someDouble)")case is Double:print("aome other double")case let someString as String:print("a string value of \(someString)")case let (x,y) as (Double,Double):print("an (x,y) point at (\(x),\(y))")case let person as Person:print("an person name is \(person.name)")case let stringConverter as (String) -> String:print(stringConverter("Michael"))default:print("something else")}
}

27、扩展extension:
用extension关键字声明,可以为类添加新的方法、属性、下标、嵌套类型等。甚至可以用扩展添加协议,例如:

extension Person:UITabBarDelegate{
}

28、协议protocol:
协议要求在需要和OC打交道的代码中,协议和可选都要求必须带@objc属性。
29、泛性:

func swapTwoValues<F>(_ a: inout F, _ b: inout F){let temporaryA = aa = bb = temporaryA
}var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
print("\(someInt),\(anotherInt)")

泛型类型:

struct Strack<FCF>{var items = [FCF]()mutating func push(item:FCF){items.append(item)}mutating func pop()->FCF {return items.removeLast()}
}
var stackOfStrings = Strack<String>()
stackOfStrings.push(item: "f")
stackOfStrings.push(item: "c")
stackOfStrings.push(item: "e")
print("\(stackOfStrings.pop())")

扩展泛型类型:

//扩展泛型类型
extension Strack{var topItem:FCF? {return items.isEmpty ? nil : items[items.count - 1]}
}
print(stackOfStrings.topItem ?? "")

类型约束:

//因为不是所有的类型都可以用==判断相等,所以必须约束泛型是符合Equatable协议的类型。因为所有任何遵循该协议的类型必须实现==和!=。
func findIndex<F:Equatable>(_ valueToFind: F, in array:[F])->Int?{for (index, value) in array.enumerated() {if value == valueToFind {return index}}return nil
}

关联类型:

protocol Container{associatedtype ItemTypemutating func append(item:ItemType)var count:Int{get}subscript(i:Int)->ItemType{get}
}
struct IntStrack:Container{var items = [Int]()mutating func push(item:Int){items.append(item)}mutating func pop()->Int{return items.removeLast()}typealias ItemType = Intmutating func append(item: IntStrack.ItemType) {self.push(item: item)}var count: Int{return items.count}subscript(i:Int)->Int{return items[i]}
}

通过where子句为关联类型定义约束:

    func allItemMatch<C1:Container,C2:Container>(_ someContainer:C1,_ anotherContainer:C2) -> Bool where C1.ItemType == C2.ItemType,C1.ItemType:Equatable{if someContainer.count != anotherContainer.count {return false}for i in 0..<someContainer.count {if someContainer[i] != anotherContainer[i] {return false}}return true
}

30、访问控制:
open:
public:
internal:
filepart:
private:

swift3 语法摘要相关推荐

  1. python语言的语法_PYTHON语言常用语法摘要

    Python 语言常用语法 在 Python 中有 4 种类型的数--整数.长整数.浮点数和复数. 使用变量时只需要给它们赋一个值.不需要声明或定义数据类型. 不要 混合使用制表符和空格来缩进, 因为 ...

  2. MySql存储过程基础语法摘要

    Delimiter $$ 默认情况下,不可能等到用户把这些语句全部输入完之后,再执行整段语句. 因为mysql一遇到分号,它就要自动执行.这种情况下,就可以使用delimiter,把delimiter ...

  3. Velocity语法大全

    来自:http://www.cnblogs.com/codingsilence/archive/2011/03/29/2146580.html 一.基本语法 1."#"用来标识Ve ...

  4. Velocity语法使用总结

    Velocity是一个基于java的模板引擎(template engine).它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象.当Velocit ...

  5. Velocity语法介绍

    原文地址:http://www.cnblogs.com/siye1982/archive/2007/11/14/959678.html 一.基本语法 1."#"用来标识Veloci ...

  6. dbartisan mysql_Sybase数据库安全

    0x00 Sybase数据库介绍 简介 Sybase的全称又叫: SAP Sybase Adaptive Server Enterprise (简称ASE或Sybase ASE),继承于MSSQL的原 ...

  7. EasyJWeb-Velocity脚本简明教程

    EasyJWeb-Velocity脚本简明教程 (pdf版) 很多人下载了EasyJWeb的开源应用示例,但是对动态页面模板文件中的标签使用不是很熟悉,这里简单介绍一下.EasyJWeb特定把视图限定 ...

  8. [转帖]Sqlcmd使用详解

    Sqlcmd使用详解 2018年09月17日 13:36:39 吥輕誩放棄 阅读数:3053 版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net ...

  9. Velocity模板引擎的简单使用

    一 简介 Velocity 是一个基于 Java 的模板引擎,它允许任何人仅仅简单的使用模板语言来引用由 Java 代码定义的对象,从而实现界面和 Java 代码的分离,使得界面设计人员可以和 Jav ...

最新文章

  1. 创建型设计模式 之 单例模式
  2. USB hub(221)
  3. 【Java设计模式】GOF32 - 单例模式
  4. IBASE component deletion
  5. DDD战略设计相关核心概念的理解
  6. 乔安监控云存储能存多长时间_干货 | 监控磁盘阵列知识介绍,不了解还不来看看?...
  7. 眼控科技 实习算法工程师面试
  8. admin.php c install,laravel-admin后台的安装
  9. python怎么清空屏幕_python3.6怎么清屏幕
  10. React Native在Android当中实践(一)——背景介绍
  11. springboot读取application.properties中自定义配置
  12. hdu--1181--变形课
  13. 对数周期天线hfss建模_Ansoft HFSS 在设计对数周期天线时的仿真方法-HFSS教程
  14. 《Redis开发与运维》笔记-复制
  15. 一个读取3DS文件的类CLoad3DS浅析Ⅰ
  16. 百万级数据量,千万级数据量是多少,海量数据的优化方案
  17. iOS - 音频后台播放设置及锁屏界面的显示与控制
  18. 关于QT源代码文件的归类
  19. 基于51单片机的智能路灯控制系统(lunwen+设计说明+仿真+程序)
  20. 求职路艰辛,深圳天瑞地安助力求职人对工作感到无忧

热门文章

  1. TIA博途如何完全卸载西门子 STEP 7 (TIA Portal) 软件?
  2. 算法笔记 最大公约数、最小公倍数、素数(质数)
  3. 零钱通项目(两个版本)含思路详解
  4. 3个方案,绕过微信小程序官方审核
  5. Paper/CV之IA:《First Order Motion Model for Image Animation图像动画的一阶运动模型》翻译与解读
  6. 欧能智能电销机器人为颠覆电销行业而来
  7. 推荐一款全能PDF编辑神器:PDFelement Pro Mac中文版
  8. 计算机考研856学校,18届北京科技大学856环境学姐,目前已录取,分享一下考研经...
  9. win10输入法看不见选字框_win10系统玩LOL打字看不到候选框如何解决?
  10. 人工智能未来发展趋势