swift的基本语法

Posted 萧家大公子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift的基本语法相关的知识,希望对你有一定的参考价值。

一 swift中的三大特性(重载;继承;多态)

1 继承

—-> 1.1 举个例子来说明 : 创建一个Person类,并且再创建一个老师和学生类,同时老师和学生类都继承Person类
//创建一个类
class Person 
    var name = ""
    var age = 0
    //函数
    func runing() 
        print("人在跑步")
    
    func study() 
        print("人在学习")
    
—-> 1.2 学生类 :
//继承
class Student : Person 
    var sno : Int = 0
    //重写父类的方法
    override func study() 
     print("学生在敲代码")
    

    override init() 
        super.init(name: "", age: 20)
    
—-> 1.3 继承于Person的老师类
class Teacher: Person 
    //重写: 子类对父类的方法不满意,重写进行实现
    override func study() 
        print("老师在备课")
    
—-> 1.4 创建各自的对象并且调用方法
//创建对象
let stu = Student()
stu.sno = 110
stu.name = "xaiofeng"
stu.age = 19

stu.runing()
stu.study()

let tea = Teacher()
tea.study()

2 重载

—-> 2.1 重载条件 : 1> 参数的类型不同 2> 参数的个数不同 (满足其一就可以)
class MathTool 
    func sum(num1 : Int, num2 : Int) ->Int 
        return num1 + num2
    
    func sum(num1 : Int, num2 : Int, num3 : Int) ->Int 
        return num1 + num2 + num3
    
    func sum(num1 : Int, num2 : Int, num3 : Int, num4 : Int) ->Int 
        return num1 + num2 + num3 + num4
    


let mathTool = MathTool()
—-> 2.2 解读重载 : 在OC中我们是不能定义完全相同的方法名,即使参数不同也是不能定义的,但是在swift中可以,但是必须满足条件,并且满足其一就可以.由上面的代码我们可以看出: 参数类型相同;函数名称相同;仅仅不同的是参数的个数,这也是满足条件的.

3 多态

—-> 3.1 条件 : 1> 一定有继承 2> 一定有方法的重写 3> 一定是父类的指针指向子类的对象
func studentInNight(p : Person) 
    p.study()

studentInNight(stu)
studentInNight(tea)

4 补充(重写)

—-> 4.1 重写原因 : 子类对父类方法不满意,不能实现需求,子类通过重写方法来实现
—-> 4.2 重写的关键字 : override(必须要在函数的前面加上这个关键字)
—-> 4.3 特殊例子 : 创建一个不继承NSObject的类,设计构造方法,不需要加上override关键字
class Person 
    var name = ""
    var age = 0
    //函数
    func runing() 
        print("人在跑步")
    
    func study() 
        print("人在学习")
    
    //如果该类继承了NSObject,那么就必须在init前面加上override,因为init是父类的方法,这样做事属于重写
    init() 
    
    //设计构造方法
    init(name : String, age : Int) 
        self.name = name
        self.age = age
    

二 swift中的循环引用

1 Swift和OC一样,采用自动引用计数来管理内容

—-> 1.1 当有一个强引用指向某一个动向时,该对象的引用计数会自动+1
—-> 1.2 当该强引用消失时,引用计数会自动-1
—-> 1.3 当引用计数为0时,该对象会被销毁
—-> 1.4 在通常情况下,ARC是会自动帮助我们管理内存的

2 简单循环引用实例 : 直接创建一个Person类

class Person 
    var name = ""
    deinit 
        print("Person-----deinit")
    

//创建类对应的对象
var person : Person? = Person()
—-> 2.1 用图解析 不打印原因

—-> 2.2 解决这种原因 : 让person指向空

2 实例 : Person有一本书,书有一个主人(owner)

//定义两个类
class Person 
    var name = ""
//    person有一本书
    var book : Book?
    deinit 
        print("Person-----deinit")
    


