import Foundation
// 单行注释
// 多行注释(支持嵌套,OC是不支持的)
 
// 常量let,初始化之后就不可改变.
// 常量的具体类型可以自动识别,等号后面是什么类型,它就是什么类型,结束不需加分号.
let teacherName = "名字"
print(teacherName)
 
// 变量var,初始化之后还可以重新赋值
// 可以自动推断类型
var studentName = "名字"
studentName = "外号"
print(studentName)
 
// 支持中文
var 编程 = "语言"
print(编程)
  
// 支持表情特殊字符
var ? = "程序员"
print(?)
 
/***************** 符号/占位符 ******************/
 
// 字符串相加
var string1 = "程序"
var string2 = 123
var string3 = string1 + String(string2) // 强制转换类型
print(string3)
 
// 占位符
let age = 18
print("my age is \(age)")
  
// 指定类型 (为常量或者变量指定一个确定的类型,指定类型后,赋值必须赋相对应类型的值)
let strCount: UInt = 123 // strCount必须为无符号整型
var string: String = "hello swift"
 
// 类型别名 (类似于OC中的typedef)
typealias class02Type = Int
let int1 : Int = 123
let int2 : class02Type = 123
print("\(int1)--\(int2)")
  
// BOOL类型.在OC中非0即真,在swift中没有这个规则,只有true和false
var boolValue1 = true
var boolValue2 = false
  
// 元组(里面元素可以是多种类型)
var cakeInfo : (String , Int) = ("蛋糕",188)
print(cakeInfo.0)
 
// 可选类型(包含两层含义,如果变量有值,那么变量就是这个值,如果变量没有值,那么变量就是nil)
// ? 可选类型
var optionValue : String? = "蓝鸥"
// ! 强制解析,必须在有值得时候才能解析
print(optionValue!)
 
/***************** 字符串和字符 *****************/
 
// 创建字符串(带初始值的)
let string1 = "class"
 
// 创建空字符串
let string2 = ""
let string3 = String()
 
// 判断字符串是否为空
if string3.isEmpty {
    print("空")
}
  
// swift中字符串是值类型,OC中字符串是引用类型
var stringValue1 = "class"
var stringValue2 = stringValue1
 
// 修改stringValue1
stringValue1 += "NB"
print(stringValue1)
print(stringValue2)
 
// 字符串的长度
let stringLength = "hello swift"
print(stringLength.characters.count)
 
for temp in stringLength.characters {
    print(temp)
}
 
// 对字符串进行操作
// 拼接字符串 (+号拼接或者占位符拼接)
var addStr = "hello"
var addStr1 = "\(addStr) world"
print(addStr1)
 
// 字符串的插入
var insertStr = "abc"
insertStr.insert("$", atIndex: insertStr.startIndex)
insertStr.insert("@", atIndex: insertStr.endIndex)
 
// 如果advancedBy()是正,就是前进,是负就是后退
// 如果用了startIndex就不能使用负数,如果用了endIndex就不能用正数,否则就会越界
insertStr.insert("#", atIndex: insertStr.endIndex.advancedBy(-1))
print(insertStr)
 
// 字符串中插入字符串
var insertStr2 = "Hello"
insertStr2.insertContentsOf("swift".characters, at: insertStr2.endIndex.advancedBy(-5))
print(insertStr2)
  
// 字符串的删除
var deleteStr = "123456"
var deleteRange = deleteStr.startIndex...deleteStr.startIndex.advancedBy(2)
deleteStr.removeRange(deleteRange)
print(deleteStr)
  
// 字符串的比较 ==
var compareStr1 = "123"
var compareStr2 = "123"
if compareStr1 == compareStr2 {
    print("相同")
}else{
    print("不同")
}
 
/******************* 集合类型 ********************/
 
// 数组(var代表可变数组,let代表不可变数组)
// 创建带初始值的数组(值的类型要统一)
var arr : [String] = ["iphone","ipad","MacBook"]
 
// 创建空数组
var emptyArr = [Int]() // 数组中只能存Int类型
 
// 判断数组是否为空
if emptyArr.isEmpty {
    print("空")
}
 
// 数组的增加
arr.append("iWatch")
print(arr)
 
// 数组的插入
arr.insert("iPod", atIndex: 1)
print(arr)
 
arr += ["iBook"] // 加号前后数据类型要一致
print(arr)
 
// 数组的删除
arr.removeAtIndex(0)
// arr.removeAll() // 删除的是全部元素,但是数组还是存在的
print(arr)
 
// 数组的修改
arr[0] = "APPLE"
arr[1...3] = ["APPLE1","APPLE2","APPLE3"]
print(arr)
  
// 数组的遍历
for temp in arr {
    print(temp)
}
 
for (tempIndex,tempValue) in arr.enumerate() {
    print("下标:\(tempIndex)->值为:\(tempValue)")
}
 
// 字典
// 创建字典.有初始值的字典
var dict = ["北京":"中国","东京":"日本","巴黎":"法国"]
print(dict)
 
// 没有初始值的字典
var emptyDict = [String: String]()
print(emptyDict)
 
// 判断字典是否为空
if emptyDict.isEmpty {
    print("空")
}
 
// 字典的增加 (输入一个新的键值对)
dict["首尔"] = "韩国"
print(dict)
  
// 字典的删除 (删除key值)
dict.removeValueForKey("首尔")
print(dict)
  
// 字典的修改 (原来的字典中如果有这个键值对,就是修改,如果没有就是增加)
dict["北京"] = "亚洲"
print(dict)
 
