Swift一些概念定义 | 二

一,闭包&逃逸闭包。

定义一个闭包变量&常量,然后调用:

let escapingBlocks: (String) -> String = {
    (str: String) -> String in
    return str;
}
print(escapingBlocks("xxxx"));

定义一个包类型,并且初始化,然后调用:

typealias escapingBlock = (String) -> String;
let testBlock: escapingBlock = {
    (s: String) -> String in
    return "hello \(s)"
}
print(testBlock("word!"));

逃逸闭包,概念,当一个函数中将一个闭包作为参数时,当前函数执行完之后(或者函数已经返回后),还没有去执行当前闭包,那么当前的闭包就是一个逃逸闭包,可以理解为逃逸出去了,没在本函数中进行执行,例如:

//定义一个包类型
typealias escapingBlock = (String) -> String;
//然后定义一函数,参数为escapingBlock的闭包,并且是逃逸闭包,因为将其block进行了返回
func escapingFunc(blockPar: @escaping escapingBlock) -> escapingBlock {
     return blockPar;
}
//
override func viewDidLoad() {
    super.viewDidLoad()
//调用函数,接受返回的闭包。
    let escB: escapingBlock = escapingFunc(blockPar: {
        (s: String) -> String in
        return "this is my escaping by string - \(s)"
    });
//调用返回的闭包
    print(escB("是的是的。"));
//以上等价于:
    let testBlock: escapingBlock = {
        (s: String) -> String in
        return "this is my escaping by string - \(s)"
    };
    let blockByFunc = escapingFunc(blockPar: testBlock);
    print(blockByFunc("😔😔😔😔😔😔"));
}

以上的闭包作为函数的参数,没有在函数内部进行执行,直接被返回了,所以在函数参数声明的时候,用@escaping去做了声明,这就是逃逸闭包。

二,Selector。以下第一种形式已经替代了第二种形式。

//1
var sel: Selector = #selector(repeatAction(_ :));
@objc func repeatAction(_ timer:Timer) -> Void {
    print("[] [] [] [] []");
}
/*-------------------------*/
//2
override func viewDidLoad() {
   super.viewDidLoad()
   let sel: Selector = Selector(("selectorTest:"));
   self.perform(sel, with: "hello");
}
@objc func selectorTest(_ params: Any) {
    print("oh oh ",params);
}

三,中间件拦截消息,进行转发,防止循环引用。

import UIKit