class Book 
    var price = 0.0
    //书有一个主人
    var owner : Person?
    deinit 
        print("Book -- deinit")
    

//创建类对应的对象
var person : Person? = Person()
var book : Book? = Book()
—-> 2.1 deinit并不会打印出结果
—-> 2.2 循环引用示意图:

—-> 2.3 此时你会发现计算将person = nil;book = nil都指向空,都不能解决问题,如下示意图

—-> 2.4 解决问题 : 让互相指向的其中一个指针变成弱指针就可以

—-> 2.5 需要写入的代码(满足其中一个就可以)
weak var book : Book?
unowned var book : Book = Book()

三 swift中的可选链

1 可选链的概念

—-> 1.1 它的可选性体现于请求或调用的目标当前可能为空(nil)
—-> 1.1.1 如果可选的目标有值,那么调用就会成功;
—-> 1.1.2 如果选择的目标为空(nil),则这种调用将返回空(nil)
—-> 1.2 多次调用被链接在一起形成一个链,如果任何一个节点为空(nil)将导致整个链失效。

2 可选链的使用

—-> 2.1 在可选类型后面放一个问号,可以定义一个可选链。
—-> 2.2 这一点很像在可选值后面放一个叹号来强制拆得其封包内的值
—–> 2.2.1 它们的主要的区别在于当可选值为空时可选链即刻失败
—–> 2.2.2 然而一般的强制解析将会引发运行时错误。因为可选链的结果可能为nil,可能有值.因此它的返回值是一个可选类型.
—–> 2.2.3 可以通过判断返回是否有值来判断是否调用成功 : 1> 有值,说明调用成功 2> 为nil,说明调用失败

3 例子 : 人有一只狗,狗有一个玩具(toy),玩具有一个价格(price)

class Person 
    var name = ""
    var dog : Dog?


class Dog 
    var name = ""
    var toy : Toy?


class Toy 
    var price  : Double = 0.0 
        didSet 
            print(price)
        
    

    //玩具有一个具体行为
    func rotating() 
        print("玩具在转圈")
    

//创建对象
let person : Person = Person()
person.name = "xiaofeng"

let dog : Dog = Dog()
dog.name = "bigYellowDog"

let toy : Toy = Toy()
toy.price = 1.0

//让对象之间产生关系
person.dog = dog
dog.toy = toy
—-> 3.1 需求一 : 给玩具赋值一个新值
第一种方式 :
person.dog!.toy!.price = 50.0
解析一 : 该方法也是可以赋值的,但是比较危险,因为并不能确定dog!和toy!一定有值,如果强制解包,返回的是nil,就会造成程序崩溃
第二种方式 : (推荐使用可选链–>比较安全)
person.dog?.toy?.price = 50.0
解析二 : 1.每一个可选进行判断,判断是否有值,如果有其中一个没有值,那么整个表达式返回一个nil 2.如果所有的可选类型都有值,那么整个表达式返回对应的类型,就可以给类型进行赋值
3.2 需求二 : 取出狗对象玩具的价格
第一种方法 :
let price = person.dog!.toy!.price
解析一 : 该方法不安全,很有可能什么都去不到,返回一个nil,程序会崩溃
第二种方式 : (推荐使用可选链–>比较安全)
let price1 = person.dog?.toy?.price
print(price1)
解析二 : 1.判断所有的可选类型是否有值,如果有其中一个没有值,那么整个可选链返回一个nil 2.如果可选类型都有值,那么返回一个具体的值
3.3 需求三 : 调用方法
第一种 : (也是可以实现的,但是比较麻烦)
person.dog!.toy!.rotating()
if let dog = person.dog 
    if let toy = dog.toy 
        toy.rotating()
    
第二种 : 一句代码搞定
person.dog?.toy?.rotating()
解析二 : 1.如果可选类型中有一个没有值,那么该方法就不会执行 2.反之,如果可选类型都有值,那么就会执行该方法

四 协议

1 协议的格式 : 协议的定义方式与类,结构体,枚举的定义都非常相似

