swift3.0基础语法

swift 3.0 基础语法

目录

01-变量和常量

02-运算符

03-可选项

04-条件语句

05-循环

06-字符串

07-元组

08-数组

09-字典

10-对象和类

11-枚举

12-属性

13-下标脚本

01-变量和常量

1.1基本数据类型

    1.整数:  Int
    2.浮点数: Double表示64位浮点数,Float表示32位浮点数
    3.布尔类型: Bool,布尔值只有 true 和 false 两种
    4.字符串: String
    5.字符: Character

1.2变量和常量

    1.变量:值能被修改,var 修饰
    2.常量:值不能被修改,let 修饰
var a = 20
a = 10
let b = 20
//b = 10  常量不能修改:error:'b' is a 'let' constant
    1.会自动推导声明的变量或常量的属性
    2.使用【option + 单击】键查看属性的类型
// 1.自动推导类型
let str = "ningcol"
let intValue = 10
let floatValue = 1.2

// 2.指定数据类型
let doubleValue:Double = 10

02-运算符

1基本运算符

var a = 5
let b = 3

// 1.赋值运算符

let c = b

// 2.加减乘除

1 + 2

5 - 3

2 * 3

10.0 / 2.5

2任何情况下都不会做隐式转化,必须以相同类型进行计算

let num1 = 1
let num2 = 2.2
let num3 = Double(num1) + num2

3必须要显式类型的转化

let j = 2.2
let i:Float = 1.2
i + Float(j)

4.求余运算

a % b

5负号运算

let minusB = -b

6.组合赋值运算

a += 2

7.比较运算

1 == 1
2 != 1
2 > 1
1 < 2
1 >= 1
2 <= 1

8.三目运算

let d = a > b ? 100 : 200

9.空合运算

1.空合运算符( a ?? b )将对可选类型 a 进行空判断(可选项内容详见:04-可选项)

2.如果 aName 为 nil,则执行??后面的,否则执行aName(注意??两边都有空格)

var aName: String? = "ningcol"
//var aName: String? = nil
let bName = aName ?? "aNameIsNil"

10.区间运算

    1.闭区间运算符( a...b )定义一个包含从 a 到 b (包括 a 和 b )的所有值的区间
    2.半开区间( a..<b )定义一个从 a 到 b 但不包括 b 的区间

for index in 1...5 {

print(index)

}

for index in 1..<5 {

print("半开区间:\(index)")

}

11.逻辑运算

1.逻辑非(!a):布尔值取反

2.逻辑与( a && b ):只有 a 和 b 的值都为 true 时,整个表达式的值才会是 true

3.逻辑或( a || b ):两个逻辑表达式的其中一个为 tru e ,整个表达式就为 true

let allowedEntry = false
let enteredDoorCode = true

if !allowedEntry {
    print("ACCESS DENIED")
}

if allowedEntry && enteredDoorCode {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}

if allowedEntry || enteredDoorCode {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}

03-可选项

1.可选值

可选值:可以有值,可以为nil(用 ? 表示可选值)

// URL 为可选项
let URL = NSURL(string: "http://www.baidu.com/")

// str 为可选项
var str: String? = "ningcol"

// var 的可选项默认为 nil
var a:Int?
print(a)

2 if let 语句

// if let : 确保 myUrl 有值,才会进入分支
if let myUrl = URL{
    print(myUrl)
}

var aName: String? = "ningcol"
// var aName: String? = nil
var aAge: Int? = 18

if let name = aName,let age = aAge {
    print(name + String(age))
}
// 可以对值进行修改
if var name = aName,let age = aAge {
    name = "lisi"
    print(name + String(age))
    
}

3.guard let

1.guard let 和 if let 相反。表示一定有值,没有就直接返回

2.降低分支层次结构

3.playground不能展示效果,要在函数中展示