class SKProxy: NSObject {
    weak var target: NSObjectProtocol?
    static func SKProxyWithTarget(_ target:NSObjectProtocol) -> SKProxy{
        let proxy = SKProxy();
        proxy.target = target;
        return proxy;
    }
    override func forwardingTarget(for aSelector: Selector!) -> Any? {
        if target?.responds(to: aSelector) == true {
            return target;
        }
        return super.forwardingTarget(for: aSelector);
    }
}
    var timer: Timer?
    @objc func repeatAction(_ timer:Timer) -> Void {
        print("[] [] [] [] []");
    }
    deinit {
        timer?.invalidate();
        timer = nil;
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        //
        let proxy: SKProxy = SKProxy.SKProxyWithTarget(self);
        timer = Timer.scheduledTimer(timeInterval: 1.0, target: proxy, selector: #selector(repeatAction(_:)), userInfo: nil, repeats: true);
}

四,判断某个对象是否有实现某个Selector(SEL):
if target?.responds(to: aSelector) == true

五,rawValue获取枚举中属性,枚举类型中的真正值,例如,UIButton中的ButtonType类型,某一个输出值为custom,那么此类型的rawValue就是0:

 public enum ButtonType : Int {
        case custom = 0
        @available(iOS 7.0, *)
        case system = 1
        case detailDisclosure = 2
}

六,Swift扩展中增加属性。

//
//  UIView+Radius.swift
//  SwiftProject
//
//  Created by skyzizhu on 2020/12/27.
//

import Foundation
import UIKit

private var cornerRadisusKey = "cornerRadisusKey";

extension UIView {

    //设置上下左右圆角
    var cornerRadisus: CGFloat {
        get{
            return objc_getAssociatedObject(self, &cornerRadisusKey) as! CGFloat;
        }
        set(newValue){
            objc_setAssociatedObject(self, &cornerRadisusKey, newValue, .OBJC_ASSOCIATION_ASSIGN);
            if newValue > 0.0 {
                setViewCornerRadisus();
            }
        }
    }
    
    private func setViewCornerRadisus() -> Void {
        let maskPath: UIBezierPath = .init(roundedRect: bounds, cornerRadius: cornerRadisus);
        let maskLayer: CAShapeLayer = CAShapeLayer();
        maskLayer.frame = bounds;
        maskLayer.path = maskPath.cgPath;
        layer.mask = maskLayer;
    }
    
    /// 使用,v.viewCornerRadisus(corners: UIRectCorner.init([.topLeft,.topRight]), cornerRadii: .init(width: 10, height: 10));
    /// - Parameters:
    ///   - corners: UIRectCorner
    ///   - cornerRadii: CGSize
    /// - Returns: NONE
    func viewCornerRadisus(corners: UIRectCorner,cornerRadii: CGSize) -> Void {
        guard (corners.rawValue != 0) else {
            return;
        }
        let maskPath: UIBezierPath = .init(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: cornerRadii);
        let maskLayer: CAShapeLayer = CAShapeLayer();
        maskLayer.frame = bounds;
        maskLayer.path = maskPath.cgPath;
        layer.mask = maskLayer;
    }
}

七,编码中判断Swift版本。

#if swift(>=4.2)
let KFRunLoopModeCommon = RunLoop.Mode.common
#else
let KFRunLoopModeCommon = RunLoopMode.commonModes
#endif

八,变量的入口+动态派发机制,可让其进行KVO监听,例如:
@objc dynamic var isKeep: Bool = false;

九,泛型的使用场景。

// 定义泛型函数,接受一个泛型参数,要求该泛型类型必须继承Animal
func AnimalRunPint<T:Animal>(animal:T) {
    animal.run()  // 继承了Animal类的子类都有run方法可以调用
}
AnimalRunPint(Dog())   // Dog run
AnimalRunPint(Cat())   // Cat run

十,subscript。
subscript,可以给任意类型(枚举、结构体、类)增加下标功能,例如:

class scriptDemoClass {
    static subscript(_ par_1:Int,_ par_2:String) -> String {
        return String(format: "%d - %@", par_1,par_2);
    }
    subscript() -> Int {
        return 33;
    }
}
//调用
let scCla:scriptDemoClass = scriptDemoClass();
let str = scriptDemoClass[1,"这是我的数组"];
print(str);
print(scCla[]);
//可通过此,封装Userdefaults,例如:
extension UserDefaults {
    static var udfs: UserDefaults {
        get {
            UserDefaults.standard;
        }
    }
    subscript(key: String) -> Any? {
        get {
            return object(forKey: key);
        }
        set {
            set(newValue, forKey: key);
        }
    }
}
//
使用:
UserDefaults.udfs["memberID"] = "1231231231";
print(UserDefaults.udfs["memberID"]!);

十一,CATransition动画,可以实现某种所想要的动画效果。

let varView = self.view.viewWithTag(101);
let tr: CATransition = CATransition();
tr.duration = 1.0;
tr.type = .moveIn;
tr.subtype = .fromBottom;
tr.startProgress = 1.0;
tr.endProgress = 0.1;
varView?.layer.add(tr, forKey: "CATransitionKey");

十二,mutating,nonmutating关键字。此两关键字只能用于struct类型中,struct为值传递,为了确保值的唯一性和完整性,方法和通过mutating,nonmutating进行修饰。
通过mutating,nonmutating关键字进行修饰的方法,可在方法内部修饰结构体的值,这里的值可理解成结构体的属性值,例如:

struct structDemo {
    var _str: String?
    var str: String {
        get{"string"}
        nonmutating set{//这里的set方法会报错,不能够修改属性_str的值
//需用mutating进行修饰,默修饰认为mutating。
            _str = newValue;
        }
    }
    mutating func change() -> Void {//这里可以修改str的值,因为mutating修饰
        str = "1212";
    }
}

十三,swift中单例创建:

class SkyObject {
    private static let obj: SkyObject = SkyObject();
    var val: Int = 0
    static func manager() -> SkyObject {
        return obj;
    }
    static func shared(params: Int) -> SkyObject {
        obj.val = params;
        return obj;
    }
}

十四,swift中的异常抛出及错误处理:

//定义错误类型
enum SKY_Error: Error
{
    case error_first
    case error_second
    case error_third
}
//标记抛出错误、异常的函数
func printerOperate(toPrint value: Int) throws -> String {
    if value == 1 {
        throw SKY_Error.error_first;
    } else if value == 2 {
        throw SKY_Error.error_second;
    } else if value == 3 {
        throw SKY_Error.error_third;
    }
    return "success";
}
/*异常处理的不同方式*/
//处理异常 - 1
do {
    let value: String = try printerOperate(toPrint: 1);
    print(value);
} catch {
    print(error);
};
//处理异常 - 2
do {
    let value: String = try printerOperate(toPrint: 2);
    print(value);
} catch {
    print(error);
}
//处理异常 - 3
do {
    let value: String = try printerOperate(toPrint: 3);
    print(value);
} catch SKY_Error.error_first {
    print("\(SKY_Error.error_first) - 错误1");
} catch SKY_Error.error_second {
    print("\(SKY_Error.error_second) - 错误2");
} catch SKY_Error.error_third {
    print("\(SKY_Error.error_third) - 错误3");
} catch {
    print("未知错误");
}
//处理异常 - 4
let value = try? printerOperate(toPrint: 0);
if let thisValue = value {
    print(thisValue);
}

Leave a Reply

Required fields are marked *