protocol SomeProtocol 
    // 协议方法

2 遵守协议的格式

class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol 
    // 类的内容
    // 实现协议中的方法

3 协议的具体代码

—-> 3.1 定义协议
//定义协议
protocol CrazySportProtocol 
    func jumping()
    func jumpingSan()
—-> 3.2 协议之间的继承关系
//协议之间的继承
protocol SportProtool : CrazySportProtocol 
    func playBasketball()
    func playFootball()
—-> 3.3 准守协议和实现协议中的方法(默认遵守了协议,就必须实现协议中的方法)
//创建类遵守协议
class Person : SportProtool 
    //遵守了协议就必须实现协议中的方法
    func jumping() 
        print("蹦极")
    
    func jumpingSan() 
        print("跳伞")
    
    func playBasketball() 
        print("打篮球")
    
    func playFootball() 
        print("踢足球")
    
—-> 3.4 创建对象调用方法
//创建对象调用方法
var person = Person()
person.jumpingSan()
person.jumping()
person.playBasketball()
person.playFootball()
—-> 3.5 代理在协议中的实现
//定义协议
protocol BuyTicketDelegate : class 
    func buyTicketing()


//创建类
class Person 
    var name = ""
    //设置代理
    weak var delegate : BuyTicketDelegate?
    func goToBeiJing() 
        //使用代理调用对应的方法
//        delegate?.buyTicketing()
        print("坐火车去北京")
    


//定义一个类,并且遵守协议
class YellowCattle : BuyTicketDelegate 
    //将人设置里面的属性
    var vipPerson : Person?
    //实现协议中的方法
    func buyTicketing() 
        print("黄牛帮你买了一张票")
    


//创建对象
let person = Person()
person.name = "xiaofeng"

//创建黄牛对象
let huangniu = YellowCattle()
huangniu.vipPerson = person

//将黄牛设置为代理
person.delegate = huangniu
person.goToBeiJing()
—-> 3.6 协议方法的可选择性(在swift中是没有协议可选择实现的,但是我们可以通过oc的方法来达到可选择实现的目的)
//将上objc和optional就代表了可以选择的实现
@objc
protocol SportsProtocol 
   optional func jumping()
   optional func jumpingSan()


class Person1 : SportsProtocol 
    @objc func jumping() 
        print("蹦极")
    

let p = Person1()
p.jumping()

五 闭包

1 闭包简介

—-> 1.1 闭包和OC中的block非常相似
—-> —–OC中的block是匿名的函数
—–>—–Swift中的闭包是一个特殊的函数
—–>—–block和闭包都经常用于回调

2 block的使用

—-> 2.1 block的用法回顾
定义网络请求类 :
@interface HttpTool : NSObject
- (void)loadRequest:(void (^)())callBackBlock;
@end

@implementation HttpTool
- (void)loadRequest:(void (^)())callBackBlock

    dispatch_async(dispatch_get_global_queue(0, 0), ^
        NSLog(@"加载网络数据:%@", [NSThread currentThread]);

        dispatch_async(dispatch_get_main_queue(), ^
            callBackBlock();
        );
    );

@end
进行网络请求,请求到数据后利用block进行回调
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

    [self.httpTool loadRequest:^
        NSLog(@"主线程中,将数据回调.%@", [NSThread currentThread]);
    ];
block写法总结:
block的写法:
    类型:
    返回值(^block的名称)(block的参数)

    值:
    ^(参数列表) 
        // 执行的代码
    ;

3 闭包代替block使用

定义网络请求的类
class HttpTool: NSObject 
    func loadRequest(callBack : ()->())
        dispatch_async(dispatch_get_global_queue(0, 0))  () -> Void in
            print("加载数据", [NSThread.currentThread()])

             dispatch_async(dispatch_get_main_queue(),  () -> Void in
                callBack()
             )
        
    