// 创建一个类(详见:10-对象和类)
class test{
    func demo(){
        let aNick: String? = "ningcol"
        let aAge: Int? = 10
        guard let nick = aNick ,let age = aAge  else {
            print("nil")
            return
        }
        print("guard let: " + nick + String(age))
    }

}
var t = test()
t.demo()

4.强制解包

// 创建一个数组(详见:08-组数)
var dataList:[String]?
dataList = ["zhangsan","lisi"]
/*********************************************************************
    1.dataList? 表示 datalist 可能为 nil
    2.如果为 nil, .count 不会报错,仍然返回 nil
    2.如果不为 nil,.count执行,返回数组元素个数
    4. ?? 空合运算符(详见:02-运算符)
*********************************************************************/
let count = dataList?.count ?? 0

// 表示 datalist 一定有值,否则会出错!
let cou = dataList!.count

04-条件语句

4.1.if语句

/*********************************************************************
    1.必须要有大括号
    2.没有"非零即真"的概念,只有ture/false
*********************************************************************/
let num = 20
if num > 10{
    print("大于10");
}else{
    print("小于或等于10")
}

4.2switch

/*********************************************************************
    1.值可以是任何类型
    2.作用域仅在 case 内部
    3.不需要 break
    4.每一个 case 都要有代码
*********************************************************************/
let name = "nick"

switch name {
case "nick":
    let age = 18
    print("one  \(age)")
case "fil":
    print("two")
case "Davi":
    print("three")
case "": break  //相当于有一行代码
case "tom","ningcol":
    print("tomAndNingcol")
default:
    print("other")
}

switch分支使用范围

let count = 3_000
var naturalThings:String
switch count{
case 0:
    naturalThings = "数字0"
case 1...3:
    naturalThings = "数字1-3"
case 4...9:
    naturalThings = "数字4-9"
case 10...99:
    naturalThings = "数字10-99"
case 1000...9999:
    naturalThings = "数字1000-9999"
default:
    naturalThings = "数字9999以上"
}
print(naturalThings);

//输出:数字1000-9999

05-循环

5.1 for循环

// 去掉了C语言风格的循环( ..< 区间运算符,详见:02-预算符)
for i in 0..<10{
    print(i)
}

print("----步长循环-----")
// 递增(步数为2)
for i in stride(from: 0, to: 12, by: 2) {
    print(i)
}
print("开始递减")
// 递减
for i in stride(from: 12, to: 0, by: -2) {
    print(i)
}

print("----反序循环----")
let range = 0...10
// 反序循环
for i in range.reversed(){
    print(i)
}

5.2循环结构while

/*
 while语句,只有当 ip<5 为 false 才跳出 while语句
 */
var  ip = 0
while (ip<5){
    print("ip=\(ip)")
    ip += 1
}
//运行结果
//ip=0
//ip=1
//ip=2
//ip=3
//ip=4


/*
 repeat-while 循环,不管pa是多少,先执行一次,在判断,为false 跳出 do while语句
 */
var  pa = 5
repeat{
    print("pa=\(pa)")
    pa += 1
}while (pa<5)
//运行结果
//pa=5

06-字符串

1.String 结构体,效率比对象高,一般推荐使用,支持遍历

2.NSString 继承NSObject

var str:String = "Hello你好"
//var st:NSString = "hah"
// 字节数量
print(str.lengthOfBytes(using: .utf8))
// 字符串长度
print(str.characters.count)
for a in str.characters{
    print(a)
}


// 字符串拼接
let name:String? = "老王"
let age = 80
let location = "隔壁"
print(location + (name ?? "a") + String(age) + "岁")
//  '\(变量名)' 会自动转换拼接
print("\(location)\(name)\(age)岁")


let rect = CGRect(x: 0, y: 0, width: 100, height: 100)
print("\(rect)")

// 格式字符串
let h = 13
let m = 5
let s = 9
let timeStr = String(format: "%02d:%02d:%02d", arguments: [h,m,s])
let timeStr1 = String(format: "%02d:%02d:%02d", h,m,s)

