Swift

Swift

常量和变量

  • var 定义变量,设置之后可以修改
  • let 定义常量,设置之后不可以修改
  • 语句末尾不用使用 ;
  • 在 Swift 中使用 print() 替代 OC 中的 NSLog,print 的性能更好
  • let定义常量,该常量的内存地址不允许修改,但是可以修改其内部的属性
  • 常量&变量的使用原则:初学的时候,尽量先用 let,只有需要变的时候,再用 var,能够更加安全
  • 初次接触 Swift 中会因为简单的 var let 误以为 Swift 中的类型非常松,其实所有变量的准确类型都是在赋值的同时自动推导的
  • Swift 是对类型要求非常严格的一门语言,一个值永远不会被自动转换成其他类型,如果要转换,必须显示转换
//常量不可以改变
let number = 10;
//变量
var number1 = 10;
number1 = 20;
//Swift可以自行做类型推断
print(number)



//定义变量(如果指定类型,一定要显性的)
var name:String = "shkljsjd"
var age:Int = 12;
var height:Float = 180.5
var 体重:Double = 12.2
var gender:Bool = true
var sex: Character = "m"
var telephone = "123456789"


//类型转换
let 整型体重 = Int(height)
print(整型体重)
var 整型电话 = Int(telephone)!
print(整型电话)

字符串

使用String的原因

  • String 是一个结构体,性能更高
    • String 目前具有了绝大多数 NSString 的功能
    • String 支持直接遍历
  • NSString 是一个 OC 对象,性能略差
  • Swift 提供了 StringNSString 之间的无缝转换
  • 在Swift中绝大多数的情况下,推荐使用 String 类型
//遍历字符串
let str = "qwerasdf"
for s in str {
    print(s)
}

//获取字符串的长度
print(str2.characters.count)

// 字符串快速拼接
let str1 = "zhangsan"
let str2 = "lisi"
let i = 10
print(str1 + str2)//可以理解成数组
print("\(str1) \(str2) \(i)")//这里可以使用\(变量名)的方式快速拼接字符串



//字符串的拼接
//这里是swift中的字符串(非常非常费劲)的拼接方法
let str: String = "zhangwu"
var subStr = str.substringWithRange(Range(start: str.startIndex, end: str.endIndex))
str.insert("1", atIndex: str2.startIndex.advancedBy(3))
//所以一把建议把swift里面的字符串转换成NSString进行拼接(删除方法同理)
let str3: NSString = "zhangsanwangwu"
print(str3.substringWithRange(NSMakeRange(0, 3)))




// 格式化字符串(这里提供了一种和OC中的stringWithFormat一样的方法,需要注意的后面的arguments是一个数组,即使一个变量也要放入数组中)
for _ in 0...10 {
    let str = String(format: "zhangsan - %04d", arguments: [arc4random_uniform(100)])
    print(str)
}

数组,字典,元组

数组

  • 如果定义数组时指定了保存对象的类型,择不能向数组中添加其他类型的内容
  • let 定义的数组是不可变的
  • var 定义的数组是可变的
// 数组中保存的都是字符串
let arr = ["zhangsan", "lisi"]

// 数组中保存的是 NSObject
let arr1 = ["zhangsan", 1]

// 添加元素
array.append("lisi")

//更新
array[0] = "zhangwu"

// 删除元素
array.removeAtIndex(1)

// 拼接数组
var array2 = [String]()
array2.append("1")
array2.append("2")
array += array2

字典

// 定义并实例化字典(这种类型是开发中常用的类型)
var dict = [String: AnyObject]()
//添加(更新)
dict["name"] = "zhangsan"
dict["age"] = 18

// 删除
dict.removeValueForKey("age")

// 合并字典
var dict2 = ["name": "wangwu", "age": 80, "title": "boss"]
for (k, v) in dict2 {
    dict.updateValue(v, forKey: k)
}

元组

//元组(tuple)(可以放任意类型)
//不定义标记
let student = ("1",1,1.1,[1],[1:1])
//访问元组元素
print(student.4)
//定义标记
let student1 = (姓名:"小明",性别:"W",年龄:[19,12,20])
//访问元组元素
print(student1.年龄[1])
print(student1.2[1])
  • 总结 :
    • 数组[index,value]:里面放着两种属性,一种是索引,一种是元素,数组中放着的只有元素,我们可以通过索引找到元素
    • 字典[key,value]:和oc中一样都放着键值对,可以通过key访问value
    • 元祖[标记,value]:可以看做是数组和字典的结合体,里面的标记可以不定义(默认像数组中的index),可以定义(就像字典中的key,但是字典中的key是有类型的,标记是无类型的)