进行网络请求,请求到数据后利用闭包进行回调
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
        // 网络请求
        httpTool.loadRequest ( () -> () in
            print("回到主线程", NSThread.currentThread());
        )
    
闭包写法总结:
闭包的写法:
    类型:(形参列表)->(返回值)
    技巧:初学者定义闭包类型,直接写()->().再填充参数和返回值

    值:
    
        (形参) -> 返回值类型 in
        // 执行代码
    

4 闭包的简写

—-> 4.1 如果闭包没有参数,没有返回值.in和in之前的内容可以省略
httpTool.loadRequest(
        print("回到主线程", NSThread.currentThread());
    )
—-> 4.2 尾随闭包写法:如果闭包是函数的最后一个参数,则可以将闭包写在()后面;如果函数只有一个参数,并且这个参数是闭包,那么()可以不写
httpTool.loadRequest() 
        print("回到主线程", NSThread.currentThread());
    
// 开发中建议该写法
httpTool.loadRequest 
        print("回到主线程", NSThread.currentThread());
    

六 懒加载

1 OC中有懒加载,而在swift中也存在懒加载.苹果希望我们对所有的对象只有在使用的时候才真在的加到内存中,这样能大大的减少了内存的消耗.

2 懒加载格式

lazy var 变量: 类型 =  创建变量代码 ()

3 具体实例

—-> 3.1 懒加载写法一:(不推荐)
lazy var names : [String] = 
        return ["xiaofeng", "it", "nb"]
    ()

    lazy var btn : UIButton = 
        let tempBtn = UIButton()
        tempBtn.setTitle("按钮", forState: .Normal)

        return tempBtn
    ()
—-> 3.2 懒加载写法二 : (推荐)
lazy var button : UIButton = UIButton()

七 访问权限(下面只介绍概念)

1 private : 只能在当前文件中访问,不能在其他文件中访问

2 internal : 内部的,修饰整个项目,在整个项目中都可以进行访问,并且默认情况下修饰就是internal

3 public : 是可以跨框架访问

八 异常处理

1 try : 手动处理异常,并且获取在调用方法过程中到底产生了怎么样的异常

2 try? : 自己不处理异常,让系统帮助我们处理

系统如何处理:

—-> 2.1 如果该方法产生了异常,那么系统会将该方法的返回值为nil
—-> 2.2 如果该方法没有产生异常,那么系统会返回对应的类型结果

3 try! : 告诉系统这个方法不会产生异常 –> 注意:如果该方法产生了异常,那么程序会崩溃(不推荐)

九 oc和swift之间混编(给上具体步骤,这里就不简要说明了)

1 swift中调用OC代码

—-> 1.1 创建一个swift文件
—-> 1.2 在swift文件中创建一个oc类(点击don’t bridge)
—-> 1.3 创建一个桥接文件(仅仅是一个头文件)
—-> 1.4 配置 点击工程文件–> Bulid Setting –>brid –>双击objc填入bridge的文件路径

2 OC中调用swift代码

—-> 2.1 创建一个OC项目(标题不能写”_”,或者其他符号,使用全英文)
—-> 2.2 创建一个swift文件(点击don’t bridge)
—-> 2.3 导入一个头文件(项目名称 -swift.h)
—-> 2.4 swift都需要使用public修饰(方法/属性)

十 总结

1 swift语法基本已经介绍的差不多了,其中还有不足,一时间没有想到,希望看到我博客的人给点意见,让我知道还有那些没有介绍.明天给大家带来一个小小的demo.(纯swift代码实现)

2 最后大家如果觉得我写大博客还行,麻烦大家给点意见,好的坏的我都接受,麻烦大家关注我的官方博客,谢谢!!!!

以上是关于swift的基本语法的主要内容,如果未能解决你的问题,请参考以下文章

Swift4.2~数组和字典(Array, Dictionary)基本类型转换

关于人脸识别,Taylor Swift是认真的

基本语法——Caché

Swift 基本语法

Swift基本语法

Swift入门——基本的语法