//: Playground - noun: a place where people can play

import UIKit

// -----------------------Swift初见--------------------------------------
// 简单输出
print("hello, world")
// print可以自定义连接符或者自定义结束符
print(1, 2, 3, 4, separator: "-")
print(1, 2, 3, 4, terminator: "")
print(1, 2, 3, 4, separator: "->", terminator: "->End\n")

// let声明常量,var声明变量
let myConstant = 11

var myVariable1 = 42
myVariable1 = 56

// 可以让编译器推断常量或者变量的类型,也可以自己显式指定
var myVariable2:Double = 6

// 值永远的不会被隐式转换为其他类型,必须显式转换
let string1 = "the label is"
let integer1 = 94
let string2 = string1 + String(integer1)

// 把值转换为字符串的另一种写法
let string3 = "the label is \(integer1)"

// 数组和字典都是用[]创建
var list1 = ["apple", "banana", "orange"]
list1[2] = "pear"

var dic = ["class": "2班", "grade": "1年级"]
dic["class"] = "3班"

// 创建一个空数组或者字典
let emptyArray = [String]()
let emptyDictionary = [String: Float]()

// 如果数组或者字典的类型已经被推断出来,就可以用[]或者[:]清空数组或者字典
list1 = []
dic = [:]

// for和if后面的条件小括号可以省略,但是语句的大括号不能省略
// Swift3中已经不支持++和--,只能 += 1和 -= 1
// if中必须是布尔表达式,不会隐性和0比较
let list2 = [1, 2, 3, 4]
var cnt = 0
for tempitem in list2 {
    if tempitem < 3 {
        cnt += 1
    } else {
        cnt -= 1
    }
}

// 用if和let处理值缺失的情况(用可选值)
// 如果变量的可选值是nil,条件会判断为false,大括号内的语句不会被执行
var optionalName: String? = nil
if let name = optionalName {
    print("hello, \(name)")
}

// ?可以规避实例为nil时,调用实例方法报错的现象,因为当实例为nil时候,因为实例是可选类型,所以语句会直接忽略后面的不再执行,故而不会出现异常(也就是说?前面的值为nil时,?后面的操作会被全部忽略)
// nil不可以用在不是可选值的常量或者变量中,如果一个常量或者变量可能会没有值,那就必须声明为可选值
// 如果声明了可选值但是没有初始化,它的默认值为nil,如果不是可选值,且没有初始化,可以定义,但是必须初始化后才能使用
var myValue: String? = nil

// 如果我们非常确定一个可选值一定有值的话,我们可以用"!"对它进行强制拆包
var myValue2: String? = "hello, everyone!"
print(myValue2!)

// 另一种处理可选值的方法是通过使用??操作符来提供一个默认值,如果不加??,该变量会输出nil
let nickName: String? = nil
let fullName: String = "John"
print("Hi, \(nickName ?? fullName)")  //此时会输出"Hi, John\n"

// switch和case支持任何类型的数据,还支持以下方式:
let vegetable = "red pepper"
switch vegetable {
    case "apple":
        print("1")
    case "banana", "orange":
        print("2")
    case let x where x.hasSuffix("pepper"):
        print("It is a \(x)")
    default:
        print("~~~")
}
// switch语句必须要写default语句,不需要写break语句,因为它匹配成功后就会退出switch语句,不会继续执行

// 使用for-in遍历字典,用两个变量来表示每个键值对,字典里面是一个无序的集合
let dic2 = [
    "apple": [1, 2, 3],
    "orange": [7, 10, 11]
]
for (key, values) in dic2 {
    for value in values {
        if value > 0 {
            //balabala...
        }
    }
}

// 使用while或者repeat while语句
var n = 2
while n < 100 {
    n = n * 2
}
repeat {
    n = n / 2;
} while n > 20

// 不包含上界用..<  包含上界用...
// 如果不希望print换行就写 print("\(i) ", terminator: "")
for i in 0..<4 {
    print("\(i) ", terminator: "")
}
for j in 0...4 {
    print(j)
}

// 使用func声明函数,使用->指定返回值的类型
func greet(person: String, day: String) -> String {
    return "Hi, \(person), today is \(day)"
}