// 字典的遍历
for (key, value) in dict {
    print("\(value)的首都\(key)")
}
 
/******************* 控制流 ********************/
 
// for in 循环 (1..<6表示小于6)  (1...6)表示小于等于6
for value in 1...6 {
    print(value)
}
 
// for循环
for var i = 0; i < 10; i++ {
    print("i = \(i)")
}
 
// while循环
var whileValue = 0
while whileValue < 10 {
    print(whileValue)
    whileValue++
}
 
// repeat-while,相当于OC中的do-while
var value = 0
repeat {
   // 循环体
   value++
   print(value)
}while value < 10
 
// 分支语句
var appleValue = 100
if appleValue > 10 {
   print("太贵了")
}else{
   print("太便宜了")
}
  
// switch-case
// 注意:swift不需要break,不会贯穿
// 如果需要贯穿,就要加fallthrough
// 如果case语句不能包含所有的情况,那么必须加上dafault
// case语句至少要有一行代码,如果没有,就必须加上break
var switchValue = 1
switch switchValue {
   case 1:
        print("switchValue = 1")
        fallthrough
   case 2:
        print("switchValue = 2")
    
   case 3:
        print("switchValue = 3")
   default:
        print("空")
}
 
// switch-case 匹配元组
var point = (10, 10)
switch point {
 
case (10, _):// _代表可以忽略这个值
    print("case(10,11)")
case (_, 0):
    print("case(10, 0)")
default:
    print("其它")
}
 
// switch-case 区间匹配
var money = 10
switch money {
case 0...10:
    print("穷屌丝")
case 100...1000:
    print("屌丝")
default:
    print("土豪")
}
 
// 标签语句 (根据标签跳出整个循环)
myWhile:while true {
    for var i = 0; i < 10; i++ {
        if i == 5 {
        break myWhile
        }
        print("i = \(i)")
    }
}
 
/******************* 函数(方法) ********************/
 
/*
func 函数名(参数列表)->返回值 {
// 函数体
}
*/
 
// 无参数无返回值.如果没有返回值->void可以省略
func func1()->Void {
print("hello swift")
}
// 调用
func1()
 
// 有参数无返回值
func func2(cityName:String) {
    print("北京地区属于\(cityName)")
}
// 调用
func2("华北")
 
// 无参数有返回值
func func3()->String{
return "中国"
}
// 调用
var result = func3()
print(result)
  
// 有参数有返回值
func func4(number1 number1:Int, number2:Int)->Int {
    return number1 + number2
}
// 调用
var resultValue = func4(number1: 10, number2: 20)
print(resultValue)
 
// 有参数有返回值  (返回元组)
func func5(number1 number1:Int, number2:Int)->(Int,Int) {
    
    return (number1 + number2, number1 * number2)
}
// 调用
var resultValue1 = func5(number1: 5, number2: 6)
print(resultValue1)
  
// 函数的形参默认是常量,不能修改.如果要修改,需要将形参指定为变量加var
func changeCity(var cityName : String)->Void {
    cityName = "三亚"
    print("周末去\(cityName)")
}
// 调用
changeCity("海南")
  
// 形参改变,实参不变.因为地址不同
// 如果想同时改变形参和实参,需要加inout关键字,同时传入地址,即加&取地址符
func changCity2 (inout cityName1:String, inout cityName2:String) {
     let tempCity = cityName1
    cityName1 = cityName2
    cityName2 = tempCity
    print("city1=\(cityName1)->city2=\(cityName2)")
}
// 调用
var city1 = "北京"
var city2 = "马尔代夫"
changCity2(&city1, cityName2: &city2)
print("实参:city1=\(city1)--city2=\(city2)")
 
// 外部参数名和内部参数名
func cityFunc(cityName1 cityNmae1:String, cityName2:String, cityName3:String) {
    print("\(cityNmae1)->\(cityName2)->\(cityName3)")
}
// 调用
cityFunc(cityName1: "北京", cityName2: "东京", cityName3: "南京")
 
// 函数的嵌套 内部函数只能在内部调用,外部函数只能在外部调用
func outFunc(boolValue:Bool, var number:Int) {
    // 自加
    func addFunc(){
     print("自加\(++number)")
    }
    // 自减
    func jianFunc(){
     print("自减\(--number)")
    }
    // 调用内部函数
    boolValue ? addFunc() : jianFunc()
}
// 调用外部函数
outFunc(true, number: 10)
  
/******************* 可选绑定 ********************/
 
// 用可选绑定来判断intNumber是否有值.如果有值,就将值赋给一个临时变量
var intNumber : Int? = 10
if var intNumber1 = intNumber {
    print(intNumber1)
}else{
    print("没有值")
}
 
var tempString = "中国"
print(Int(tempString))
if let intValue = Int(tempString) {
    print(intValue)
}else{
    print("不是数字")
}
/******************* 枚举 ********************/
// 定义一个枚举,枚举名首字母大写
// 哈希值不会通过我们的改变而改变
enum City:Int{
    case BeiJing = 100
    case NewYork
    case Paris
}
print(City.Paris.hashValue)
// 原始值
print(City.Paris.rawValue)
  
enum City1:String{
    case BeiJing = "北京"
    case NanJing = "南京"
    case ShenZhen = "深圳"
}
print(City1.ShenZhen.hashValue)
// 原始值
print(City1.ShenZhen.rawValue)
 
// tempCity 类型是City1 值是BeiJing 通过rawValue创建了一个类型为City2的变量
let tempCity = City1(rawValue: "北京")
print(tempCity!)
print(tempCity!.rawValue)