1.在Swift中使用 Range,最好把 String 改成 NSString

2.str.substring(with: Range<String.Index>) 很麻烦

3. '值 as 类型' 作为类型转换

(str as NSString).substring(with: NSMakeRange(2, 5))

let index = str.index(str.startIndex, offsetBy: 3)
str.substring(from: index)
// "123"只是用来取到索引位置
str.substring(from: "123".endIndex)

print("****\(str.substring(from: "123".endIndex))")

str.substring(to: index)

String 使用 Range

let myRange = str.startIndex..<str.index(str.startIndex, offsetBy: 5)
str.substring(with: myRange)

let myRange1 = index..<str.index(str.startIndex, offsetBy: 5)
str.substring(with: myRange1)

07-元组

// 元组的元素个数固定,不允许增加、删除
var stu = (404,"小白")
// 支持嵌套
var msg = ("基本信息", ("李刚",34))
print(stu)
print(msg)

var (a,b) = stu
print(a,b)
//如果仅需要元组中的个别的值,可以使用"_"的方式来处理不需要的值
let (c,_) = stu
print(c)

//通过序号获得元组的值
print("status is \(stu.0)")

// 可以修改
stu.0 = 500

let message = (status: 100, msg:"哈哈")
print("message is \(message.status)  and \(message.msg)")

08-数组

8.1 数组定义

使用let修饰的数组是不可变数组

使用var修饰的数组是可变数组

//方括号 [] 来创建数组
let array1 = ["zhangsan","lisi"]

let array2 = [1,2,3,4,5]

var array3:[Int] // 定义一个数组(没有初始化)
array3 = [Int]() //初始化
//声明空数组,(必须初始化)
let array4 = [String]()  // 等价上面两行代码

let array5:[Any] = ["zhangsan","lisi",20]

var arr3 = [Double](repeating: 0.0, count: 3) //[0.0, 0.0, 0.0]
var arr4 = Array(repeating: 3.0, count: 3)  //[3.0, 3.0, 3.0]

var arr: [String] = ["Alex", "Brian", "Dave"]
print(arr.count)
print(arr[0])

8.2数组遍历

// forin方式
for name in array1{
    print(name)
}
// 遍历数组
for i in 0..<array2.count{
    print(array2[i])
}

//区间遍历
for item in array2[0..<2] {

    print("item\(item)")
}

// 同时遍历下标和内容
print("=====同时遍历下标和内容=====")
for e in array2.enumerated(){
    print(e)
    //offset 下标    element 值
    print("元组 \(e.offset) \(e.element)")
}

//下标和值同时遍历
for (n, s) in array2.enumerated() {
    print(n, "===", s)
}

// 反序遍历
for a in array2.reversed(){
    print(a)
}

// 遍历下标和数值 反序

for (xxx,ooo) in array2.enumerated().reversed() {
    print(xxx,"==",ooo)
}

8.3数组增删改

// 追加
arr.append("ningcol")

// 合并(类型必须一致)
let arr1 = ["Evi","Tank"]
arr += arr1

// 修改
arr[0] = "Tom"
print(arr)

// 删除
arr.removeFirst()
print(arr)

//根据索引删除
arr.remove(at: 2)
print(arr)

// 删除全部并保留空间
arr.removeAll(keepingCapacity: true)
print(arr.capacity)  //数组容量

/***************************容量*************************/
// 容量每次都会在原来基础上 * 2
print("初始容量 \(array3.capacity)")
for i in 0..<8{
    array3.append(i)
    print("--\(array3),容量:\(array3.capacity)")
}

09-字典

01字典定义

//方括号 [] 来创建字典

let dict1 = ["name":"lisi","age":"18"]
// 不同类型必须指明为 any
var dict2:[String:Any] = ["name":"lisi","age":18]


let array = [
    ["name":"lisi","age":"18"],
    ["name":"wangwu","age":8]
]
print(array)
let array1:[[String:Any]] = [
    ["name":"lisi","age":"18"],
    ["name":"wangwu","age":8]
]
print(array1)