// 我们在写函数的时候,如果不提供参数的标签,那么参数的标签就是参数的名字,我们可以在参数名称前面加上自己想要的文字作为函数的参数标签,如果我们不想使用参数标签的话我们可以在参数名称前面加上"_"
// 下面三个语句,分别使用自定义标签、参数名称以及不使用标签

// 内部使用的时候采用参数名称(内部参数名)
func myfunc1(name: String, Address adr: String) -> Void {
    print("My name is \(name), my address is \(adr)")
}
func myfunc2(name: String, adr: String) -> Void {
    print("My name is \(name), my address is \(adr)")
}
func myfunc3( _ name: String, _ adr: String) -> Void {
    print("My name is \(name), my address is \(adr)")
}
// 外部调用的时候使用的是参数标签名(外部参数名)
myfunc1(name: "John", Address: "1234")
myfunc2(name: "John", adr: "1234")
myfunc3("John", "1234")

// 二进制、八进制、十进制、十六进制
var a1 = 0b100 // 4
var a2 = 0o100 // 64
var a3 = 100 // 100
var a4 = 0x100 // 256
// 十进制指数
var a5 = 1.25e-2 // 0.0125

// 元组:可以将多个类型的值聚合起来: 
// 注意!元组是用小括号括起来的() ; 数组和字典是用大括号括起来的[]
let tuples1 = ("John", 21, 1.78)

// 如果想要分解元组可以这样:
let (name, age, height) = tuples1
print("my name is \(name), my age is \(age), my height is \(height)")

// 如果说只想用name可以用下划线代替想要忽略的值,只指定name变量
let (name2, _, _) = tuples1
print("my name is \(name2)!~~~")

// 元组可以使用类似下标的形式访问,不过是以"tuplesName.0" "tuplesName.1" "tuplesName.2"的形式
print("my name is \(tuples1.0) and my age is \(tuples1.1)")

// 也可以给元组定义标签,这样就可以直接使用标签的名字进行访问啦~~~
let tuples2 = (name: "TomCat", age:"22")
print("hello, my name is \(tuples2.name) and my age is \(tuples2.age)")

// 可以用元组来做到让一个函数返回多个值
func myfunc4(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    let min = scores[0]
    let max = scores[1]
    let sum = 0
    return (min, max, sum)
}

// 函数可以带有可变个数的参数
func func8(arr: Int...) -> Int {
    var sum = 0
    for number in arr {
        sum += number
    }
    return sum
}
func8()
func8(arr: 1, 2, 3)

// 函数可以嵌套,被嵌套的函数可以访问外侧函数的变量
func func5() -> Int {
    var y = 10
    func add() {
        y += 20
    }
    add()
    return y
}

// 函数可以作为返回值
func func6() -> ((Int) -> Int) {
    func func7(number: Int) -> Int {
        return 1 + number
    }
    return func7
}

var value6 = func6() //此时value6是func6的返回值类型,func6的返回值类型是一个函数类型,它表示接收一个int类型,返回一个int类型的函数类型
print(value6(7))  // print "8\n"

// 函数可以作为参数
// 如下condition就是一个函数类型的参数
func func9(arr: [Int], condition: (Int) -> Bool) -> Bool {
    for item in arr {
        if condition(item) {
            return true
        }
    }
    return false
}
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
func9(arr: numbers, condition: lessThanTen)

// 闭包
// 函数实际上是一种特殊的闭包,它是一段之后能够被调取的代码
// 可以使用{}创建一个匿名闭包,使用in将参数和返回值类型声明与闭包函数体进行分离
numbers.map({
    (number: Int) -> Int in
    let result = 3 * number
    return result
})

// 更简洁的写法:如果一个闭包的类型已知,比如作为一个回调函数,就可以忽略参数的类型和返回值。单个语句闭包会把它语句的值当作结果返回
let value7 = numbers.map({number in 3 * number})
print(value7)

