Swift-知识点

作者: iiNico | 来源:发表于2016-11-05 00:55 被阅读436次

    协议

    协议支持多继承

    class SomeClass: SomeSuperClass, FirstProtocol,  AnotherProtocol {
        // 类的内容
       // 实现协议中的方法
    }
    
    • 类 结构体 枚举都可以遵守协议
    // 1.定义协议
    protocol SportProtocol {
        func playBasketball()
        func playFootball()
    }
    // 2.遵守协议
    // 注意:默认情况下在swift中所有的协议方法都是必须实现的,如果不实现,则编译器会报错
    class Person : SportProtocol {
        var name : String?
        var age : Int = 0
    
        // 实现协议中的方法
        func playBasketball() {
            print("人在打篮球")
        }
    
        func playFootball() {
            print("人在踢足球")
        }
    }
    

    协议之间的继承

    protocol CrazySportProtocol {
        func jumping()
    }
    
    protocol SportProtocol : CrazySportProtocol {
        func playBasketball()
        func playFootball()
    }
    

    协议继承用于代理设计模式

    protocol BuyTicketProtocol {
        func buyTicket()
    }
    
    class Person {
        // 1.定义协议属性
        var delegate : BuyTicketProtocol
    
        // 2.自定义构造函数
        init (delegate : BuyTicketProtocol) {
            self.delegate = delegate
        }
    
        // 3.行为
        func goToBeijing() {
            delegate.buyTicket()
        }
    }
    
    
    class HuangNiu: BuyTicketProtocol {
        func buyTicket() {
            print("买了一张火车票")
        }
    }
    
    let p = Person(delegate: HuangNiu())
    p.goToBeijing()
    
    • 代理属性,一般都是使用weak修饰
      • weak修饰的必须是类类型的对象
      • 一般要求,协议继承自NSObjectProtocol / class

    在Swift中,如果遵守了一个协议,必须要实现,协议里面所有的方法
    协议可选是OC的特性

    • @objc 修饰协议
    • @objc optional 修饰方法
    // 1.定义协议
    @objc
    protocol SportProtocol {
        func playBasketball()
    
       @objc  optional func playFootball()
    }
    
    // 2.遵守协议
    class Person : SportProtocol {
        var name : String?
        var age : Int = 0
    
        // 实现协议中的方法
        @objc func playBasketball() {
            print("人在打篮球")
        }
    }
    

    泛型

    简单的理解泛型就是一个"泛化"的类型,并不特指某一个具体的类型

    • 泛型的使用
      • 作为函数的参数或返回值


        泛型作为返回值
      • 泛型与类型的结合
        • 与结构体的结合


          与结构体结合
        • 与类的结合


          与类结合
        • 与协议的关联


          与协议关联
      • 泛型与where子句结合使用
        • 与where子句结合使用

    闭包

    • 闭包与OC中的Block非常相似
      • OC中的block是匿名的函数
      • Swift中的闭包是一个特殊的函数
      • block和闭包都是经常用于回调

    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]);
        }];
    }
    

    闭包格式

    类型    类型:(形参列表)->(返回值)
            {
    值          (形参) -> 返回值类型 in
                执行代码
            }
    

    使用闭包代替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和in之间的内容可以省略

        httpTool.loadRequest({
            print("回到主线程", NSThread.currentThread());
        })
    

    尾随闭包

    • 写法
      • 如果闭包是函数的最后一个参数,则可以将闭包写在()后面
      • 如果函数只有一个参数,并且这个参数是闭包,那么()可以不写
        httpTool.loadRequest() {
            print("回到主线程", NSThread.currentThread());
        }
    
    
        // 开发中建议该写法
        httpTool.loadRequest {
            print("回到主线程", NSThread.currentThread());
        }
    

    如果在HttpTool中有对闭包进行强引用,则会形成循环引用

    class HttpTool: NSObject {
    
        // 定义属性,来强引用传入的闭包
        var callBack : (()->())?
    
        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()
                 })
            }
    
            self.callBack = callBack
        }
    }
    在Swift中检测一个对象是否销毁,可以实现对象的deinit函数
    

    循环引用解决方案

    • 方案一

      • 使用weak,对self使用所引用
      • 但是self可能有值也可能没有值,因为weakSelf是一个可选类型,正真正使用时可以对其强制解包(该处强制捷豹没有问题,因为控制器一定存在,否则无法调用所在函数)
          // 解决方案一:
      weak var weakSelf = self
      httpTool.loadData {
          print("加载数据完成,更新界面:", NSThread.currentThread())
          weakSelf!.view.backgroundColor = UIColor.redColor()
      }
      
    • 方案二

      • 可以写在闭包中,并且闭包中用到的self都是弱引用

            httpTool.loadData {[weak self] () -> () in
        print("加载数据完成,更新界面:", NSThread.currentThread())
        self!.view.backgroundColor = UIColor.redColor()
        

      }
      ```

    • 方案三

      • 使用关键字'unowned'
      • 从行为上来说 unowned 更像OC中的unsafe_unretained
      • unowned表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个"无效的"引用,它不能是 Optional值,也不会被指向nil
      httpTool.loadData {[unowned self] () -> () in
          print("加载数据完成,更新界面:", NSThread.currentThread())
          self.view.backgroundColor = UIColor.redColor()
      }
      

      逃逸闭包 非逃逸闭包

      // @escaping 逃逸闭包
      // 可以被其他对象引用 -- 逃逸闭包
      // 默认情况下, 闭包, 是不能被其他对象引用 -- 非逃逸闭包
      

    懒加载

    • 懒加载介绍
      • 和OC不同的是swift有专门的关键字来实现懒加载
      • lazy关键字可以用于定义某一个属性懒加载
    • 格式
      • lazy var 变量:类型 = 函数名() 构造函数
        自定义函数
      • lazy var 变量:类型 = {创建变量代码}()
    • 懒加载的使用
        // 懒加载的本质是,在第一次使用的时候执行闭包,将闭包的返回值赋值给属性
        // lazy的作用是只会赋值一次
        lazy var array : [String] = {
            () -> [String] in
            return ["sz", "lmj", "lnj"]
        }()
    

    注释

    • 单行注释

      • 单行注释以 // 作为起始标记
      • // 注释内容
    • 多行注释

      • 以/*开头
      • 以*/结尾
      • 和C语言多行注释不同的是,Swift的多行注释可以嵌套多行注释
      /*
      内容
      /*
      内容
      */
      内容
      */
      
    • 文档注释

      • 格式 1

        /**
        方法的含义描述
        
        - parameter path: 路径
        
        - throws: 抛出异常
        
        - returns: 返回值
        */
        
      • 格式 2

      /// 方法的功能描述
      /// - parameter a 参数a的含义描述
      /// - parameter b 参数b的含义描述
      /// - throws: 异常描述
      /// - returns: 返回值描述
      
      • 快捷键 command + option + /

      • 格式 3

          /// 方法的功能描述
      /// * 描述1
      /// * 描述2
      /**
          描述
          描述
       */
      /// - parameter a: 参数a的含义描述
      /// - parameter b: 参数b的含义描述
      /// - throws: 异常描述
      /// - returns: 返回值描述
      
    • 分组注释

      • Swift中不可以再使用 '#pragma mark - '
      • 如果打算对代码进行分组可以使用 '//MARK:-'方式
      • MARK : //MARK: -
      • TODO : //TODO: - 需要做
      • FIXME : //FIXME:解决bug

    开启分组注释
    因为默认的话 TODO 跟 FIXME 是没有开启的,所以需要我们手动开启
    步骤 一


    步骤二


    开启注释代码 直接复制粘贴就好了

    TAGS="TODO:|FIXME:"
    echo "searching ${SRCROOT} for ${TAGS}"
    find "${SRCROOT}" \\( -name "*.swift" \\) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\\$" | perl -p -e "s/($TAGS)/ warning: \\$1/"
    

    优点:

    访问权限

    OC中的访问权限

    @private:作用范围只能在自身类
    @protected:作用范围在自身类和继承自己的子类,什么都不写,默认是此属性。
    @public:作用范围最大,在任何地方
    @package:本包内使用,跨包不可以
    
    • 注意
      • 只是用来修饰成员变量,无法修饰方法
      • @interface中的声明的成员变量默认是public,@implatation中声明的成员变量默认是private

    Swift中的访问控制模型基于模块和源文件,类这三个概念

    internal:在本模块中都可以进行访问 默认的 子类可以继承
    private:当前类私有
    fileprivate:在当前源文件中可以访问
    public:在其他模块中可以访问,但不能被override,如果修饰类,则无法继承
    open:在其他模块中可以访问,并且可以被override,如果修饰类,可以继承
    
    • 注意
      • Swift访问权限,作用与类,属性,方法等
      • Swift中的访问级别遵守一个基本原则:不可以在某个实体中定义访问级别更高的实体

    方法抛出异常

    • 异常的介绍

      • 只要我们在编程,就一定要面对错误处理的问题.
      • Swift在设计的时候就尽可能让我们明确感知错误.明确处理错误 *比如:只有使用Optional才能处理空值
      • 如何描述一个错误?
        • 在Swift里,任何一个遵从Error protocol的类型,都可以用于描述错误
        • Error是一个空的protocol,它唯一的功能,就是告诉Swift编译器,某个类用来表示一个错误.
        • 通常,我们使用一个enum来定义各种错误的可能性
    • 异常的示例

      • 当我们调用方法获取结果为nil时,你并不能确定到底参数什么错误得到了nil

      func readFileContent(filePath : String) -> String? {
      // 1.filePath为""
      if filePath == "" {
      return nil
      }

          // 2.filepath有值,但是没有对应的文件
          if filePath != "/User/Desktop/123.plist" {
              return nil
          }
      
          // 3.取出其中的内容
          return "123"
       }
       
       readFileContent("abc")
        ```
      

      使用异常对上述方法进行改进

      // 1.定义异常
      enum FileReadError : Error {
          case FileISNull
          case FileNotFound
      }
      
      // 2.改进方法,让方法抛出异常
      func readFileContent(filePath : String) throws -> String {
          // 1.filePath为""
          if filePath == "" {
      
              throw FileReadError.FileISNull
          }
      
          // 2.filepath有值,但是没有对应的文件
          if filePath != "/User/Desktop/123.plist" {
      
              throw FileReadError.FileISNull
          }
      
          // 3.取出其中的内容
          return "123"
      }
      
      
    • 处理异常的方式

      • 1 try方式,需要手动处理异常
      do {
          let result = try readFileContent("abc")
      } catch {
          print(error)
      }    
      
      • 2 try?方式,不处理异常,如果出现了异常,则返回一个nil,没有异常则返回对应的值
      // 最终返回结果为一个可选类型
      let result = try? readFileContent("abc")
      
      • try!方法,告诉系统改方法没有异常
      // 注意:如果出现了异常,则程序会崩溃
      try! readFileContent("abc")
      

    Swift调用OC

    方式一 创建OC文件时提示,点击Create Bridging Header

    方式二

    导入桥接文件的全路径

    在桥接文件中,直接导入OC的头文件,就可以使用了

    OC调用Swift

    • 注意
        1. 如果想让Swift类/方法/属性, 在OC中使用; 需要使用public关键字对类/方法/属性等进行修饰
        1. 如果是类, 必须继承自NSObject
        1. 如果是协议


    相关文章

      网友评论

        本文标题:Swift-知识点

        本文链接:https://www.haomeiwen.com/subject/ommwuttx.html