一,闭包&逃逸闭包。
定义一个闭包变量&常量,然后调用:
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);
}