// 可以通过参数的位置而不是参数名字来引用参数
// 如果一个闭包是作为最后一个参数传给一个函数的时候,它可以直接跟在括号后面
// 当一个闭包是传给函数的唯一参数,可以完全忽略括号
let arr2 = numbers.sorted { $0 > $1 }
print(arr2)

// 使用class来创建一个类
// 使用一个构造函数来初始化类实例,使用init来创建一个构造器
class className1 {
    var value = 0
    var name = "hahaha"
    init(value: Int) {
        self.value = value
    }
    func func10() -> String {
        return "A shape with \(value) sides"
    }
}

// 创建一个类的实例,不是new不是new不是new!!是在类名后面加括号。
// 使用点来访问实例的属性和方法
var instanceName1 = className1(value: 5)
instanceName1.value = 2
var stringName2 = instanceName1.func10()

// 子类在后面加上“:父类名字”就能继承自父类~创建类的时候并不需要一个标准的根类,所以可以忽略父类
// 如果要重写父类的方法,必须使用override标记(如果没有添加override就重写父类方法的话编译器会报错)。编译器也同样会检测override标记的方法是否确实在父类中
class className2: className1 {
    var sideLength: Double
    init(sideLength: Double, value: Int) {
        self.sideLength = sideLength
        super.init(value: value)
        name = "xixi"
    }
    override func func10() -> String {
        print("lalala~")
        return name
    }
}

// 除了储存简单的属性之外,属性可以有getter和setter
class className3 {
    var sideLength: Double = 2
    var perimeter: Double {
        get {
            return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }
}

var instanceName2 = className3()
print(instanceName2.perimeter)
instanceName2.perimeter = 8
print(instanceName2.sideLength)

// willSet和didSet 在设置一个新值之前或之后运行的代码
class className4 {
    var age: Int = 0 {
        willSet {
            print("we will set an new value \(newValue) to age")
        }
        didSet {
            print("we have changed \(oldValue) to \(age)")
        }
    }
}

var instanceName4 = className4()
instanceName4.age = 8
instanceName4.age = 12

// 使用enum创建枚举
enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six
    case Jack, Queen, King
    func simpleDescription() -> String {
        switch self {
            case .Ace:
                return "ace"
            case .Jack:
                return "jack"
        default:
            return String(self.rawValue)
        
        }
    }
}
let ace = Rank.Ace
let aceRawValue = ace.rawValue

// 使用struct创建结构体。结构体和类相似,比如方法和构造器。结构体是传值,类是传引用
struct Card {
    var rank = 1
    func func11() -> String {
        return "hello"
    }
}

// 使用protocol来声明协议
// mutating 关键字用来标记一个会修改结构体的方法
protocol ExampleProtocol {
    var value11: Int {get}
    mutating func adjust()
}
// 类、枚举和结构体都可以实现协议

// Extension 扩展是给已经存在的类,结构体,枚举类型和协议增加新的功能
// 扩展能够增加新功能,但是不能覆盖已有的功能

// 错误处理
// 定义错误类型:
enum PrinterError: Error {
    case OutOfPaper
    case NoToner
    case OnFire
}
// 使用throw关键字来抛出一个错误、使用throws关键字来表示一个可以抛出错误的函数。
// 如果在函数中抛出一个错误,这个函数会立刻返回并且调用该函数的代码进行错误处理
func send(job: Int, toPrinter printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.NoToner
    }
    return "Job sent"
}
// 在do-catch中进行错误处理,使用try标记抛出错误的代码
do {
    let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
    print(printerResponse)
} catch PrinterError.OnFire {
    print("I'll just put this over here, with the rest of the fire")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}
// 错误处理的另一种方法:使用try? 将结果转换为可选的。如果函数抛出错误,该错误会被抛弃并且结果为nil。否则的话,结果会是一个包含函数返回值的可选值
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
// 使用defer代码块表示在函数返回之前,函数中最后会执行的代码

// 泛型

// 可以使用where对参数做出一些约束,比如必须是实现了某一个协议,或者说具有一个特定的父类