循环,遍历,switch,枚举

循环和遍历

//whlie
while false
{

}
//类似于do...while
repeat
{

}while false
// 循环
for var i = 0; i < 10; i++ {
    print(i)
}
// 遍历 0 ~ 9(省略号之间不能有空格)
for i in 0..<10 {
    print(i)
}

// 遍历 0 ~ 10(省略号之间不能有空格)
for i in 0...10 {
    print(i)
}

// 特殊写法(如果不关心循环本身的索引,可以用通配符'_'忽略)
for _ in 0...10 {
    print("hello")
}


//数组的遍历
var studentArr = [1,2,3,4,5,6,7,8,9]
for item in studentArr
{
    print("item = \(item)")
}
//可以遍历数组中的所以和元素(间接用到了元组的特性)
for(index,value)in studentArr.enumerate()
{
    print("index =\(index)   value = \(value)")
}
//字典的遍历(同样间接用到了元组的特性)
var studentDic = ["姓名":"张三","爱好":"男"�"]
for (key,value)in studentDic
{
    print("key = \(key)  value = \(value)")
}

switch和枚举

//swtich(自带break,可以重复,但是找到一个就不会找第二个)
var name1 = "小明"
switch name1
{
    case "小明":print(name1)
    //要想要自带贯穿效果(重复之后也继续寻找)加fallthrough关键字
    fallthrough
    case "小明":print(name1)
    //一定要包含所有条件
    default: print("不存在")
}
//case可以写区间
var age1 = 12
switch age1 {
case 10...15:
    print("a")
default:
    print("默认")
}
//当age2 == 15成立的时候把age2赋给age
var age2 = 15
switch age2{
case let age where age2 == 15:
    print("age = \(age)")
default: break
}
//遍历元祖
var studentTuple = (姓名:"张三",性别:"男",年龄:12)
switch studentTuple
{
case ("张三","男",12):
    print("找对了")
case (_,_,12):
    print("找对了")//只要一个条件成立就可以进
default:
    break
}

//枚举(和oc一样默认初始值是0,如果修改初始值的话需要制指定类型,swift的枚举创建必须要带case)
enum season :Int
{
    case spring = 2
    case summer
    case autumn
    case winter
}
print(season.autumn)
//打印枚举值的值
print(season.autumn.rawValue)

var today = season.summer
//筛选枚举
switch today
{
    case.spring:print("春天")
    case.summer:print("夏天")
    case.autumn:print("秋天")
    case.winter:print("冬天")
}
//枚举也可以这样定义(case后面跟着多个元素,枚举值的类型也可以是String类型)
enum City:String
{
    case 北京 = "北京",上海
    case 石家庄,武汉
    case 青岛
}

函数

//函数
//无参无返回
func func1()
{
    print("无参无返回值")
}
//无参有返回
func func2()->String
{
    print("无参有返回值")
    return "小明"
}
//有参无返回
func func3 (a :String)
{
    print("有参无返回值")
}
//有参有返回
func func4 (a:Int)->String
{
    print("有参有返回值")
    return String(a)
}
//函数调用
func1()
func2()
func3("123")
func4(1)

//不定参数(这点与oc中的不大一样,如果传入的参数不固定可以这样写)
func add(a:Int...)->Int
{
    var result = 0
    for item in a
    {
        result += item
    }
    return result
}
//调用的时候传入的参数就是不固定的
print(add(1,2,3,4))
//返回值是多个参数
func func5()->(Int,String)
{
    return(1,String(123))
}
//交换
var m = 1
var n = 2
//变成指针(inout)(只有改变指针才能达到换值的目的)
//xy是外部参数,ab是内部参数,系统默认第一个不会帮我们省略,以后的参数会帮我们省略,所以要将x写出来,但是y可以省略
func change(inout x a:Int,inout y b:Int)
{
    let temp = a
    a = b
    b = temp
}
change(x: &m, y: &n)

结构体和类

  • Swift要求类和结构体中的存储属性(非lazy)在对象初始化完毕后必须有值

结构体

  • Swift里面的结构体和oc中的不太一样,苹果官方更推荐在开发中使用结构体,Swift中的结构体更像类,可以定义属性和方法
  • Swift中的结构体是值类型,也就是说在赋值的时候是拷贝一块内存空间,类似于oc中的深拷贝
  • Swift中的结构体不可以继承
struct Father
{
    init ()
    {
        print("______")
    }
}

//结构体
struct Person{
    //存储属性(和@property一样)
    var name:String!
    var age:NSInteger!
    //计算属性(不会存值,依赖于其他存储属性,没有存储空间)
    var fatherAge:NSInteger
        {
            set {
                age = newValue - 20
            }
            get {
               return age + 20
            }
        }
    //初始化方法
    init()
    {
        print("初始化方法")
    }
    //自定义初始化方法
    init(name:String,age:NSInteger)
    {
        self.name = name
        self.age = age
    }
    //懒加载属性(用到时在加载)
   lazy var father:Father = Father()
    //类属性
    static var Arr = Array()
    //对象方法
    func eat(){
        print("吃饭")
    }
    //类方法
    static func happy() {
        print("类方法happy")
    }
}

  • 类可以继承
  • 类是引用类型,赋值的过程是复制的指针,两个对象同时指向同一块内存空间,修改一个影响另一个,类似于浅拷贝
class Person1:NSObject
{
//重写父类的方法必须用关键字override
    override init()
    {
        print("初始化人")
    }
}
class dog: NSObject
{
    //存储属性
    var name:NSString!
    var age:NSInteger!
    //计算属性
    var fatherAge:NSInteger{
        set{
            age = newValue / 10
        }
        get {
             return age * 10
        }
    }
    //懒加载属性
    lazy var person:Person1 = Person1()
    //类属性
    static var arr = Array()
    //类方法 (class和static都可以创建类方法,唯一的区别是用static修饰的类,其子类不可以重写该类的方法)
    static func eat()
    {
        print("吃")
    }
    //对象方法
    func happy()
    {
        print("happy")
    }
    //自定义初始化方法
    init(name:String,age :NSInteger)
    {
        self.name  = name
        self.age = age
    }

}

protocol和extension

  • 在swift中协议和oc的区别不是很大,而extension更像是oc中的category,extension不但可以给类扩展,也可以给协议扩展

protocol

  • swift中的协议把可选协议个必须实现的协议分开
//必须实现的协议
protocol PersonDelegate
{
    //对象方法
    func numberOfDog()->String
    // 类方法
    static func numberOfDog()
    //属性
    var gender:String{get set}
    //类属性
    static var classRoom:String{ get set}
}

//可选协议
@objc protocol DogDelegate{
    optional var name:String{set get }
    //方法
    optional func eat()->String
}

extension

  • 正因为swift中的extension有这个特性,所以开发过程中我们可以充分利用extension的特性可以把我们的项目模块化(例如创建tableView的时候,两个代理可以用extension写出来)
//扩展
extension Person {
    func text (){
        print("asda")
    }
}
//创建一个类
class Student:NSObject
{
    var delegate:DogDelegate?

    override init() {
        super.init()
        self.delegate = self
    }
//    func eat() -> String {
//        return "123"
//    }
}

extension Student : DogDelegate
{
    func eat() -> String {
        return "123"
    }
}

闭包

  • swift中的闭包类似于oc中的block
  • 闭包表达式的类型和函数的类型一样(也就是in之前的部分)
  • in关键字的目的是便于区分返回值和执行语句
  • 关于闭包表达式的优化
    • 1.类型优化, 由于函数中已经声明了闭包参数的类型, 所以传入的实参可以不用写类型
    • 2.返回值优化, 同理由于函数中已经声明了闭包的返回值类型,所以传入的实参可以不用写类型
    • 3.参数优化, swift可以使用$索引的方式来访问闭包的参数, 默认从0开始
//闭包
var block :(Int->Void)?

//实现
block = {(a:Int) in
    return a
}
block!(0)

//第二种写法(可以省略,$0第一个参数,$1代表第二个参数)
var bb:(Int,String)->String
bb = {
    return $1
}
bb(1,"2")
//闭包作为函数回调
func eat(block:(a:Int)->(Int))->Int
{
    return block(a: 1)
}

eat { (a) -> (Int) in
    return a
}

你可能感兴趣的:(Swift)