print(dict2["age"])

02字典增删改

// 增加
dict2["sex"] = "man"
print(dict2)
// 修改(通过key来取值,key不存在就是新增)
dict2["name"] = "zhangsan"
print(dict2)
// 删除(直接给key进行删除)
dict2.removeValue(forKey: "age")
print(dict2)

03字典遍历

for e in dict2{
    //e 为元组
    print("字典遍历:\(e)  e.key:\(e.key)  value:\(e.value)")
}
// key value 可以随意更改
for (key,value) in dict2{
    //e 为元组
    print("key:\(key), value:\(value)")
}

04字典合并

var dict3:[String:Any] = ["name":"zhangsan","age":18,"sex":"man"]
let dict4:[String:Any] = ["name":"ningcol","height":50]
// 如果key存在修改  不存在会增加
for e in dict4{
    dict3[e.key] = dict4[e.key]
}
print("合并dict:" + String(format: "%@", dict3))

10-对象和类

// 创建一个类
class Shape {
    var numberOfSides = 0
    // 定义 simpleDescription 无参方法,返回值为 String 类型
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

// 实例化
var shape = Shape()
// 赋值
shape.numberOfSides = 7
// 调用方法
var shapeDescription = shape.simpleDescription()

//  构造函数来初始化类实例
//如 oc : 
/*
 - (instanceType) initWithName:(NSString *)name;
 */
class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    //自定义构造函数
    init(name: String) {
        //构造函数内的名字和类属性名字一样,需要使用 self 调用属性
        self.name = name
    }
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

//let name = NamedShape(name: "name")
//name.simpleDescription()

重写父类方法

class Square: NamedShape {
    var sideLength: Double
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }
    func area() ->  Double {
        return sideLength * sideLength
    }
    // 使用 override
    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)."
    } }
let test = Square(sideLength: 5, name: "my test square")
test.area()
test.simpleDescription()

01-if let 语句

/*
 可选类型在每次访问的时候都会提取并检测它的值是否存在,但有时候根据程序结构可以推断可选量在首次赋值后必然存在值,这时候就不需要每次验证值是否存在了,我们可以使用!进行强制隐式解包来获取它的值,或者使用 if let 语句隐式解包
 */

//强制隐式解包
let possibleString: String? = "An optional string"
print(possibleString!)//解包,确定 possibleString 值一定存在,不需要验证

//隐式解包

if let value = possibleString {
    let stringValue = value
    
}

02-guard 语句

//grard 语句只会执行一个代码块
//guard 语句判断其后表达式的布尔值为 false 时才会执行之后的代码块里的代码,若为 true, 则跳过整个 guard 语句

//guard 函数只能用在函数里面

func checkLogin(person: [String : String]) {
    
    //检查账号密码,如果用户名为空,则不能登录
    guard let uname = person["uname"] else {
        
        print("用户为空,不能登录")
        return
    }
    //检查账号密码,如果密码为空,则不能登录
    guard let pawd = person["pawd"] else {
        
        print("密码空,不能登录!")
        return
    }
    
    //账号和密码都存在,方可进登录
    print("用户名:\(uname) 密码:\(pawd)")
    print("登录中请稍后...")
    
}

03-自定义构造函数

class Person: NSObject {
    var name : String?
    var age : Int = 0
    
    override init() {
        // 在构造函数中,如果没有明确super.init(),那么系统会帮助调用super.init()
        // super.init()
        
        print("------")
    }
    
    // 自定义构造函数不需要 override
    init(name : String, age : Int) {
        self.name = name
        self.age = age
    }
    