【note】Swift初见笔记相关推荐

  1. 【swift学习笔记】二.页面转跳数据回传

    上一篇我们介绍了页面转跳:[swift学习笔记]一.页面转跳的条件判断和传值 这一篇说一下如何把数据回传回父页面,如下图所示,这个例子很简单,只是把传过去的数据加上了"回传"两个字 ...

  2. swift学习笔记《5》- 实用

    title: swift学习笔记<5>- 实用 date: 2016-09-21 21:39:00 categories: 学习笔记 Swift学习 tags: Swift 1.setVa ...

  3. Swift学习笔记(4)使用UIImagePickerController实现从设备图片库和照相机获取图片

    Swift学习笔记(4)使用UIImagePickerController实现从设备图片库和照相机获取图片 设备图片库和照相机是图像的两个重要来源,使用UIKit中提供的图像选择器UIImagePic ...

  4. Swift tips 笔记

    Swift tips 笔记 CaseIterable协议 enum遵守了CaseIterable协议可以实现遍历枚举值 enum Season : CaseIterable {case spring, ...

  5. swift学习笔记之一——初见swift

    为什么80%的码农都做不了架构师?>>>    注:使用xcode6,启用调试bug提示输入密码,可在终端输入DevToolsSecurity -enable 解决 //====== ...

  6. 【note】the swift programming language Swift教程笔记

    // ------–Swift教程--------------- 要么变量初始化让其可以推断出类型,要么直接指定一个类型,不可以写: var a 这样的语句,会让系统不明白a到底是什么类型的变量 允许 ...

  7. Swift学习笔记8--Optional Chaining

    Optional Chaining 自判断链接(Optional Chaining)是一种可以请求和调用属性.方法及子脚本的过程,它的自判断性体现于请求或调用的目标当前可能为空(  nil ).如果自 ...

  8. Swift学习笔记 ——(一)

    前言 作为一个前端开发者,经常与javaacript(以下简称:js)打交道.最近想了解一下ios开发,前两天看了一下objective-c(以下简称:oc),相对于js来说还是有很多不同的,但是语言 ...

  9. swift基础笔记4-类和结构体

    类和结构体对比 类和结构体是人们构建代码所用的一种通用且灵活的构造体.我们可以使用完全相同的语法规则来为类和结构体 定义属性(常量.变量)和添加方法,从而扩展类和结构体的功能. Swift 并不要求你 ...

最新文章

  1. java多张图片合成一张_OLIS 多张图片合成分享
  2. Nova 的高性能虚拟机支撑
  3. centos安装kvm
  4. C语言atoi()函数:将字符串转换成int(整数)和sprintf和memset
  5. 领域应用 | NLP 和知识图谱:金融科技领域的“双子星”
  6. java 使用json-lib 对象,String,json互转
  7. Judy Beta 第10天
  8. vue 原型设计 拖拽_设计即开发,如何打通软件研发的“任督二脉”?
  9. java maxheap_Java底层PriorityQueue 优先队列——基于MaxHeap最大堆
  10. [Java] 蓝桥杯PREV-5 历届试题 错误票据
  11. Hadoop常见问题及解决方法
  12. 1. Window环境下 - 开发环境的配置: (安装Android Studio 2.1)
  13. perl软件使用报错总结
  14. VS2017配置opencv-c++
  15. android 常用机型尺寸_android手机屏幕密度和逻辑尺寸
  16. python爬虫随心所欲地爬取百度图片
  17. 程序员容易发福的原因及解决办法
  18. 无法加入域,隶属于域,工作组选项为灰色
  19. 机器学习之手写字体(digits)识别——利用sklearn实现
  20. python对异常捕获的操作

热门文章

  1. android真实项目教程(七)——梦醒边缘花落_by_CJJ
  2. Android UI开发第四十一篇——墨迹天气3.0引导界面及动画实现
  3. 百度地图LBS云存储自定义poi热点
  4. 瞬间之美:Web 界面设计如何让用户心动
  5. 数据结构之各排序算法
  6. linux curl 命令(转)
  7. Linux系统定时任务Crond
  8. [Android自定义控件] Android Scroller工具类和GestureDetector的简单用法
  9. .NET文档生成工具ADB[更新至2.3]
  10. MBA 案例:一个叫花子做的策划