    //    init(dict : [String : AnyObject]) {
    //        let tempName = dict["name"]
    //        // tempName是一个AnyObject?,转成String?
    //        // as? 最终转成的类型是一个可选类型
    //        // as! 最终转成的类型是一个确定的类型
    //        name = tempName as? String
    //
    //
    //        /*
    //        let tempAge = dict["age"]
    //        let tempAge1 = tempAge as? Int
    //        if tempAge1 != nil {
    //            age = tempAge1!
    //        }
    //        */
    //
    
    //        if let tempAge = dict["age"] as? Int {
    //            age = tempAge
    //        }
    //    }
    
    //使用 KVC 必须先掉用 super.init()
    init(dict : [String : AnyObject]) {
        super.init()
        
        setValuesForKeys(dict)
    }
    
    override func setValue(_ value: Any?, forUndefinedKey key: String) {
        
    }
}

//@interface Person : NSObject
//
//- (instanceType)initWithName:(NSString *)name age: (int)age
//- (instanceType)initWithDict:(NSDictionary *)dict;
//
//@end


let p = Person()
let p1 = Person(name: "why", age: 18)
print(p1.age)
print(p1.name)

let p2 = Person(dict: ["name" : "why" as AnyObject, "height" : 1.88 as AnyObject, "age" : 18 as AnyObject])
print(p2.age)
print(p2.name)

11-枚举

枚举定义

enum SomeEumeration {
    // 在这里定义枚举
}

//// 定义枚举类型 指定类型
enum RequestType : String {
    case GET = "GET"
    case POST = "POST"
}

以下是地图四个方向的一个例子:

enum MapDirection {
    case North
    case South
    case East
    case West
    
    func simpleDescription() -> String {
        switch self {
        case .North:
            return "North"
        case .South:
            return "South"
        case .East:
            return "East"
        case .West:
            return "West"
        default:
            return String("unknow")
        }
    }
}

//多个成员值可以出现在同一行上,用逗号隔开:
enum MapDirection1 {
    case North,South,East,West
}

//枚举的使用:枚举名称通过点语法获枚举的某一个取值
var directionToHead = MapDirection.West

//一旦directionToHead 被声明为一个 MapDirection类型,我们可以使用更短的点(.)语法将其设置为另一个 MapDirection 的值

12-属性

/*
 1.存储属性
 2.计算属性
 3.类属性
 */

class Student: NSObject {
    // 定义存储属性
    var age : Int = 0
    var name : String?
    
    var mathScore : Double = 0.0
    var chineseScore : Double = 0.0
    
    // 定义计算属性: 通过别的方式计算到结果的属性,称之为计算属性
    var averageScore : Double {
        return (mathScore + chineseScore) * 0.5
    }
    
    // 定义类型属性: 类属性是和整个类相关的属性.而且是通过类名进行访问
    /*
     两种创建方法
     */
    //第一种方法
    static var courseCount : Int = 0
    
    //第二中方法
    class var newvalue: Int {
        return 10
    }
    
    /*
     // 定义方法,可以返回平均成绩
     func getAverageScore() -> Double {
     // 在swift开发中,如果使用当前对象的某一个属性,或者调用当前对象的某一个方法时,可以直接使用,不需要加self
     return (mathScore + chineseScore) * 0.5
     }
     */
}

// 给类属性进行赋值
Student.courseCount = 2

// 创建对象
let stu = Student()

// 给对象的属性赋值
stu.age = 10
stu.name = "yz"
stu.mathScore = 78
stu.chineseScore = 59.9

print(stu.age)
if let name = stu.name {
    print(name)
}

let averageScore = stu.averageScore

//使用类名调用,对象不可以调用
Student.newvalue
Student.courseCount
/********************************************计算属性***************************************/

/*枚举、类、结构体除了拥有存储属性,还可以定义计算属性。
计算属性不直接存储值,而是提供一个getter和一个可选的setter来间接获取、设置其他属性和变量的值。
 */

//便捷setter声明 如果计算属性的setter没有定义表示新值的参数名,则可以用默认值newValue,

//get:用来取值,封装取值的过程
//set:用来设值,封装设值的过程
// 下面定义三个结构体,来描述一个矩形
class Square {
        // 正方形的宽度
           var width: Double = 0.0
         // 正方形的周长
           var girth: Double {
                 get {
                         // 周长 = 宽度 * 4
                             return width * 4
                     }
                 set {
                         // 宽度 = 周长 / 4
                                width = newValue / 4
                     }
             }
     }
 var s = Square()//1
 s.width = 10//2
 print(s.girth)//3
 s.girth = 200//4
 print(s.width)//5
/*
 第3行代码:调用girth属性的get,输出结果是40
 
 第4行代码:调用girth属性的set,并且把200传递给newGirth参数
 
 第5行代码:输出结果是50
 */


//只读计算属性 只有getter没有setter的计算属性
//只读计算属性总是返回一个值,可以通过点语法访问,但是不能设置
//只读计算属性可以省略get和花括号
// 一个结构体 ,volume计算体积
struct Cuboid{
    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double{
        return width * height * depth
    }
}

let newCuboid = Cuboid(width: 3.0, height: 4.0, depth: 5.0)

/*注意
 1.因为计算属性的值不是固定的,因此只能用var修饰计算属性,不能用let
 2.一个属性不能既是存储属性,又是计算属性
 */

属性的监视器

//属性监视器可以用来监控属性值的变化,每次属性被修改的时候都会被调用,即使新的值和旧的值一样.
//一个属性监视器由 willSet 和 didSet 组成, willSet 在设置新的值之前被调用,新的值作为传参,didSet 在新的值被设置之后调用,会将旧的属性值作为传参.

class Person: NSObject {
    // 属性监听器
    var name : String? {
        // 属性即将改变时进行监听
        willSet {
            print(name)
            print(newValue)
        }
        
        // 属性已经改变时进行监听
        didSet {
            print(name)
            print(oldValue)
        }
    }
}


let p = Person()
p.name = "why"
p.name = "yz"

13-下标脚本

//下标脚本
//swift 通过索引快速取值的一种语法.例如数组的a[0]就是一个下标脚本,通过索引0 快速取值,我们可以在类,结构体,和枚举中自己定义下标脚本
//下标脚本使用subscript 关键字来定义 通过 get ,set 来定义读,写属性,可以只有 get 只读方法.定义
//set 属性时,传入的参数类型和subscript 函数返回的值必须相同
/**subscript(参数名称1: 数据类型, 参数名称2: 数据类型,...)-> 返回值的数据类型 {

     get {
         //返回与参数类型一样的值
     } set (参数名称){
         // 执行相关的赋值操作
     }
}
*/
//代码如下:

class Experience {
    var age: [Int] = Array(repeating: 0,count: 5)
    subscript(index:Int) -> Int {
    
        get {
        
            return age[index]
            
        }set {
        
            age[index] = newValue
        }
    }
}
//可以通过下标脚本来设置获取某一属性的值
var ex = Experience()
//设置第一个脚标的值为5
ex[0] = 5
ex[1] = 6
print(ex[0])
print(ex[1])

/**
 
 下标脚本可以和计算属性一样设置为读写或只读,也就是定义下标脚本时不设置 set 方法,上面的代码是读写形式,下面就使用只读的形式实现使用下标访问属性值的功能
 */

class Experience2 {
    
    var age2: [Int] = Array(repeating: 0,count: 5)
    
    subscript(index:Int) -> Int {
        
        get {
            
            return age2[index]
            
        }
    }
}

//这种情况下,我们只能获取属性值,不能对属性设置值.获取属性值的代码如下

var ex2 = Experience2()
let e0 = ex2[0]
let e1 = ex2[1]

print(e0)
print(e1)

/****************************************************

对之前学习的swift 语法又复习了一下,此文转载简书作者:ningcol 链接:http://www.jianshu.com/p/1c25105bba4f 可以去原作者文章中下载 demo,这里我在原作者文章中又补充了一些基础知识.

***************************************************************/